summaryrefslogtreecommitdiffstats
path: root/src/imageplugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/imageplugins')
-rw-r--r--src/imageplugins/Makefile.am5
-rw-r--r--src/imageplugins/adjustcurves/Makefile.am33
-rw-r--r--src/imageplugins/adjustcurves/adjustcurves.cpp677
-rw-r--r--src/imageplugins/adjustcurves/adjustcurves.h143
-rw-r--r--src/imageplugins/adjustcurves/adjustcurvestool.cpp659
-rw-r--r--src/imageplugins/adjustcurves/adjustcurvestool.h145
-rw-r--r--src/imageplugins/adjustcurves/digikamimageplugin_adjustcurves.desktop52
-rw-r--r--src/imageplugins/adjustcurves/digikamimageplugin_adjustcurves_ui.rc20
-rw-r--r--src/imageplugins/adjustcurves/imageplugin_adjustcurves.cpp70
-rw-r--r--src/imageplugins/adjustcurves/imageplugin_adjustcurves.h56
-rw-r--r--src/imageplugins/adjustlevels/Makefile.am34
-rw-r--r--src/imageplugins/adjustlevels/adjustlevels.cpp913
-rw-r--r--src/imageplugins/adjustlevels/adjustlevels.h153
-rw-r--r--src/imageplugins/adjustlevels/adjustlevelstool.cpp901
-rw-r--r--src/imageplugins/adjustlevels/adjustlevelstool.h160
-rw-r--r--src/imageplugins/adjustlevels/digikamimageplugin_adjustlevels.desktop52
-rw-r--r--src/imageplugins/adjustlevels/digikamimageplugin_adjustlevels_ui.rc20
-rw-r--r--src/imageplugins/adjustlevels/imageplugin_adjustlevels.cpp71
-rw-r--r--src/imageplugins/adjustlevels/imageplugin_adjustlevels.h56
-rw-r--r--src/imageplugins/antivignetting/Makefile.am34
-rw-r--r--src/imageplugins/antivignetting/antivignetting.cpp149
-rw-r--r--src/imageplugins/antivignetting/antivignetting.h62
-rw-r--r--src/imageplugins/antivignetting/antivignettingtool.cpp378
-rw-r--r--src/imageplugins/antivignetting/antivignettingtool.h92
-rw-r--r--src/imageplugins/antivignetting/digikamimageplugin_antivignetting.desktop50
-rw-r--r--src/imageplugins/antivignetting/digikamimageplugin_antivignetting_ui.rc20
-rw-r--r--src/imageplugins/antivignetting/imageeffect_antivignetting.cpp380
-rw-r--r--src/imageplugins/antivignetting/imageeffect_antivignetting.h79
-rw-r--r--src/imageplugins/antivignetting/imageplugin_antivignetting.cpp70
-rw-r--r--src/imageplugins/antivignetting/imageplugin_antivignetting.h57
-rw-r--r--src/imageplugins/blurfx/Makefile.am34
-rw-r--r--src/imageplugins/blurfx/blurfx.cpp1445
-rw-r--r--src/imageplugins/blurfx/blurfx.h191
-rw-r--r--src/imageplugins/blurfx/blurfxtool.cpp402
-rw-r--r--src/imageplugins/blurfx/blurfxtool.h93
-rw-r--r--src/imageplugins/blurfx/digikamimageplugin_blurfx.desktop49
-rw-r--r--src/imageplugins/blurfx/digikamimageplugin_blurfx_ui.rc20
-rw-r--r--src/imageplugins/blurfx/imageeffect_blurfx.cpp388
-rw-r--r--src/imageplugins/blurfx/imageeffect_blurfx.h80
-rw-r--r--src/imageplugins/blurfx/imageplugin_blurfx.cpp70
-rw-r--r--src/imageplugins/blurfx/imageplugin_blurfx.h56
-rw-r--r--src/imageplugins/border/Makefile.am34
-rw-r--r--src/imageplugins/border/border.cpp393
-rw-r--r--src/imageplugins/border/border.h151
-rw-r--r--src/imageplugins/border/bordertool.cpp668
-rw-r--r--src/imageplugins/border/bordertool.h123
-rw-r--r--src/imageplugins/border/digikamimageplugin_border.desktop50
-rw-r--r--src/imageplugins/border/digikamimageplugin_border_ui.rc20
-rw-r--r--src/imageplugins/border/imageeffect_border.cpp667
-rw-r--r--src/imageplugins/border/imageeffect_border.h109
-rw-r--r--src/imageplugins/border/imageplugin_border.cpp71
-rw-r--r--src/imageplugins/border/imageplugin_border.h57
-rw-r--r--src/imageplugins/border/patterns/Makefile.am5
-rw-r--r--src/imageplugins/border/patterns/chalk-pattern.pngbin0 -> 18994 bytes
-rw-r--r--src/imageplugins/border/patterns/craters-pattern.pngbin0 -> 17350 bytes
-rw-r--r--src/imageplugins/border/patterns/dried-pattern.pngbin0 -> 20634 bytes
-rw-r--r--src/imageplugins/border/patterns/granit-pattern.pngbin0 -> 20766 bytes
-rw-r--r--src/imageplugins/border/patterns/ice-pattern.pngbin0 -> 18371 bytes
-rw-r--r--src/imageplugins/border/patterns/leaf-pattern.pngbin0 -> 63395 bytes
-rw-r--r--src/imageplugins/border/patterns/marble-pattern.pngbin0 -> 14715 bytes
-rw-r--r--src/imageplugins/border/patterns/paper-pattern.pngbin0 -> 21785 bytes
-rw-r--r--src/imageplugins/border/patterns/parque-pattern.pngbin0 -> 9835 bytes
-rw-r--r--src/imageplugins/border/patterns/pine-pattern.pngbin0 -> 2868 bytes
-rw-r--r--src/imageplugins/border/patterns/pink-pattern.pngbin0 -> 14947 bytes
-rw-r--r--src/imageplugins/border/patterns/rain-pattern.pngbin0 -> 15876 bytes
-rw-r--r--src/imageplugins/border/patterns/rock-pattern.pngbin0 -> 39841 bytes
-rw-r--r--src/imageplugins/border/patterns/stone-pattern.pngbin0 -> 57784 bytes
-rw-r--r--src/imageplugins/border/patterns/wall-pattern.pngbin0 -> 19335 bytes
-rw-r--r--src/imageplugins/border/patterns/wood-pattern.pngbin0 -> 11893 bytes
-rw-r--r--src/imageplugins/channelmixer/Makefile.am34
-rw-r--r--src/imageplugins/channelmixer/channelmixer.cpp784
-rw-r--r--src/imageplugins/channelmixer/channelmixer.h133
-rw-r--r--src/imageplugins/channelmixer/channelmixertool.cpp774
-rw-r--r--src/imageplugins/channelmixer/channelmixertool.h138
-rw-r--r--src/imageplugins/channelmixer/digikamimageplugin_channelmixer.desktop51
-rw-r--r--src/imageplugins/channelmixer/digikamimageplugin_channelmixer_ui.rc20
-rw-r--r--src/imageplugins/channelmixer/imageplugin_channelmixer.cpp71
-rw-r--r--src/imageplugins/channelmixer/imageplugin_channelmixer.h56
-rw-r--r--src/imageplugins/charcoal/Makefile.am34
-rw-r--r--src/imageplugins/charcoal/charcoal.cpp249
-rw-r--r--src/imageplugins/charcoal/charcoal.h56
-rw-r--r--src/imageplugins/charcoal/charcoaltool.cpp202
-rw-r--r--src/imageplugins/charcoal/charcoaltool.h82
-rw-r--r--src/imageplugins/charcoal/digikamimageplugin_charcoal.desktop50
-rw-r--r--src/imageplugins/charcoal/digikamimageplugin_charcoal_ui.rc20
-rw-r--r--src/imageplugins/charcoal/imageeffect_charcoal.cpp193
-rw-r--r--src/imageplugins/charcoal/imageeffect_charcoal.h69
-rw-r--r--src/imageplugins/charcoal/imageplugin_charcoal.cpp72
-rw-r--r--src/imageplugins/charcoal/imageplugin_charcoal.h57
-rw-r--r--src/imageplugins/colorfx/Makefile.am34
-rw-r--r--src/imageplugins/colorfx/colorfxtool.cpp699
-rw-r--r--src/imageplugins/colorfx/colorfxtool.h136
-rw-r--r--src/imageplugins/colorfx/digikamimageplugin_colorfx.desktop40
-rw-r--r--src/imageplugins/colorfx/digikamimageplugin_colorfx_ui.rc20
-rw-r--r--src/imageplugins/colorfx/imageeffect_colorfx.cpp690
-rw-r--r--src/imageplugins/colorfx/imageeffect_colorfx.h131
-rw-r--r--src/imageplugins/colorfx/imageplugin_colorfx.cpp73
-rw-r--r--src/imageplugins/colorfx/imageplugin_colorfx.h57
-rw-r--r--src/imageplugins/coreplugin/Makefile.am52
-rw-r--r--src/imageplugins/coreplugin/autocorrectiontool.cpp438
-rw-r--r--src/imageplugins/coreplugin/autocorrectiontool.h128
-rw-r--r--src/imageplugins/coreplugin/bcgtool.cpp366
-rw-r--r--src/imageplugins/coreplugin/bcgtool.h115
-rw-r--r--src/imageplugins/coreplugin/blurtool.cpp169
-rw-r--r--src/imageplugins/coreplugin/blurtool.h81
-rw-r--r--src/imageplugins/coreplugin/bwsepiatool.cpp1177
-rw-r--r--src/imageplugins/coreplugin/bwsepiatool.h193
-rw-r--r--src/imageplugins/coreplugin/digikamimageplugin_core.desktop47
-rw-r--r--src/imageplugins/coreplugin/digikamimageplugin_core_ui.rc56
-rw-r--r--src/imageplugins/coreplugin/hsl/Makefile.am26
-rw-r--r--src/imageplugins/coreplugin/hsl/hsltool.cpp453
-rw-r--r--src/imageplugins/coreplugin/hsl/hsltool.h126
-rw-r--r--src/imageplugins/coreplugin/hsl/hspreviewwidget.cpp126
-rw-r--r--src/imageplugins/coreplugin/hsl/hspreviewwidget.h64
-rw-r--r--src/imageplugins/coreplugin/hsl/imageeffect_hsl.cpp428
-rw-r--r--src/imageplugins/coreplugin/hsl/imageeffect_hsl.h116
-rw-r--r--src/imageplugins/coreplugin/iccprooftool.cpp1310
-rw-r--r--src/imageplugins/coreplugin/iccprooftool.h209
-rw-r--r--src/imageplugins/coreplugin/imageeffect_autocorrection.cpp431
-rw-r--r--src/imageplugins/coreplugin/imageeffect_autocorrection.h128
-rw-r--r--src/imageplugins/coreplugin/imageeffect_bcg.cpp350
-rw-r--r--src/imageplugins/coreplugin/imageeffect_bcg.h110
-rw-r--r--src/imageplugins/coreplugin/imageeffect_blur.cpp147
-rw-r--r--src/imageplugins/coreplugin/imageeffect_blur.h68
-rw-r--r--src/imageplugins/coreplugin/imageeffect_bwsepia.cpp1183
-rw-r--r--src/imageplugins/coreplugin/imageeffect_bwsepia.h195
-rw-r--r--src/imageplugins/coreplugin/imageeffect_iccproof.cpp1284
-rw-r--r--src/imageplugins/coreplugin/imageeffect_iccproof.h204
-rw-r--r--src/imageplugins/coreplugin/imageeffect_redeye.cpp574
-rw-r--r--src/imageplugins/coreplugin/imageeffect_redeye.h153
-rw-r--r--src/imageplugins/coreplugin/imageeffect_rgb.cpp419
-rw-r--r--src/imageplugins/coreplugin/imageeffect_rgb.h113
-rw-r--r--src/imageplugins/coreplugin/imageplugin_core.cpp295
-rw-r--r--src/imageplugins/coreplugin/imageplugin_core.h85
-rw-r--r--src/imageplugins/coreplugin/ratiocrop/Makefile.am26
-rw-r--r--src/imageplugins/coreplugin/ratiocrop/imageeffect_ratiocrop.cpp799
-rw-r--r--src/imageplugins/coreplugin/ratiocrop/imageeffect_ratiocrop.h132
-rw-r--r--src/imageplugins/coreplugin/ratiocrop/imageselectionwidget.cpp1422
-rw-r--r--src/imageplugins/coreplugin/ratiocrop/imageselectionwidget.h176
-rw-r--r--src/imageplugins/coreplugin/ratiocrop/ratiocroptool.cpp853
-rw-r--r--src/imageplugins/coreplugin/ratiocrop/ratiocroptool.h135
-rw-r--r--src/imageplugins/coreplugin/redeyetool.cpp587
-rw-r--r--src/imageplugins/coreplugin/redeyetool.h157
-rw-r--r--src/imageplugins/coreplugin/rgbtool.cpp440
-rw-r--r--src/imageplugins/coreplugin/rgbtool.h119
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/Makefile.am32
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/LICENCE12
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/Makefile.am7
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/README2
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/abort_.c10
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/blaswrap.h158
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/clapack.h5079
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/close.c80
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dgemm.c313
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dger.c143
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dgesv.c117
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetf2.c157
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetrf.c197
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetrs.c159
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dlaswp.c143
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dscal.c62
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dswap.c81
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/dtrsm.c404
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/endfile.c102
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/err.c240
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/f2c.h223
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/fio.h96
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/fmt.c470
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/fmt.h86
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/fmtlib.c40
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/fp.h28
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/idamax.c61
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/ieeeck.c150
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/ilaenv.c610
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/lsame.c101
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/open.c256
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/s_cmp.c40
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/s_copy.c47
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/s_stop.c37
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/sfe.c29
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/sig_die.c41
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/util.c39
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/wref.c266
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/wrtfmt.c321
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/wsfe.c69
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/clapack/xerbla.c58
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/imageeffect_sharpen.cpp696
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/imageeffect_sharpen.h102
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/matrix.cpp663
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/matrix.h129
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/refocus.cpp199
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/refocus.h67
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/sharpentool.cpp741
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/sharpentool.h111
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/unsharp.cpp127
-rw-r--r--src/imageplugins/coreplugin/sharpnesseditor/unsharp.h58
-rw-r--r--src/imageplugins/distortionfx/Makefile.am34
-rw-r--r--src/imageplugins/distortionfx/digikamimageplugin_distortionfx.desktop50
-rw-r--r--src/imageplugins/distortionfx/digikamimageplugin_distortionfx_ui.rc20
-rw-r--r--src/imageplugins/distortionfx/distortionfx.cpp869
-rw-r--r--src/imageplugins/distortionfx/distortionfx.h149
-rw-r--r--src/imageplugins/distortionfx/distortionfxtool.cpp398
-rw-r--r--src/imageplugins/distortionfx/distortionfxtool.h96
-rw-r--r--src/imageplugins/distortionfx/imageeffect_distortionfx.cpp378
-rw-r--r--src/imageplugins/distortionfx/imageeffect_distortionfx.h82
-rw-r--r--src/imageplugins/distortionfx/imageplugin_distortionfx.cpp72
-rw-r--r--src/imageplugins/distortionfx/imageplugin_distortionfx.h59
-rw-r--r--src/imageplugins/emboss/Makefile.am34
-rw-r--r--src/imageplugins/emboss/digikamimageplugin_emboss.desktop51
-rw-r--r--src/imageplugins/emboss/digikamimageplugin_emboss_ui.rc20
-rw-r--r--src/imageplugins/emboss/emboss.cpp127
-rw-r--r--src/imageplugins/emboss/emboss.h75
-rw-r--r--src/imageplugins/emboss/embosstool.cpp167
-rw-r--r--src/imageplugins/emboss/embosstool.h82
-rw-r--r--src/imageplugins/emboss/imageeffect_emboss.cpp170
-rw-r--r--src/imageplugins/emboss/imageeffect_emboss.h69
-rw-r--r--src/imageplugins/emboss/imageplugin_emboss.cpp72
-rw-r--r--src/imageplugins/emboss/imageplugin_emboss.h57
-rw-r--r--src/imageplugins/filmgrain/Makefile.am34
-rw-r--r--src/imageplugins/filmgrain/digikamimageplugin_filmgrain.desktop52
-rw-r--r--src/imageplugins/filmgrain/digikamimageplugin_filmgrain_ui.rc20
-rw-r--r--src/imageplugins/filmgrain/filmgrain.cpp202
-rw-r--r--src/imageplugins/filmgrain/filmgrain.h58
-rw-r--r--src/imageplugins/filmgrain/filmgraintool.cpp195
-rw-r--r--src/imageplugins/filmgrain/filmgraintool.h83
-rw-r--r--src/imageplugins/filmgrain/imageeffect_filmgrain.cpp195
-rw-r--r--src/imageplugins/filmgrain/imageeffect_filmgrain.h74
-rw-r--r--src/imageplugins/filmgrain/imageplugin_filmgrain.cpp71
-rw-r--r--src/imageplugins/filmgrain/imageplugin_filmgrain.h57
-rw-r--r--src/imageplugins/freerotation/Makefile.am34
-rw-r--r--src/imageplugins/freerotation/digikamimageplugin_freerotation.desktop51
-rw-r--r--src/imageplugins/freerotation/digikamimageplugin_freerotation_ui.rc20
-rw-r--r--src/imageplugins/freerotation/freerotation.cpp263
-rw-r--r--src/imageplugins/freerotation/freerotation.h94
-rw-r--r--src/imageplugins/freerotation/freerotationtool.cpp318
-rw-r--r--src/imageplugins/freerotation/freerotationtool.h97
-rw-r--r--src/imageplugins/freerotation/imageeffect_freerotation.cpp308
-rw-r--r--src/imageplugins/freerotation/imageeffect_freerotation.h83
-rw-r--r--src/imageplugins/freerotation/imageplugin_freerotation.cpp70
-rw-r--r--src/imageplugins/freerotation/imageplugin_freerotation.h57
-rw-r--r--src/imageplugins/hotpixels/Makefile.am36
-rw-r--r--src/imageplugins/hotpixels/TODO4
-rw-r--r--src/imageplugins/hotpixels/blackframelistview.cpp176
-rw-r--r--src/imageplugins/hotpixels/blackframelistview.h127
-rw-r--r--src/imageplugins/hotpixels/blackframeparser.cpp211
-rw-r--r--src/imageplugins/hotpixels/blackframeparser.h102
-rw-r--r--src/imageplugins/hotpixels/digikamimageplugin_hotpixels.desktop50
-rw-r--r--src/imageplugins/hotpixels/digikamimageplugin_hotpixels_ui.rc20
-rw-r--r--src/imageplugins/hotpixels/hotpixel.h74
-rw-r--r--src/imageplugins/hotpixels/hotpixelfixer.cpp302
-rw-r--r--src/imageplugins/hotpixels/hotpixelfixer.h98
-rw-r--r--src/imageplugins/hotpixels/hotpixelstool.cpp276
-rw-r--r--src/imageplugins/hotpixels/hotpixelstool.h113
-rw-r--r--src/imageplugins/hotpixels/imageeffect_hotpixels.cpp279
-rw-r--r--src/imageplugins/hotpixels/imageeffect_hotpixels.h104
-rw-r--r--src/imageplugins/hotpixels/imageplugin_hotpixels.cpp72
-rw-r--r--src/imageplugins/hotpixels/imageplugin_hotpixels.h56
-rw-r--r--src/imageplugins/hotpixels/weights.cpp283
-rw-r--r--src/imageplugins/hotpixels/weights.h90
-rw-r--r--src/imageplugins/infrared/Makefile.am34
-rw-r--r--src/imageplugins/infrared/digikamimageplugin_infrared.desktop52
-rw-r--r--src/imageplugins/infrared/digikamimageplugin_infrared_ui.rc19
-rw-r--r--src/imageplugins/infrared/imageeffect_infrared.cpp227
-rw-r--r--src/imageplugins/infrared/imageeffect_infrared.h76
-rw-r--r--src/imageplugins/infrared/imageplugin_infrared.cpp71
-rw-r--r--src/imageplugins/infrared/imageplugin_infrared.h57
-rw-r--r--src/imageplugins/infrared/infrared.cpp367
-rw-r--r--src/imageplugins/infrared/infrared.h60
-rw-r--r--src/imageplugins/infrared/infraredtool.cpp225
-rw-r--r--src/imageplugins/infrared/infraredtool.h86
-rw-r--r--src/imageplugins/inpainting/Makefile.am34
-rw-r--r--src/imageplugins/inpainting/digikamimageplugin_inpainting.desktop49
-rw-r--r--src/imageplugins/inpainting/digikamimageplugin_inpainting_ui.rc20
-rw-r--r--src/imageplugins/inpainting/imageeffect_inpainting.cpp466
-rw-r--r--src/imageplugins/inpainting/imageeffect_inpainting.h116
-rw-r--r--src/imageplugins/inpainting/imageplugin_inpainting.cpp97
-rw-r--r--src/imageplugins/inpainting/imageplugin_inpainting.h57
-rw-r--r--src/imageplugins/inpainting/inpaintingtool.cpp430
-rw-r--r--src/imageplugins/inpainting/inpaintingtool.h133
-rw-r--r--src/imageplugins/inserttext/Makefile.am34
-rw-r--r--src/imageplugins/inserttext/digikamimageplugin_inserttext.desktop50
-rw-r--r--src/imageplugins/inserttext/digikamimageplugin_inserttext_ui.rc20
-rw-r--r--src/imageplugins/inserttext/fontchooserwidget.cpp738
-rw-r--r--src/imageplugins/inserttext/fontchooserwidget.h172
-rw-r--r--src/imageplugins/inserttext/imageeffect_inserttext.cpp348
-rw-r--r--src/imageplugins/inserttext/imageeffect_inserttext.h103
-rw-r--r--src/imageplugins/inserttext/imageplugin_inserttext.cpp70
-rw-r--r--src/imageplugins/inserttext/imageplugin_inserttext.h56
-rw-r--r--src/imageplugins/inserttext/inserttexttool.cpp336
-rw-r--r--src/imageplugins/inserttext/inserttexttool.h111
-rw-r--r--src/imageplugins/inserttext/inserttextwidget.cpp622
-rw-r--r--src/imageplugins/inserttext/inserttextwidget.h156
-rw-r--r--src/imageplugins/lensdistortion/Makefile.am34
-rw-r--r--src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion.desktop50
-rw-r--r--src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion_ui.rc20
-rw-r--r--src/imageplugins/lensdistortion/imageeffect_lensdistortion.cpp317
-rw-r--r--src/imageplugins/lensdistortion/imageeffect_lensdistortion.h82
-rw-r--r--src/imageplugins/lensdistortion/imageplugin_lensdistortion.cpp69
-rw-r--r--src/imageplugins/lensdistortion/imageplugin_lensdistortion.h56
-rw-r--r--src/imageplugins/lensdistortion/lensdistortion.cpp135
-rw-r--r--src/imageplugins/lensdistortion/lensdistortion.h63
-rw-r--r--src/imageplugins/lensdistortion/lensdistortiontool.cpp326
-rw-r--r--src/imageplugins/lensdistortion/lensdistortiontool.h92
-rw-r--r--src/imageplugins/lensdistortion/pixelaccess.cpp314
-rw-r--r--src/imageplugins/lensdistortion/pixelaccess.h93
-rw-r--r--src/imageplugins/noisereduction/Makefile.am34
-rw-r--r--src/imageplugins/noisereduction/digikamimageplugin_noisereduction.desktop53
-rw-r--r--src/imageplugins/noisereduction/digikamimageplugin_noisereduction_ui.rc20
-rw-r--r--src/imageplugins/noisereduction/imageeffect_noisereduction.cpp553
-rw-r--r--src/imageplugins/noisereduction/imageeffect_noisereduction.h82
-rw-r--r--src/imageplugins/noisereduction/imageplugin_noisereduction.cpp70
-rw-r--r--src/imageplugins/noisereduction/imageplugin_noisereduction.h56
-rw-r--r--src/imageplugins/noisereduction/noisereduction.cpp809
-rw-r--r--src/imageplugins/noisereduction/noisereduction.h257
-rw-r--r--src/imageplugins/noisereduction/noisereductiontool.cpp536
-rw-r--r--src/imageplugins/noisereduction/noisereductiontool.h92
-rw-r--r--src/imageplugins/oilpaint/Makefile.am34
-rw-r--r--src/imageplugins/oilpaint/digikamimageplugin_oilpaint.desktop51
-rw-r--r--src/imageplugins/oilpaint/digikamimageplugin_oilpaint_ui.rc20
-rw-r--r--src/imageplugins/oilpaint/imageeffect_oilpaint.cpp201
-rw-r--r--src/imageplugins/oilpaint/imageeffect_oilpaint.h69
-rw-r--r--src/imageplugins/oilpaint/imageplugin_oilpaint.cpp70
-rw-r--r--src/imageplugins/oilpaint/imageplugin_oilpaint.h56
-rw-r--r--src/imageplugins/oilpaint/oilpaint.cpp203
-rw-r--r--src/imageplugins/oilpaint/oilpaint.h72
-rw-r--r--src/imageplugins/oilpaint/oilpainttool.cpp208
-rw-r--r--src/imageplugins/oilpaint/oilpainttool.h82
-rw-r--r--src/imageplugins/perspective/Makefile.am35
-rw-r--r--src/imageplugins/perspective/digikamimageplugin_perspective.desktop52
-rw-r--r--src/imageplugins/perspective/digikamimageplugin_perspective_ui.rc20
-rw-r--r--src/imageplugins/perspective/imageeffect_perspective.cpp252
-rw-r--r--src/imageplugins/perspective/imageeffect_perspective.h89
-rw-r--r--src/imageplugins/perspective/imageplugin_perspective.cpp69
-rw-r--r--src/imageplugins/perspective/imageplugin_perspective.h56
-rw-r--r--src/imageplugins/perspective/matrix.cpp177
-rw-r--r--src/imageplugins/perspective/matrix.h106
-rw-r--r--src/imageplugins/perspective/perspectivetool.cpp244
-rw-r--r--src/imageplugins/perspective/perspectivetool.h100
-rw-r--r--src/imageplugins/perspective/perspectivewidget.cpp839
-rw-r--r--src/imageplugins/perspective/perspectivewidget.h172
-rw-r--r--src/imageplugins/perspective/triangle.cpp65
-rw-r--r--src/imageplugins/perspective/triangle.h57
-rw-r--r--src/imageplugins/raindrop/Makefile.am34
-rw-r--r--src/imageplugins/raindrop/digikamimageplugin_raindrop.desktop52
-rw-r--r--src/imageplugins/raindrop/digikamimageplugin_raindrop_ui.rc20
-rw-r--r--src/imageplugins/raindrop/imageeffect_raindrop.cpp259
-rw-r--r--src/imageplugins/raindrop/imageeffect_raindrop.h70
-rw-r--r--src/imageplugins/raindrop/imageplugin_raindrop.cpp69
-rw-r--r--src/imageplugins/raindrop/imageplugin_raindrop.h56
-rw-r--r--src/imageplugins/raindrop/raindrop.cpp457
-rw-r--r--src/imageplugins/raindrop/raindrop.h105
-rw-r--r--src/imageplugins/raindrop/raindroptool.cpp254
-rw-r--r--src/imageplugins/raindrop/raindroptool.h82
-rw-r--r--src/imageplugins/restoration/Makefile.am35
-rw-r--r--src/imageplugins/restoration/digikamimageplugin_restoration.desktop52
-rw-r--r--src/imageplugins/restoration/digikamimageplugin_restoration_ui.rc20
-rw-r--r--src/imageplugins/restoration/imageeffect_restoration.cpp349
-rw-r--r--src/imageplugins/restoration/imageeffect_restoration.h94
-rw-r--r--src/imageplugins/restoration/imageplugin_restoration.cpp71
-rw-r--r--src/imageplugins/restoration/imageplugin_restoration.h57
-rw-r--r--src/imageplugins/restoration/restorationtool.cpp356
-rw-r--r--src/imageplugins/restoration/restorationtool.h100
-rw-r--r--src/imageplugins/sheartool/Makefile.am33
-rw-r--r--src/imageplugins/sheartool/digikamimageplugin_sheartool.desktop53
-rw-r--r--src/imageplugins/sheartool/digikamimageplugin_sheartool_ui.rc20
-rw-r--r--src/imageplugins/sheartool/imageeffect_sheartool.cpp322
-rw-r--r--src/imageplugins/sheartool/imageeffect_sheartool.h82
-rw-r--r--src/imageplugins/sheartool/imageplugin_sheartool.cpp69
-rw-r--r--src/imageplugins/sheartool/imageplugin_sheartool.h56
-rw-r--r--src/imageplugins/sheartool/shear.cpp185
-rw-r--r--src/imageplugins/sheartool/shear.h84
-rw-r--r--src/imageplugins/sheartool/sheartool.cpp331
-rw-r--r--src/imageplugins/sheartool/sheartool.h96
-rw-r--r--src/imageplugins/superimpose/Makefile.am35
-rw-r--r--src/imageplugins/superimpose/digikamimageplugin_superimpose.desktop52
-rw-r--r--src/imageplugins/superimpose/digikamimageplugin_superimpose_ui.rc20
-rw-r--r--src/imageplugins/superimpose/dirselectwidget.cpp182
-rw-r--r--src/imageplugins/superimpose/dirselectwidget.h78
-rw-r--r--src/imageplugins/superimpose/imageeffect_superimpose.cpp280
-rw-r--r--src/imageplugins/superimpose/imageeffect_superimpose.h87
-rw-r--r--src/imageplugins/superimpose/imageplugin_superimpose.cpp71
-rw-r--r--src/imageplugins/superimpose/imageplugin_superimpose.h58
-rw-r--r--src/imageplugins/superimpose/superimpose.cpp70
-rw-r--r--src/imageplugins/superimpose/superimpose.h67
-rw-r--r--src/imageplugins/superimpose/superimposetool.cpp271
-rw-r--r--src/imageplugins/superimpose/superimposetool.h90
-rw-r--r--src/imageplugins/superimpose/superimposewidget.cpp329
-rw-r--r--src/imageplugins/superimpose/superimposewidget.h118
-rw-r--r--src/imageplugins/texture/Makefile.am35
-rw-r--r--src/imageplugins/texture/digikamimageplugin_texture.desktop52
-rw-r--r--src/imageplugins/texture/digikamimageplugin_texture_ui.rc20
-rw-r--r--src/imageplugins/texture/imageeffect_texture.cpp291
-rw-r--r--src/imageplugins/texture/imageeffect_texture.h100
-rw-r--r--src/imageplugins/texture/imageplugin_texture.cpp70
-rw-r--r--src/imageplugins/texture/imageplugin_texture.h56
-rw-r--r--src/imageplugins/texture/patterns/Makefile.am5
-rw-r--r--src/imageplugins/texture/patterns/bluejean-texture.pngbin0 -> 18748 bytes
-rw-r--r--src/imageplugins/texture/patterns/bricks-texture.pngbin0 -> 7888 bytes
-rw-r--r--src/imageplugins/texture/patterns/bricks2-texture.pngbin0 -> 8867 bytes
-rw-r--r--src/imageplugins/texture/patterns/burlap-texture.pngbin0 -> 7960 bytes
-rw-r--r--src/imageplugins/texture/patterns/canvas-texture.pngbin0 -> 33037 bytes
-rw-r--r--src/imageplugins/texture/patterns/cellwood-texture.pngbin0 -> 55637 bytes
-rw-r--r--src/imageplugins/texture/patterns/fabric-texture.pngbin0 -> 14189 bytes
-rw-r--r--src/imageplugins/texture/patterns/marble-texture.pngbin0 -> 19218 bytes
-rw-r--r--src/imageplugins/texture/patterns/marble2-texture.pngbin0 -> 6551 bytes
-rw-r--r--src/imageplugins/texture/patterns/metalwire-texture.pngbin0 -> 90343 bytes
-rw-r--r--src/imageplugins/texture/patterns/modern-texture.pngbin0 -> 85181 bytes
-rw-r--r--src/imageplugins/texture/patterns/moss-texture.pngbin0 -> 19894 bytes
-rw-r--r--src/imageplugins/texture/patterns/paper-texture.pngbin0 -> 4435 bytes
-rw-r--r--src/imageplugins/texture/patterns/paper2-texture.pngbin0 -> 182714 bytes
-rw-r--r--src/imageplugins/texture/patterns/stone-texture.pngbin0 -> 13774 bytes
-rw-r--r--src/imageplugins/texture/patterns/wall-texture.pngbin0 -> 69570 bytes
-rw-r--r--src/imageplugins/texture/texture.cpp181
-rw-r--r--src/imageplugins/texture/texture.h62
-rw-r--r--src/imageplugins/texture/texturetool.cpp294
-rw-r--r--src/imageplugins/texture/texturetool.h112
-rw-r--r--src/imageplugins/whitebalance/Makefile.am33
-rw-r--r--src/imageplugins/whitebalance/digikamimageplugin_whitebalance.desktop53
-rw-r--r--src/imageplugins/whitebalance/digikamimageplugin_whitebalance_ui.rc20
-rw-r--r--src/imageplugins/whitebalance/imageeffect_whitebalance.cpp842
-rw-r--r--src/imageplugins/whitebalance/imageeffect_whitebalance.h168
-rw-r--r--src/imageplugins/whitebalance/imageplugin_whitebalance.cpp71
-rw-r--r--src/imageplugins/whitebalance/imageplugin_whitebalance.h57
-rw-r--r--src/imageplugins/whitebalance/whitebalancetool.cpp850
-rw-r--r--src/imageplugins/whitebalance/whitebalancetool.h174
425 files changed, 75937 insertions, 0 deletions
diff --git a/src/imageplugins/Makefile.am b/src/imageplugins/Makefile.am
new file mode 100644
index 00000000..3e04b062
--- /dev/null
+++ b/src/imageplugins/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = coreplugin adjustcurves adjustlevels antivignetting blurfx border \
+ channelmixer charcoal colorfx distortionfx emboss filmgrain \
+ freerotation hotpixels infrared inpainting inserttext lensdistortion \
+ noisereduction oilpaint perspective raindrop restoration sheartool \
+ superimpose texture whitebalance
diff --git a/src/imageplugins/adjustcurves/Makefile.am b/src/imageplugins/adjustcurves/Makefile.am
new file mode 100644
index 00000000..f798a7af
--- /dev/null
+++ b/src/imageplugins/adjustcurves/Makefile.am
@@ -0,0 +1,33 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_adjustcurves_la_SOURCES = imageplugin_adjustcurves.cpp \
+ adjustcurvestool.cpp
+
+digikamimageplugin_adjustcurves_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_adjustcurves_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_adjustcurves.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_adjustcurves.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_adjustcurves_ui.rc
diff --git a/src/imageplugins/adjustcurves/adjustcurves.cpp b/src/imageplugins/adjustcurves/adjustcurves.cpp
new file mode 100644
index 00000000..ace9c9b3
--- /dev/null
+++ b/src/imageplugins/adjustcurves/adjustcurves.cpp
@@ -0,0 +1,677 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-01
+ * Description : image histogram adjust curves.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqpainter.h>
+#include <tqcombobox.h>
+#include <tqspinbox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqtimer.h>
+#include <tqhbuttongroup.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <knuminput.h>
+#include <tdemessagebox.h>
+#include <tdeselect.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagehistogram.h"
+#include "imagecurves.h"
+#include "histogramwidget.h"
+#include "curveswidget.h"
+#include "colorgradientwidget.h"
+#include "dimgimagefilters.h"
+#include "adjustcurves.h"
+#include "adjustcurves.moc"
+
+namespace DigikamAdjustCurvesImagesPlugin
+{
+
+AdjustCurveDialog::AdjustCurveDialog(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Adjust Color Curves"), "adjustcurves", true, false)
+{
+ m_destinationPreviewData = 0L;
+
+ Digikam::ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sixteenBit = iface.originalSixteenBit();
+ bool hasAlpha = iface.originalHasAlpha();
+ m_originalImage = Digikam::DImg(w, h, sixteenBit, hasAlpha ,data);
+ delete [] data;
+
+ m_histoSegments = m_originalImage.sixteenBit() ? 65535 : 255;
+ m_curves = new Digikam::ImageCurves(m_originalImage.sixteenBit());
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Adjust Color Curves"),
+ digikam_version,
+ I18N_NOOP("An image-histogram-curves adjustment plugin for digiKam."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new Digikam::ImageWidget("adjustcurves Tool Dialog", plainPage(),
+ i18n("<p>This is the image's curve-adjustments preview. "
+ "You can pick a spot on the image "
+ "to see the corresponding level in the histogram."));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* grid = new TQGridLayout( gboxSettings, 5, 5, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ m_channelCB->insertItem( i18n("Alpha") );
+ m_channelCB->setCurrentText( i18n("Luminosity") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"
+ "<b>Alpha</b>: display the alpha image-channel values. "
+ "This channel corresponds to the transparency value and "
+ "is supported by some image formats, such as PNG or TIF."));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::CurvesWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::CurvesWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setButton(Digikam::CurvesWidget::LogScaleHistogram);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ grid->addMultiCellWidget(label1, 0, 0, 1, 1);
+ grid->addMultiCellWidget(m_channelCB, 0, 0, 2, 2);
+ grid->addMultiCellLayout(l1, 0, 0, 4, 5);
+
+ // -------------------------------------------------------------
+
+ TQWidget *curveBox = new TQWidget(gboxSettings);
+ TQGridLayout* gl = new TQGridLayout(curveBox, 4, 2, 0);
+
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, curveBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "curves settings changes."));
+
+ m_vGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Vertical, 10, curveBox );
+ m_vGradient->setColors( TQColor( "white" ), TQColor( "black" ) );
+
+ TQLabel *spacev = new TQLabel(curveBox);
+ spacev->setFixedWidth(1);
+
+ m_curvesWidget = new Digikam::CurvesWidget(256, 256, m_originalImage.bits(), m_originalImage.width(),
+ m_originalImage.height(), m_originalImage.sixteenBit(),
+ m_curves, curveBox);
+ TQWhatsThis::add( m_curvesWidget, i18n("<p>This is the curve drawing of the selected channel from "
+ "original image"));
+
+ TQLabel *spaceh = new TQLabel(curveBox);
+ spaceh->setFixedHeight(1);
+
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, curveBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gl->addMultiCellWidget(m_histogramWidget, 0, 0, 2, 2);
+ gl->addMultiCellWidget(m_vGradient, 2, 2, 0, 0);
+ gl->addMultiCellWidget(spacev, 2, 2, 1, 1);
+ gl->addMultiCellWidget(m_curvesWidget, 2, 2, 2, 2);
+ gl->addMultiCellWidget(spaceh, 3, 3, 2, 2);
+ gl->addMultiCellWidget(m_hGradient, 4, 4, 2, 2);
+ gl->setRowSpacing(1, spacingHint());
+
+ grid->addMultiCellWidget(curveBox, 2, 3, 0, 5);
+
+ // -------------------------------------------------------------
+
+ m_curveType = new TQHButtonGroup(gboxSettings);
+ m_curveFree = new TQPushButton(m_curveType);
+ m_curveType->insert(m_curveFree, FreeDrawing);
+ TDEGlobal::dirs()->addResourceType("curvefree", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("curvefree", "curvefree.png");
+ m_curveFree->setPixmap( TQPixmap( directory + "curvefree.png" ) );
+ m_curveFree->setToggleButton(true);
+ TQToolTip::add( m_curveFree, i18n( "Curve free mode" ) );
+ TQWhatsThis::add( m_curveFree, i18n("<p>With this button, you can draw your curve free-hand with the mouse."));
+ m_curveSmooth = new TQPushButton(m_curveType);
+ m_curveType->insert(m_curveSmooth, SmoothDrawing);
+ TDEGlobal::dirs()->addResourceType("curvemooth", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("curvemooth", "curvemooth.png");
+ m_curveSmooth->setPixmap( TQPixmap( directory + "curvemooth.png" ) );
+ m_curveSmooth->setToggleButton(true);
+ TQToolTip::add( m_curveSmooth, i18n( "Curve smooth mode" ) );
+ TQWhatsThis::add( m_curveSmooth, i18n("<p>With this button, you constrains the curve type to a smooth line with tension."));
+ m_curveType->setExclusive(true);
+ m_curveType->setButton(SmoothDrawing);
+ m_curveType->setFrameShape(TQFrame::NoFrame);
+
+ // -------------------------------------------------------------
+
+ m_pickerColorButtonGroup = new TQHButtonGroup(gboxSettings);
+ m_pickBlack = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickBlack, BlackTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-black", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-black", "color-picker-black.png");
+ m_pickBlack->setPixmap( TQPixmap( directory + "color-picker-black.png" ) );
+ m_pickBlack->setToggleButton(true);
+ TQToolTip::add( m_pickBlack, i18n( "All channels shadow tone color picker" ) );
+ TQWhatsThis::add( m_pickBlack, i18n("<p>With this button, you can pick the color from original image used to set <b>Shadow Tone</b> "
+ "smooth curves point on Red, Green, Blue, and Luminosity channels."));
+ m_pickGray = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickGray, GrayTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-grey", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-grey", "color-picker-grey.png");
+ m_pickGray->setPixmap( TQPixmap( directory + "color-picker-grey.png" ) );
+ m_pickGray->setToggleButton(true);
+ TQToolTip::add( m_pickGray, i18n( "All channels middle tone color picker" ) );
+ TQWhatsThis::add( m_pickGray, i18n("<p>With this button, you can pick the color from original image used to set <b>Middle Tone</b> "
+ "smooth curves point on Red, Green, Blue, and Luminosity channels."));
+ m_pickWhite = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickWhite, WhiteTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-white", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-white", "color-picker-white.png");
+ m_pickWhite->setPixmap( TQPixmap( directory + "color-picker-white.png" ) );
+ m_pickWhite->setToggleButton(true);
+ TQToolTip::add( m_pickWhite, i18n( "All channels highlight tone color picker" ) );
+ TQWhatsThis::add( m_pickWhite, i18n("<p>With this button, you can pick the color from original image used to set <b>Highlight Tone</b> "
+ "smooth curves point on Red, Green, Blue, and Luminosity channels."));
+ m_pickerColorButtonGroup->setExclusive(true);
+ m_pickerColorButtonGroup->setFrameShape(TQFrame::NoFrame);
+
+ // -------------------------------------------------------------
+
+ m_resetButton = new TQPushButton(i18n("&Reset"), gboxSettings);
+ m_resetButton->setPixmap( SmallIcon("reload_page", 18) );
+ TQToolTip::add( m_resetButton, i18n( "Reset current channel curves' values." ) );
+ TQWhatsThis::add( m_resetButton, i18n("<p>If you press this button, all curves' values "
+ "from the current selected channel "
+ "will be reset to the default values."));
+
+ TQHBoxLayout* l3 = new TQHBoxLayout();
+ l3->addWidget(m_curveType);
+ l3->addWidget(m_pickerColorButtonGroup);
+ l3->addWidget(m_resetButton);
+ l3->addStretch(10);
+
+ grid->addMultiCellLayout(l3, 4, 4, 1, 5);
+
+ // -------------------------------------------------------------
+
+
+ grid->setRowStretch(5, 10);
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_curvesWidget, TQ_SIGNAL(signalCurvesChanged()),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotSpotColorChanged( const Digikam::DColor & )));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+ // ComboBox slots.
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_curveType, TQ_SIGNAL(clicked(int)),
+ this, TQ_SLOT(slotCurveTypeChanged(int)));
+
+ // -------------------------------------------------------------
+ // Bouttons slots.
+
+ connect(m_resetButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotResetCurrentChannel()));
+
+ connect(m_pickerColorButtonGroup, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotPickerColorButtonActived()));
+}
+
+AdjustCurveDialog::~AdjustCurveDialog()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+ delete m_curvesWidget;
+ delete m_previewWidget;
+ delete m_curves;
+}
+
+void AdjustCurveDialog::slotPickerColorButtonActived()
+{
+ // Save previous rendering mode and toggle to original image.
+ m_currentPreviewMode = m_previewWidget->getRenderingPreviewMode();
+ m_previewWidget->setRenderingPreviewMode(Digikam::ImageGuideWidget::PreviewOriginalImage);
+}
+
+void AdjustCurveDialog::slotSpotColorChanged(const Digikam::DColor &color)
+{
+ Digikam::DColor sc = color;
+
+ if ( m_pickBlack->isOn() )
+ {
+ // Black tonal curves point.
+ m_curves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 1,
+ TQPoint(TQMAX(TQMAX(sc.red(), sc.green()), sc.blue()), 42*m_histoSegments/256));
+ m_curves->setCurvePoint(Digikam::ImageHistogram::RedChannel, 1, TQPoint(sc.red(), 42*m_histoSegments/256));
+ m_curves->setCurvePoint(Digikam::ImageHistogram::GreenChannel, 1, TQPoint(sc.green(), 42*m_histoSegments/256));
+ m_curves->setCurvePoint(Digikam::ImageHistogram::BlueChannel, 1, TQPoint(sc.blue(), 42*m_histoSegments/256));
+ m_pickBlack->setOn(false);
+ }
+ else if ( m_pickGray->isOn() )
+ {
+ // Gray tonal curves point.
+ m_curves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 8,
+ TQPoint(TQMAX(TQMAX(sc.red(), sc.green()), sc.blue()), 128*m_histoSegments/256));
+ m_curves->setCurvePoint(Digikam::ImageHistogram::RedChannel, 8, TQPoint(sc.red(), 128*m_histoSegments/256));
+ m_curves->setCurvePoint(Digikam::ImageHistogram::GreenChannel, 8, TQPoint(sc.green(), 128*m_histoSegments/256));
+ m_curves->setCurvePoint(Digikam::ImageHistogram::BlueChannel, 8, TQPoint(sc.blue(), 128*m_histoSegments/256));
+ m_pickGray->setOn(false);
+ }
+ else if ( m_pickWhite->isOn() )
+ {
+ // White tonal curves point.
+ m_curves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 15,
+ TQPoint(TQMAX(TQMAX(sc.red(), sc.green()), sc.blue()), 213*m_histoSegments/256));
+ m_curves->setCurvePoint(Digikam::ImageHistogram::RedChannel, 15, TQPoint(sc.red(), 213*m_histoSegments/256));
+ m_curves->setCurvePoint(Digikam::ImageHistogram::GreenChannel, 15, TQPoint(sc.green(), 213*m_histoSegments/256));
+ m_curves->setCurvePoint(Digikam::ImageHistogram::BlueChannel, 15, TQPoint(sc.blue(), 213*m_histoSegments/256));
+ m_pickWhite->setOn(false);
+ }
+ else
+ {
+ m_curvesWidget->setCurveGuide(color);
+ return;
+ }
+
+ // Calculate Red, green, blue curves.
+
+ for (int i = Digikam::ImageHistogram::ValueChannel ; i <= Digikam::ImageHistogram::BlueChannel ; i++)
+ m_curves->curvesCalculateCurve(i);
+
+ m_curvesWidget->repaint(false);
+
+ // restore previous rendering mode.
+ m_previewWidget->setRenderingPreviewMode(m_currentPreviewMode);
+
+ slotEffect();
+}
+
+void AdjustCurveDialog::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void AdjustCurveDialog::slotResetCurrentChannel()
+{
+ m_curves->curvesChannelReset(m_channelCB->currentItem());
+
+ m_curvesWidget->reset();
+ slotEffect();
+ m_histogramWidget->reset();
+}
+
+void AdjustCurveDialog::slotEffect()
+{
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *orgData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ // Create the new empty destination image data space.
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ m_destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)];
+
+ // Calculate the LUT to apply on the image.
+ m_curves->curvesLutSetup(Digikam::ImageHistogram::AlphaChannel);
+
+ // Apply the lut to the image.
+ m_curves->curvesLutProcess(orgData, m_destinationPreviewData, w, h);
+
+ iface->putPreviewImage(m_destinationPreviewData);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ delete [] orgData;
+}
+
+void AdjustCurveDialog::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *orgData = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ // Create the new empty destination image data space.
+ uchar* desData = new uchar[w*h*(sb ? 8 : 4)];
+
+ // Calculate the LUT to apply on the image.
+ m_curves->curvesLutSetup(Digikam::ImageHistogram::AlphaChannel);
+
+ // Apply the lut to the image.
+ m_curves->curvesLutProcess(orgData, desData, w, h);
+
+ iface->putOriginalImage(i18n("Adjust Curve"), desData);
+ kapp->restoreOverrideCursor();
+
+ delete [] orgData;
+ delete [] desData;
+ accept();
+}
+
+void AdjustCurveDialog::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_curvesWidget->m_channelType = Digikam::CurvesWidget::ValueHistogram;
+ m_vGradient->setColors( TQColor( "white" ), TQColor( "black" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ m_curvesWidget->m_channelType = Digikam::CurvesWidget::RedChannelHistogram;
+ m_vGradient->setColors( TQColor( "red" ), TQColor( "black" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ m_curvesWidget->m_channelType = Digikam::CurvesWidget::GreenChannelHistogram;
+ m_vGradient->setColors( TQColor( "green" ), TQColor( "black" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ m_curvesWidget->m_channelType = Digikam::CurvesWidget::BlueChannelHistogram;
+ m_vGradient->setColors( TQColor( "blue" ), TQColor( "black" ) );
+ break;
+
+ case AlphaChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::AlphaChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_curvesWidget->m_channelType = Digikam::CurvesWidget::AlphaChannelHistogram;
+ m_vGradient->setColors( TQColor( "white" ), TQColor( "black" ) );
+ break;
+ }
+
+ m_curveType->setButton(m_curves->getCurveType(channel));
+
+ m_curvesWidget->repaint(false);
+ m_histogramWidget->repaint(false);
+}
+
+void AdjustCurveDialog::slotScaleChanged(int scale)
+{
+ m_curvesWidget->m_scaleType = scale;
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+ m_curvesWidget->repaint(false);
+}
+
+void AdjustCurveDialog::slotCurveTypeChanged(int type)
+{
+ switch(type)
+ {
+ case SmoothDrawing:
+ {
+ m_curves->setCurveType(m_curvesWidget->m_channelType, Digikam::ImageCurves::CURVE_SMOOTH);
+ m_pickerColorButtonGroup->setEnabled(true);
+ break;
+ }
+
+ case FreeDrawing:
+ {
+ m_curves->setCurveType(m_curvesWidget->m_channelType, Digikam::ImageCurves::CURVE_FREE);
+ m_pickerColorButtonGroup->setEnabled(false);
+ break;
+ }
+ }
+
+ m_curvesWidget->curveTypeChanged();
+}
+
+void AdjustCurveDialog::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("adjustcurves Tool Dialog");
+
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+
+ m_curvesWidget->reset();
+
+ for (int i = 0 ; i < 5 ; i++)
+ {
+ m_curves->curvesChannelReset(i);
+ m_curves->setCurveType(i, (Digikam::ImageCurves::CurveType)config->readNumEntry(TQString("CurveTypeChannel%1").arg(i),
+ Digikam::ImageCurves::CURVE_SMOOTH));
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p = config->readPointEntry(TQString("CurveAjustmentChannel%1Point%2").arg(i).arg(j), &disable);
+
+ if (m_originalImage.sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+
+ m_curves->setCurvePoint(i, j, p);
+ }
+
+ m_curves->curvesCalculateCurve(i);
+ }
+
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void AdjustCurveDialog::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("adjustcurves Tool Dialog");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+
+ for (int i = 0 ; i < 5 ; i++)
+ {
+ config->writeEntry(TQString("CurveTypeChannel%1").arg(i), m_curves->getCurveType(i));
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint p = m_curves->getCurvePoint(i, j);
+
+ if (m_originalImage.sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()/255);
+ p.setY(p.y()/255);
+ }
+
+ config->writeEntry(TQString("CurveAjustmentChannel%1Point%2").arg(i).arg(j), p);
+ }
+ }
+
+ config->sync();
+}
+
+void AdjustCurveDialog::resetValues()
+{
+ for (int channel = 0 ; channel < 5 ; channel++)
+ m_curves->curvesChannelReset(channel);
+
+ m_curvesWidget->reset();
+ m_histogramWidget->reset();
+}
+
+// Load all settings.
+void AdjustCurveDialog::slotUser3()
+{
+ KURL loadCurvesFile;
+
+ loadCurvesFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Select Gimp Curves File to Load")) );
+ if( loadCurvesFile.isEmpty() )
+ return;
+
+ if ( m_curves->loadCurvesFromGimpCurvesFile( loadCurvesFile ) == false )
+ {
+ KMessageBox::error(this, i18n("Cannot load from the Gimp curves text file."));
+ return;
+ }
+
+ // Refresh the current curves config.
+ slotChannelChanged(m_channelCB->currentItem());
+ slotEffect();
+}
+
+// Save all settings.
+void AdjustCurveDialog::slotUser2()
+{
+ KURL saveCurvesFile;
+
+ saveCurvesFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Gimp Curves File to Save")) );
+ if( saveCurvesFile.isEmpty() )
+ return;
+
+ if ( m_curves->saveCurvesToGimpCurvesFile( saveCurvesFile ) == false )
+ {
+ KMessageBox::error(this, i18n("Cannot save to the Gimp curves text file."));
+ return;
+ }
+
+ // Refresh the current curves config.
+ slotChannelChanged(m_channelCB->currentItem());
+}
+
+} // NameSpace DigikamAdjustCurvesImagesPlugin
+
diff --git a/src/imageplugins/adjustcurves/adjustcurves.h b/src/imageplugins/adjustcurves/adjustcurves.h
new file mode 100644
index 00000000..f4cad2f2
--- /dev/null
+++ b/src/imageplugins/adjustcurves/adjustcurves.h
@@ -0,0 +1,143 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-01
+ * Description : image histogram adjust curves.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ADJUSTCURVES_H
+#define ADJUSTCURVES_H
+
+// Digikam includes.
+
+#include "imagedlgbase.h"
+#include "dimg.h"
+
+// Local includes.
+
+class TQComboBox;
+class TQPushButton;
+class TQHButtonGroup;
+
+namespace Digikam
+{
+class CurvesWidget;
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class ImageCurves;
+}
+
+namespace DigikamAdjustCurvesImagesPlugin
+{
+
+class AdjustCurveDialog : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ AdjustCurveDialog(TQWidget *parent);
+ ~AdjustCurveDialog();
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void finalRendering();
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+ void slotEffect();
+ void slotResetCurrentChannel();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotCurveTypeChanged(int type);
+ void slotSpotColorChanged(const Digikam::DColor &color);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+ void slotPickerColorButtonActived();
+
+private:
+
+ enum ColorPicker
+ {
+ BlackTonal=0,
+ GrayTonal,
+ WhiteTonal
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel,
+ AlphaChannel
+ };
+
+ enum CurvesDrawingType
+ {
+ SmoothDrawing=0,
+ FreeDrawing
+ };
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ uchar *m_destinationPreviewData;
+
+ int m_histoSegments;
+ int m_currentPreviewMode;
+
+ TQComboBox *m_channelCB;
+
+ TQPushButton *m_resetButton;
+ TQPushButton *m_pickBlack;
+ TQPushButton *m_pickGray;
+ TQPushButton *m_pickWhite;
+ TQPushButton *m_curveFree;
+ TQPushButton *m_curveSmooth;
+
+ TQHButtonGroup *m_pickerColorButtonGroup;
+ TQHButtonGroup *m_scaleBG;
+ TQHButtonGroup *m_curveType;
+
+ Digikam::CurvesWidget *m_curvesWidget;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+ Digikam::ColorGradientWidget *m_vGradient;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ImageCurves *m_curves;
+ Digikam::DImg m_originalImage;
+};
+
+} // NameSpace DigikamAdjustCurvesImagesPlugin
+
+#endif /* ADJUSTCURVES_H */
diff --git a/src/imageplugins/adjustcurves/adjustcurvestool.cpp b/src/imageplugins/adjustcurves/adjustcurvestool.cpp
new file mode 100644
index 00000000..7bfd00f7
--- /dev/null
+++ b/src/imageplugins/adjustcurves/adjustcurvestool.cpp
@@ -0,0 +1,659 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-01
+ * Description : image histogram adjust curves.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqpainter.h>
+#include <tqcombobox.h>
+#include <tqspinbox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqtimer.h>
+#include <tqhbuttongroup.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <knuminput.h>
+#include <tdemessagebox.h>
+#include <tdeselect.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <kpushbutton.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagehistogram.h"
+#include "imagecurves.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "curveswidget.h"
+#include "colorgradientwidget.h"
+#include "dimgimagefilters.h"
+#include "adjustcurvestool.h"
+#include "adjustcurvestool.moc"
+
+using namespace Digikam;
+
+namespace DigikamAdjustCurvesImagesPlugin
+{
+
+AdjustCurvesTool::AdjustCurvesTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ m_destinationPreviewData = 0;
+
+ ImageIface iface(0, 0);
+ m_originalImage = iface.getOriginalImg();
+
+ m_histoSegments = m_originalImage->sixteenBit() ? 65535 : 255;
+
+ setName("adjustcurves");
+ setToolName(i18n("Adjust Curves"));
+ setToolIcon(SmallIcon("adjustcurves"));
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImageWidget("adjustcurves Tool", 0,
+ i18n("<p>This is the image's curve-adjustments preview. "
+ "You can pick a spot on the image "
+ "to see the corresponding level in the histogram."));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 5, 5);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), m_gboxSettings->plainPage());
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, m_gboxSettings->plainPage() );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ m_channelCB->insertItem( i18n("Alpha") );
+ m_channelCB->setCurrentText( i18n("Luminosity") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"
+ "<b>Alpha</b>: display the alpha image-channel values. "
+ "This channel corresponds to the transparency value and "
+ "is supported by some image formats, such as PNG or TIF."));
+
+ m_scaleBG = new TQHButtonGroup(m_gboxSettings->plainPage());
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, CurvesWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, CurvesWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setButton(CurvesWidget::LogScaleHistogram);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin(0);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ TQWidget *curveBox = new TQWidget(m_gboxSettings->plainPage());
+ TQGridLayout* gl = new TQGridLayout(curveBox, 4, 2, 0);
+
+ m_histogramWidget = new HistogramWidget(256, 140, curveBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "curves settings changes."));
+
+ m_vGradient = new ColorGradientWidget( ColorGradientWidget::Vertical, 10, curveBox );
+ m_vGradient->setColors( TQColor( "white" ), TQColor( "black" ) );
+
+ TQLabel *spacev = new TQLabel(curveBox);
+ spacev->setFixedWidth(1);
+
+ m_curvesWidget = new CurvesWidget(256, 256, m_originalImage->bits(), m_originalImage->width(),
+ m_originalImage->height(), m_originalImage->sixteenBit(),
+ curveBox);
+ TQWhatsThis::add( m_curvesWidget, i18n("<p>This is the curve drawing of the selected channel from "
+ "original image"));
+
+ TQLabel *spaceh = new TQLabel(curveBox);
+ spaceh->setFixedHeight(1);
+
+ m_hGradient = new ColorGradientWidget( ColorGradientWidget::Horizontal, 10, curveBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gl->addMultiCellWidget(m_histogramWidget, 0, 0, 2, 2);
+ gl->addMultiCellWidget(m_vGradient, 2, 2, 0, 0);
+ gl->addMultiCellWidget(spacev, 2, 2, 1, 1);
+ gl->addMultiCellWidget(m_curvesWidget, 2, 2, 2, 2);
+ gl->addMultiCellWidget(spaceh, 3, 3, 2, 2);
+ gl->addMultiCellWidget(m_hGradient, 4, 4, 2, 2);
+ gl->setRowSpacing(1, m_gboxSettings->spacingHint());
+
+ // -------------------------------------------------------------
+
+ m_curveType = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_curveFree = new TQPushButton(m_curveType);
+ m_curveType->insert(m_curveFree, FreeDrawing);
+ TDEGlobal::dirs()->addResourceType("curvefree", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("curvefree", "curvefree.png");
+ m_curveFree->setPixmap( TQPixmap( directory + "curvefree.png" ) );
+ m_curveFree->setToggleButton(true);
+ TQToolTip::add( m_curveFree, i18n( "Curve free mode" ) );
+ TQWhatsThis::add( m_curveFree, i18n("<p>With this button, you can draw your curve free-hand with the mouse."));
+ m_curveSmooth = new TQPushButton(m_curveType);
+ m_curveType->insert(m_curveSmooth, SmoothDrawing);
+ TDEGlobal::dirs()->addResourceType("curvemooth", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("curvemooth", "curvemooth.png");
+ m_curveSmooth->setPixmap( TQPixmap( directory + "curvemooth.png" ) );
+ m_curveSmooth->setToggleButton(true);
+ TQToolTip::add( m_curveSmooth, i18n( "Curve smooth mode" ) );
+ TQWhatsThis::add( m_curveSmooth, i18n("<p>With this button, you constrains the curve type to a smooth line with tension."));
+ m_curveType->setExclusive(true);
+ m_curveType->setButton(SmoothDrawing);
+ m_curveType->setFrameShape(TQFrame::NoFrame);
+
+ // -------------------------------------------------------------
+
+ m_pickerColorButtonGroup = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_pickBlack = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickBlack, BlackTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-black", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-black", "color-picker-black.png");
+ m_pickBlack->setPixmap( TQPixmap( directory + "color-picker-black.png" ) );
+ m_pickBlack->setToggleButton(true);
+ TQToolTip::add( m_pickBlack, i18n( "All channels shadow tone color picker" ) );
+ TQWhatsThis::add( m_pickBlack, i18n("<p>With this button, you can pick the color from original image used to set <b>Shadow Tone</b> "
+ "smooth curves point on Red, Green, Blue, and Luminosity channels."));
+ m_pickGray = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickGray, GrayTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-grey", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-grey", "color-picker-grey.png");
+ m_pickGray->setPixmap( TQPixmap( directory + "color-picker-grey.png" ) );
+ m_pickGray->setToggleButton(true);
+ TQToolTip::add( m_pickGray, i18n( "All channels middle tone color picker" ) );
+ TQWhatsThis::add( m_pickGray, i18n("<p>With this button, you can pick the color from original image used to set <b>Middle Tone</b> "
+ "smooth curves point on Red, Green, Blue, and Luminosity channels."));
+ m_pickWhite = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickWhite, WhiteTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-white", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-white", "color-picker-white.png");
+ m_pickWhite->setPixmap( TQPixmap( directory + "color-picker-white.png" ) );
+ m_pickWhite->setToggleButton(true);
+ TQToolTip::add( m_pickWhite, i18n( "All channels highlight tone color picker" ) );
+ TQWhatsThis::add( m_pickWhite, i18n("<p>With this button, you can pick the color from original image used to set <b>Highlight Tone</b> "
+ "smooth curves point on Red, Green, Blue, and Luminosity channels."));
+ m_pickerColorButtonGroup->setExclusive(true);
+ m_pickerColorButtonGroup->setFrameShape(TQFrame::NoFrame);
+
+ // -------------------------------------------------------------
+
+ m_resetButton = new TQPushButton(i18n("&Reset"), m_gboxSettings->plainPage());
+ m_resetButton->setPixmap( SmallIcon("reload_page", 18) );
+ TQToolTip::add( m_resetButton, i18n( "Reset current channel curves' values." ) );
+ TQWhatsThis::add( m_resetButton, i18n("<p>If you press this button, all curves' values "
+ "from the current selected channel "
+ "will be reset to the default values."));
+
+ TQHBoxLayout* l3 = new TQHBoxLayout();
+ l3->addWidget(m_curveType);
+ l3->addWidget(m_pickerColorButtonGroup);
+ l3->addWidget(m_resetButton);
+ l3->addStretch(10);
+
+ grid->addMultiCellLayout(l1, 0, 0, 1, 5);
+ grid->addMultiCellWidget(curveBox, 1, 3, 0, 5);
+ grid->addMultiCellLayout(l3, 4, 4, 1, 5);
+ grid->setMargin(0);
+ grid->setSpacing(m_gboxSettings->spacingHint());
+ grid->setRowStretch(5, 10);
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_curvesWidget, TQ_SIGNAL(signalCurvesChanged()),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotSpotColorChanged(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotColorSelectedFromTarget(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+ // ComboBox slots.
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_curveType, TQ_SIGNAL(clicked(int)),
+ this, TQ_SLOT(slotCurveTypeChanged(int)));
+
+ // -------------------------------------------------------------
+ // Buttons slots.
+
+ connect(m_resetButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotResetCurrentChannel()));
+
+ connect(m_pickerColorButtonGroup, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotPickerColorButtonActived()));
+}
+
+AdjustCurvesTool::~AdjustCurvesTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void AdjustCurvesTool::slotPickerColorButtonActived()
+{
+ // Save previous rendering mode and toggle to original image.
+ m_currentPreviewMode = m_previewWidget->getRenderingPreviewMode();
+ m_previewWidget->setRenderingPreviewMode(ImageGuideWidget::PreviewOriginalImage);
+}
+
+void AdjustCurvesTool::slotSpotColorChanged(const DColor &color)
+{
+ DColor sc = color;
+
+ if ( m_pickBlack->isOn() )
+ {
+ // Black tonal curves point.
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::ValueChannel, 1,
+ TQPoint(TQMAX(TQMAX(sc.red(), sc.green()), sc.blue()), 42*m_histoSegments/256));
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::RedChannel, 1, TQPoint(sc.red(), 42*m_histoSegments/256));
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::GreenChannel, 1, TQPoint(sc.green(), 42*m_histoSegments/256));
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::BlueChannel, 1, TQPoint(sc.blue(), 42*m_histoSegments/256));
+ m_pickBlack->setOn(false);
+ }
+ else if ( m_pickGray->isOn() )
+ {
+ // Gray tonal curves point.
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::ValueChannel, 8,
+ TQPoint(TQMAX(TQMAX(sc.red(), sc.green()), sc.blue()), 128*m_histoSegments/256));
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::RedChannel, 8, TQPoint(sc.red(), 128*m_histoSegments/256));
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::GreenChannel, 8, TQPoint(sc.green(), 128*m_histoSegments/256));
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::BlueChannel, 8, TQPoint(sc.blue(), 128*m_histoSegments/256));
+ m_pickGray->setOn(false);
+ }
+ else if ( m_pickWhite->isOn() )
+ {
+ // White tonal curves point.
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::ValueChannel, 15,
+ TQPoint(TQMAX(TQMAX(sc.red(), sc.green()), sc.blue()), 213*m_histoSegments/256));
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::RedChannel, 15, TQPoint(sc.red(), 213*m_histoSegments/256));
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::GreenChannel, 15, TQPoint(sc.green(), 213*m_histoSegments/256));
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::BlueChannel, 15, TQPoint(sc.blue(), 213*m_histoSegments/256));
+ m_pickWhite->setOn(false);
+ }
+ else
+ {
+ m_curvesWidget->setCurveGuide(color);
+ return;
+ }
+
+ // Calculate Red, green, blue curves.
+
+ for (int i = ImageHistogram::ValueChannel ; i <= ImageHistogram::BlueChannel ; i++)
+ m_curvesWidget->curves()->curvesCalculateCurve(i);
+
+ m_curvesWidget->repaint(false);
+
+ // restore previous rendering mode.
+ m_previewWidget->setRenderingPreviewMode(m_currentPreviewMode);
+
+ slotEffect();
+}
+
+void AdjustCurvesTool::slotColorSelectedFromTarget( const DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void AdjustCurvesTool::slotResetCurrentChannel()
+{
+ m_curvesWidget->curves()->curvesChannelReset(m_channelCB->currentItem());
+
+ m_curvesWidget->repaint();
+ slotEffect();
+ m_histogramWidget->reset();
+}
+
+void AdjustCurvesTool::slotEffect()
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *orgData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ // Create the new empty destination image data space.
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ m_destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)];
+
+ // Calculate the LUT to apply on the image.
+ m_curvesWidget->curves()->curvesLutSetup(ImageHistogram::AlphaChannel);
+
+ // Apply the lut to the image.
+ m_curvesWidget->curves()->curvesLutProcess(orgData, m_destinationPreviewData, w, h);
+
+ iface->putPreviewImage(m_destinationPreviewData);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ delete [] orgData;
+}
+
+void AdjustCurvesTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *orgData = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ // Create the new empty destination image data space.
+ uchar* desData = new uchar[w*h*(sb ? 8 : 4)];
+
+ // Calculate the LUT to apply on the image.
+ m_curvesWidget->curves()->curvesLutSetup(ImageHistogram::AlphaChannel);
+
+ // Apply the lut to the image.
+ m_curvesWidget->curves()->curvesLutProcess(orgData, desData, w, h);
+
+ iface->putOriginalImage(i18n("Adjust Curves"), desData);
+ kapp->restoreOverrideCursor();
+
+ delete [] orgData;
+ delete [] desData;
+}
+
+void AdjustCurvesTool::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_curvesWidget->m_channelType = CurvesWidget::ValueHistogram;
+ m_vGradient->setColors( TQColor( "white" ), TQColor( "black" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ m_curvesWidget->m_channelType = CurvesWidget::RedChannelHistogram;
+ m_vGradient->setColors( TQColor( "red" ), TQColor( "black" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ m_curvesWidget->m_channelType = CurvesWidget::GreenChannelHistogram;
+ m_vGradient->setColors( TQColor( "green" ), TQColor( "black" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ m_curvesWidget->m_channelType = CurvesWidget::BlueChannelHistogram;
+ m_vGradient->setColors( TQColor( "blue" ), TQColor( "black" ) );
+ break;
+
+ case AlphaChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::AlphaChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_curvesWidget->m_channelType = CurvesWidget::AlphaChannelHistogram;
+ m_vGradient->setColors( TQColor( "white" ), TQColor( "black" ) );
+ break;
+ }
+
+ m_curveType->setButton(m_curvesWidget->curves()->getCurveType(channel));
+
+ m_curvesWidget->repaint(false);
+ m_histogramWidget->repaint(false);
+}
+
+void AdjustCurvesTool::slotScaleChanged(int scale)
+{
+ m_curvesWidget->m_scaleType = scale;
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+ m_curvesWidget->repaint(false);
+}
+
+void AdjustCurvesTool::slotCurveTypeChanged(int type)
+{
+ switch(type)
+ {
+ case SmoothDrawing:
+ {
+ m_curvesWidget->curves()->setCurveType(m_curvesWidget->m_channelType, ImageCurves::CURVE_SMOOTH);
+ m_pickerColorButtonGroup->setEnabled(true);
+ break;
+ }
+
+ case FreeDrawing:
+ {
+ m_curvesWidget->curves()->setCurveType(m_curvesWidget->m_channelType, ImageCurves::CURVE_FREE);
+ m_pickerColorButtonGroup->setEnabled(false);
+ break;
+ }
+ }
+
+ m_curvesWidget->curveTypeChanged();
+}
+
+void AdjustCurvesTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("adjustcurves Tool");
+
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+
+ m_curvesWidget->reset();
+
+ for (int i = 0 ; i < 5 ; i++)
+ {
+ m_curvesWidget->curves()->curvesChannelReset(i);
+ m_curvesWidget->curves()->setCurveType(i, (ImageCurves::CurveType)config->readNumEntry(TQString("CurveTypeChannel%1").arg(i),
+ ImageCurves::CURVE_SMOOTH));
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p = config->readPointEntry(TQString("CurveAjustmentChannel%1Point%2").arg(i).arg(j), &disable);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+
+ m_curvesWidget->curves()->setCurvePoint(i, j, p);
+ }
+
+ m_curvesWidget->curves()->curvesCalculateCurve(i);
+ }
+
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+ slotEffect();
+}
+
+void AdjustCurvesTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("adjustcurves Tool");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+
+ for (int i = 0 ; i < 5 ; i++)
+ {
+ config->writeEntry(TQString("CurveTypeChannel%1").arg(i), m_curvesWidget->curves()->getCurveType(i));
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint p = m_curvesWidget->curves()->getCurvePoint(i, j);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()/255);
+ p.setY(p.y()/255);
+ }
+
+ config->writeEntry(TQString("CurveAjustmentChannel%1Point%2").arg(i).arg(j), p);
+ }
+ }
+
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void AdjustCurvesTool::slotResetSettings()
+{
+ for (int channel = 0 ; channel < 5 ; channel++)
+ m_curvesWidget->curves()->curvesChannelReset(channel);
+
+ m_curvesWidget->reset();
+ slotEffect();
+ m_histogramWidget->reset();
+}
+
+void AdjustCurvesTool::slotLoadSettings()
+{
+ KURL loadCurvesFile;
+
+ loadCurvesFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Select Gimp Curves File to Load")) );
+ if( loadCurvesFile.isEmpty() )
+ return;
+
+ if ( m_curvesWidget->curves()->loadCurvesFromGimpCurvesFile( loadCurvesFile ) == false )
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot load from the Gimp curves text file."));
+ return;
+ }
+
+ // Refresh the current curves config.
+ slotChannelChanged(m_channelCB->currentItem());
+ slotEffect();
+}
+
+void AdjustCurvesTool::slotSaveAsSettings()
+{
+ KURL saveCurvesFile;
+
+ saveCurvesFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Gimp Curves File to Save")) );
+ if( saveCurvesFile.isEmpty() )
+ return;
+
+ if ( m_curvesWidget->curves()->saveCurvesToGimpCurvesFile( saveCurvesFile ) == false )
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot save to the Gimp curves text file."));
+ return;
+ }
+
+ // Refresh the current curves config.
+ slotChannelChanged(m_channelCB->currentItem());
+}
+
+} // NameSpace DigikamAdjustCurvesImagesPlugin
diff --git a/src/imageplugins/adjustcurves/adjustcurvestool.h b/src/imageplugins/adjustcurves/adjustcurvestool.h
new file mode 100644
index 00000000..4a380530
--- /dev/null
+++ b/src/imageplugins/adjustcurves/adjustcurvestool.h
@@ -0,0 +1,145 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-01
+ * Description : image histogram adjust curves.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ADJUSTCURVESTOOL_H
+#define ADJUSTCURVESTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+// Local includes.
+
+class TQComboBox;
+class TQPushButton;
+class TQHButtonGroup;
+
+namespace Digikam
+{
+class CurvesWidget;
+class HistogramWidget;
+class ColorGradientWidget;
+class EditorToolSettings;
+class ImageWidget;
+class DImg;
+class DColor;
+}
+
+namespace DigikamAdjustCurvesImagesPlugin
+{
+
+class AdjustCurvesTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ AdjustCurvesTool(TQObject *parent);
+ ~AdjustCurvesTool();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+
+private slots:
+
+ void slotSaveAsSettings();
+ void slotLoadSettings();
+ void slotEffect();
+ void slotResetSettings();
+ void slotResetCurrentChannel();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotCurveTypeChanged(int type);
+ void slotSpotColorChanged(const Digikam::DColor& color);
+ void slotColorSelectedFromTarget(const Digikam::DColor& color);
+ void slotPickerColorButtonActived();
+
+private:
+
+ enum ColorPicker
+ {
+ BlackTonal=0,
+ GrayTonal,
+ WhiteTonal
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel,
+ AlphaChannel
+ };
+
+ enum CurvesDrawingType
+ {
+ SmoothDrawing=0,
+ FreeDrawing
+ };
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ uchar *m_destinationPreviewData;
+
+ int m_histoSegments;
+ int m_currentPreviewMode;
+
+ TQComboBox *m_channelCB;
+
+ TQPushButton *m_resetButton;
+ TQPushButton *m_pickBlack;
+ TQPushButton *m_pickGray;
+ TQPushButton *m_pickWhite;
+ TQPushButton *m_curveFree;
+ TQPushButton *m_curveSmooth;
+
+ TQHButtonGroup *m_pickerColorButtonGroup;
+ TQHButtonGroup *m_scaleBG;
+ TQHButtonGroup *m_curveType;
+
+ Digikam::CurvesWidget *m_curvesWidget;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+ Digikam::ColorGradientWidget *m_vGradient;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+
+ Digikam::DImg *m_originalImage;
+};
+
+} // NameSpace DigikamAdjustCurvesImagesPlugin
+
+#endif /* ADJUSTCURVESTOOL_H */
diff --git a/src/imageplugins/adjustcurves/digikamimageplugin_adjustcurves.desktop b/src/imageplugins/adjustcurves/digikamimageplugin_adjustcurves.desktop
new file mode 100644
index 00000000..377c2a33
--- /dev/null
+++ b/src/imageplugins/adjustcurves/digikamimageplugin_adjustcurves.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_AdjustCurves
+Name[bg]=Приставка за снимки - Настройка на кривите
+Name[da]=Billedplugin_Kurvejustering
+Name[el]=ΠρόσθετοΕικόνας_ΠροσαρμογήΚαμπύλων
+Name[fi]=TasonsäätöKäyrä
+Name[hr]=Podešavanje krivulja
+Name[it]=PluginImmagini_RegolaCurve
+Name[nl]=Afbeeldingsplugin_CurvesAanpassen
+Name[sr]=Подешавање кривих
+Name[sr@Latn]=Podešavanje krivih
+Name[sv]=Insticksprogram för justering av kurvor
+Name[tr]=ResimEklentisi_EğriAyarla
+Name[xx]=xxImagePlugin_AdjustCurvesxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+
+Comment=Image histogram adjust curves plugin for digiKam
+Comment[bg]=Приставка на digiKam за настройка кривите на хистограмите на снимки
+Comment[ca]=Connector pel digiKam d'ajust de les corbes de l'histograma d'imatges
+Comment[da]=Plugin til histogramkurvejustering i Digikam
+Comment[de]=digiKam-Modul zur Justierung der Farbkurven
+Comment[el]=Πρόσθετο προσαρμογής των καμπύλων του ιστογράμματος εικόνας για το digiKam
+Comment[es]=Histograma de imágenes, plugin de ajuste de curvas para digiKam
+Comment[et]=DigiKami pildi histogrammi kõverate kohendamise plugin
+Comment[fa]=وصلۀ منحنیهای تنظیم سابقه‌نمای تصویر برای digiKam
+Comment[fi]=Muokkaa värikanavien raja-arvoja
+Comment[fr]=Module externe pour ajuster les courbes de l'histogramme dans digiKam
+Comment[gl]=Un plugin de digiKam para o axuste das curvas do histograma da imaxe
+Comment[hr]=digiKam dodatak za histogramsko podešavanje krivulja
+Comment[is]=Íforrit fyrir digiKam sem breytir ferlum (curves) í stuðlariti myndar
+Comment[it]=Plugin di regolazione delle curve degli istogrammi delle immagini per digiKam
+Comment[ja]=digiKam カーブ補正プラグイン
+Comment[nds]=digiKam-Moduul för't Topassen vun Histogramm-Klöörbagens
+Comment[nl]=Digikam-plugin voor curvesaanpassing van afbeeldingshistogram
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਚਿੱਤਰ ਹਿਸਟੋਗਰਾਮ ਅਨੁਕੂਲ ਚਾਪ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam dostosowująca krzywe i histogram dla obrazu
+Comment[pt]=Um 'plugin' do digiKam de ajuste de curvas do histograma da imagem
+Comment[pt_BR]=Plugin de ajuste de curvas do histograma da imagem
+Comment[ru]=Модуль digiKam подстройки кривых гистограммы изображения
+Comment[sk]=digiKam plugin histogramu kriviek úprav obrázku
+Comment[sr]=digiKam-ов прикључак за подешавање кривих хистограма слике
+Comment[sr@Latn]=digiKam-ov priključak za podešavanje krivih histograma slike
+Comment[sv]=Digikam insticksprogram för justering av kurvor i bildhistogram
+Comment[tr]=digiKam için resim histogram eğrileri ayarlama eklentisi
+Comment[uk]=Втулок коригування кривих гістограми зображень для digiKam
+Comment[vi]=Phần bổ sung biểu đồ tần xuất điều chỉnh đường cong ảnh cho digiKam
+Comment[xx]=xxImage histogram adjust curves plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_adjustcurves
+author=Caulier Gilles, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/adjustcurves/digikamimageplugin_adjustcurves_ui.rc b/src/imageplugins/adjustcurves/digikamimageplugin_adjustcurves_ui.rc
new file mode 100644
index 00000000..c87c2c1e
--- /dev/null
+++ b/src/imageplugins/adjustcurves/digikamimageplugin_adjustcurves_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_adjustcurves" >
+
+ <MenuBar>
+
+ <Menu name="Color" ><text>&amp;Color</text>
+ <Action name="imageplugin_adjustcurves" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action name="imageplugin_adjustcurves" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/adjustcurves/imageplugin_adjustcurves.cpp b/src/imageplugins/adjustcurves/imageplugin_adjustcurves.cpp
new file mode 100644
index 00000000..11b6e53f
--- /dev/null
+++ b/src/imageplugins/adjustcurves/imageplugin_adjustcurves.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-01
+ * Description : image histogram adjust curves.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "adjustcurvestool.h"
+#include "imageplugin_adjustcurves.h"
+#include "imageplugin_adjustcurves.moc"
+
+using namespace DigikamAdjustCurvesImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY( digikamimageplugin_adjustcurves,
+ KGenericFactory<ImagePlugin_AdjustCurves>("digikamimageplugin_adjustcurves"));
+
+ImagePlugin_AdjustCurves::ImagePlugin_AdjustCurves(TQObject *parent, const char*, const TQStringList&)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_AdjustCurves")
+{
+ m_curvesAction = new TDEAction(i18n("Curves Adjust..."), "adjustcurves",
+ CTRL+SHIFT+Key_M, // NOTE: Photoshop 7 use CTRL+M (but it's used in KDE to toogle menu bar).
+ this, TQ_SLOT(slotCurvesAdjust()),
+ actionCollection(), "imageplugin_adjustcurves");
+
+ setXMLFile("digikamimageplugin_adjustcurves_ui.rc");
+
+ DDebug() << "ImagePlugin_AdjustCurves plugin loaded" << endl;
+}
+
+ImagePlugin_AdjustCurves::~ImagePlugin_AdjustCurves()
+{
+}
+
+void ImagePlugin_AdjustCurves::setEnabledActions(bool enable)
+{
+ m_curvesAction->setEnabled(enable);
+}
+
+void ImagePlugin_AdjustCurves::slotCurvesAdjust()
+{
+ AdjustCurvesTool *curves = new AdjustCurvesTool(this);
+ loadTool(curves);
+}
diff --git a/src/imageplugins/adjustcurves/imageplugin_adjustcurves.h b/src/imageplugins/adjustcurves/imageplugin_adjustcurves.h
new file mode 100644
index 00000000..f8e43578
--- /dev/null
+++ b/src/imageplugins/adjustcurves/imageplugin_adjustcurves.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-01
+ * Description : image histogram adjust curves.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_ADJUSTCURVES_H
+#define IMAGEPLUGIN_ADJUSTCURVES_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_AdjustCurves : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_AdjustCurves(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_AdjustCurves();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotCurvesAdjust();
+
+private:
+
+ TDEAction *m_curvesAction;
+};
+
+#endif /* IMAGEPLUGIN_ADJUSTCURVES_H */
diff --git a/src/imageplugins/adjustlevels/Makefile.am b/src/imageplugins/adjustlevels/Makefile.am
new file mode 100644
index 00000000..2b04f4cc
--- /dev/null
+++ b/src/imageplugins/adjustlevels/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_adjustlevels_la_SOURCES = imageplugin_adjustlevels.cpp \
+ adjustlevelstool.cpp
+
+digikamimageplugin_adjustlevels_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_adjustlevels_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_adjustlevels.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_adjustlevels.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_adjustlevels_ui.rc
+
diff --git a/src/imageplugins/adjustlevels/adjustlevels.cpp b/src/imageplugins/adjustlevels/adjustlevels.cpp
new file mode 100644
index 00000000..72d5e46b
--- /dev/null
+++ b/src/imageplugins/adjustlevels/adjustlevels.cpp
@@ -0,0 +1,913 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-20
+ * Description : image histogram adjust levels.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqpainter.h>
+#include <tqcombobox.h>
+#include <tqspinbox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqtimer.h>
+#include <tqhbuttongroup.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <knuminput.h>
+#include <tdemessagebox.h>
+#include <tdeselect.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagehistogram.h"
+#include "imagelevels.h"
+#include "histogramwidget.h"
+#include "dimgimagefilters.h"
+#include "adjustlevels.h"
+#include "adjustlevels.moc"
+
+namespace DigikamAdjustLevelsImagesPlugin
+{
+
+AdjustLevelDialog::AdjustLevelDialog(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Adjust Color Levels"),
+ "adjustlevels", true, false)
+{
+ m_destinationPreviewData = 0L;
+
+ Digikam::ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sixteenBit = iface.originalSixteenBit();
+ bool hasAlpha = iface.originalHasAlpha();
+ m_originalImage = Digikam::DImg(w, h, sixteenBit, hasAlpha ,data);
+ delete [] data;
+
+ m_histoSegments = m_originalImage.sixteenBit() ? 65535 : 255;
+ m_levels = new Digikam::ImageLevels(m_originalImage.sixteenBit());
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Adjust Color Levels"),
+ digikam_version,
+ I18N_NOOP("An image-histogram-levels adjustment plugin for digiKam."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new Digikam::ImageWidget("adjustlevels Tool Dialog", plainPage(),
+ i18n("<p>Here you can see the image's "
+ "level-adjustments preview. You can pick a spot on the image "
+ "to see the corresponding level in the histogram."));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* grid = new TQGridLayout(gboxSettings, 16, 8, spacingHint(), 0);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ m_channelCB->insertItem( i18n("Alpha") );
+ m_channelCB->setCurrentText( i18n("Luminosity") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Here select the histogram channel to display:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"
+ "<b>Alpha</b>: display the alpha image-channel values. "
+ "This channel corresponds to the transparency value and "
+ "is supported by some image formats, such as PNG or TIF."));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Here select the histogram scale.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "The Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, gboxSettings, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing of the "
+ "selected image channel. This one is re-computed at any levels "
+ "settings changes."));
+
+ m_levelsHistogramWidget = new Digikam::HistogramWidget(256, 140, m_originalImage.bits(), m_originalImage.width(),
+ m_originalImage.height(), m_originalImage.sixteenBit(), gboxSettings, false);
+ TQWhatsThis::add( m_levelsHistogramWidget, i18n("<p>This is the histogram drawing of the selected channel "
+ "from original image"));
+
+ // -------------------------------------------------------------
+
+ m_hGradientMinInput = new KGradientSelector( TDESelector::Horizontal, gboxSettings );
+ m_hGradientMinInput->setFixedHeight( 20 );
+ m_hGradientMinInput->setMinValue(0);
+ m_hGradientMinInput->setMaxValue(m_histoSegments);
+ TQWhatsThis::add( m_hGradientMinInput, i18n("<p>Select the minimal intensity input value of the histogram."));
+ TQToolTip::add( m_hGradientMinInput, i18n( "Minimal intensity input." ) );
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMinInput->installEventFilter(this);
+
+ m_hGradientMaxInput = new KGradientSelector( TDESelector::Horizontal, gboxSettings );
+ m_hGradientMaxInput->setFixedHeight( 20 );
+ m_hGradientMaxInput->setMinValue(0);
+ m_hGradientMaxInput->setMaxValue(m_histoSegments);
+ TQWhatsThis::add( m_hGradientMaxInput, i18n("<p>Select the maximal intensity input value of the histogram."));
+ TQToolTip::add( m_hGradientMaxInput, i18n( "Maximal intensity input." ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxInput->installEventFilter(this);
+
+ m_minInput = new TQSpinBox(0, m_histoSegments, 1, gboxSettings);
+ m_minInput->setValue(0);
+ TQWhatsThis::add( m_minInput, i18n("<p>Select the minimal intensity input value of the histogram."));
+ TQToolTip::add( m_minInput, i18n( "Minimal intensity input." ) );
+
+ m_gammaInput = new KDoubleNumInput(gboxSettings);
+ m_gammaInput->setPrecision(2);
+ m_gammaInput->setRange(0.1, 3.0, 0.01);
+ m_gammaInput->setValue(1.0);
+ TQToolTip::add( m_gammaInput, i18n( "Gamma input value." ) );
+ TQWhatsThis::add( m_gammaInput, i18n("<p>Select the gamma input value."));
+
+ m_maxInput = new TQSpinBox(0, m_histoSegments, 1, gboxSettings);
+ m_maxInput->setValue(m_histoSegments);
+ TQToolTip::add( m_maxInput, i18n( "Maximal intensity input." ) );
+ TQWhatsThis::add( m_maxInput, i18n("<p>Select the maximal intensity input value of the histogram."));
+
+ m_hGradientMinOutput = new KGradientSelector( TDESelector::Horizontal, gboxSettings );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ TQWhatsThis::add( m_hGradientMinOutput, i18n("<p>Select the minimal intensity output value of the histogram."));
+ TQToolTip::add( m_hGradientMinOutput, i18n( "Minimal intensity output." ) );
+ m_hGradientMinOutput->setFixedHeight( 20 );
+ m_hGradientMinOutput->setMinValue(0);
+ m_hGradientMinOutput->setMaxValue(m_histoSegments);
+ m_hGradientMinOutput->installEventFilter(this);
+
+ m_hGradientMaxOutput = new KGradientSelector( TDESelector::Horizontal, gboxSettings );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ TQWhatsThis::add( m_hGradientMaxOutput, i18n("<p>Select the maximal intensity output value of the histogram."));
+ TQToolTip::add( m_hGradientMaxOutput, i18n( "Maximal intensity output." ) );
+ m_hGradientMaxOutput->setFixedHeight( 20 );
+ m_hGradientMaxOutput->setMinValue(0);
+ m_hGradientMaxOutput->setMaxValue(m_histoSegments);
+ m_hGradientMaxOutput->installEventFilter(this);
+
+ m_minOutput = new TQSpinBox(0, m_histoSegments, 1, gboxSettings);
+ m_minOutput->setValue(0);
+ TQToolTip::add( m_minOutput, i18n( "Minimal intensity output." ) );
+ TQWhatsThis::add( m_minOutput, i18n("<p>Select the minimal intensity output value of the histogram."));
+
+ m_maxOutput = new TQSpinBox(0, m_histoSegments, 1, gboxSettings);
+ m_maxOutput->setValue(m_histoSegments);
+ TQToolTip::add( m_maxOutput, i18n( "Maximal intensity output." ) );
+ TQWhatsThis::add( m_maxOutput, i18n("<p>Select the maximal intensity output value of the histogram."));
+
+ // -------------------------------------------------------------
+
+ m_pickerColorButtonGroup = new TQHButtonGroup(gboxSettings);
+ m_pickBlack = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickBlack, BlackTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-black", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-black", "color-picker-black.png");
+ m_pickBlack->setPixmap( TQPixmap( directory + "color-picker-black.png" ) );
+ m_pickBlack->setToggleButton(true);
+ TQToolTip::add( m_pickBlack, i18n( "All channels shadow tone color picker" ) );
+ TQWhatsThis::add( m_pickBlack, i18n("<p>With this button, you can pick the color from original image used to set <b>Shadow Tone</b> "
+ "levels input on Red, Green, Blue, and Luminosity channels."));
+ m_pickGray = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickGray, GrayTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-gray", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-gray", "color-picker-gray.png");
+ m_pickGray->setPixmap( TQPixmap( directory + "color-picker-gray.png" ) );
+ m_pickGray->setToggleButton(true);
+ TQToolTip::add( m_pickGray, i18n( "All channels middle tone color picker" ) );
+ TQWhatsThis::add( m_pickGray, i18n("<p>With this button, you can pick the color from original image used to set <b>Middle Tone</b> "
+ "levels input on Red, Green, Blue, and Luminosity channels."));
+ m_pickWhite = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickWhite, WhiteTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-white", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-white", "color-picker-white.png");
+ m_pickWhite->setPixmap( TQPixmap( directory + "color-picker-white.png" ) );
+ m_pickWhite->setToggleButton(true);
+ TQToolTip::add( m_pickWhite, i18n( "All channels highlight tone color picker" ) );
+ TQWhatsThis::add( m_pickWhite, i18n("<p>With this button, you can pick the color from original image used to set <b>Highlight Tone</b> "
+ "levels input on Red, Green, Blue, and Luminosity channels."));
+ m_pickerColorButtonGroup->setExclusive(true);
+ m_pickerColorButtonGroup->setFrameShape(TQFrame::NoFrame);
+
+ m_autoButton = new TQPushButton(gboxSettings);
+ m_autoButton->setPixmap(kapp->iconLoader()->loadIcon("system-run", (TDEIcon::Group)TDEIcon::Toolbar)); TQToolTip::add( m_autoButton, i18n( "Adjust all levels automatically." ) );
+ TQWhatsThis::add( m_autoButton, i18n("<p>If you press this button, all channel levels will be adjusted "
+ "automatically."));
+
+ m_resetButton = new TQPushButton(i18n("&Reset"), gboxSettings);
+ m_resetButton->setPixmap(kapp->iconLoader()->loadIcon("reload_page", (TDEIcon::Group)TDEIcon::Toolbar));
+ TQToolTip::add( m_resetButton, i18n( "Reset current channel levels' values." ) );
+ TQWhatsThis::add( m_resetButton, i18n("<p>If you press this button, all levels' values "
+ "from the current selected channel "
+ "will be reset to the default values."));
+
+ TQLabel *space = new TQLabel(gboxSettings);
+ space->setFixedWidth(spacingHint());
+
+ TQHBoxLayout* l3 = new TQHBoxLayout();
+ l3->addWidget(m_pickerColorButtonGroup);
+ l3->addWidget(m_autoButton);
+ l3->addWidget(space);
+ l3->addWidget(m_resetButton);
+ l3->addStretch(10);
+
+ // -------------------------------------------------------------
+
+ grid->addMultiCellLayout(l1, 0, 0, 0, 6);
+ grid->setRowSpacing(1, spacingHint());
+ grid->addMultiCellWidget(m_histogramWidget, 2, 2, 1, 5);
+ grid->setRowSpacing(3, spacingHint());
+ grid->addMultiCellWidget(m_levelsHistogramWidget, 4, 4, 1, 5);
+ grid->addMultiCellWidget(m_hGradientMinInput, 5, 5, 0, 6);
+ grid->addMultiCellWidget(m_minInput, 5, 5, 8, 8);
+ grid->setRowSpacing(6, spacingHint());
+ grid->addMultiCellWidget(m_hGradientMaxInput, 7, 7, 0, 6);
+ grid->addMultiCellWidget(m_maxInput, 7, 7, 8, 8);
+ grid->setRowSpacing(8, spacingHint());
+ grid->addMultiCellWidget(m_gammaInput, 9, 9, 0, 8);
+ grid->setRowSpacing(10, spacingHint());
+ grid->addMultiCellWidget(m_hGradientMinOutput, 11, 11, 0, 6);
+ grid->addMultiCellWidget(m_minOutput, 11, 11, 8, 8);
+ grid->setRowSpacing(12, spacingHint());
+ grid->addMultiCellWidget(m_hGradientMaxOutput, 13, 13, 0, 6);
+ grid->addMultiCellWidget(m_maxOutput, 13, 13, 8, 8);
+ grid->setRowSpacing(14, spacingHint());
+ grid->addMultiCellLayout(l3, 15, 15, 0, 8);
+ grid->setRowStretch(16, 10);
+ grid->setColStretch(2, 10);
+ grid->setColSpacing(0, 5);
+ grid->setColSpacing(6, 5);
+ grid->setColSpacing(7, spacingHint());
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+ // Channels and scale selection slots.
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotSpotColorChanged( const Digikam::DColor & )));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+ // Color sliders and spinbox slots.
+
+ connect(m_hGradientMinInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustMinInputSpinBox(int)));
+
+ connect(m_minInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotAdjustSliders()));
+
+ connect(m_gammaInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotGammaInputchanged(double)));
+
+ connect(m_hGradientMaxInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustMaxInputSpinBox(int)));
+
+ connect(m_maxInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotAdjustSliders()));
+
+ connect(m_hGradientMinOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustMinOutputSpinBox(int)));
+
+ connect(m_minOutput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotAdjustSliders()));
+
+ connect(m_hGradientMaxOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustMaxOutputSpinBox(int)));
+
+ connect(m_maxOutput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotAdjustSliders()));
+
+ // -------------------------------------------------------------
+ // Bouttons slots.
+
+ connect(m_autoButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotAutoLevels()));
+
+ connect(m_resetButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotResetCurrentChannel()));
+
+ connect(m_pickerColorButtonGroup, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotPickerColorButtonActived()));
+
+}
+
+AdjustLevelDialog::~AdjustLevelDialog()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+ delete m_levelsHistogramWidget;
+ delete m_levels;
+}
+
+void AdjustLevelDialog::slotPickerColorButtonActived()
+{
+ // Save previous rendering mode and toggle to original image.
+ m_currentPreviewMode = m_previewWidget->getRenderingPreviewMode();
+ m_previewWidget->setRenderingPreviewMode(Digikam::ImageGuideWidget::PreviewOriginalImage);
+}
+
+void AdjustLevelDialog::slotSpotColorChanged(const Digikam::DColor &color)
+{
+ if ( m_pickBlack->isOn() )
+ {
+ // Black tonal levels point.
+ m_levels->levelsBlackToneAdjustByColors(m_channelCB->currentItem(), color);
+ m_pickBlack->setOn(false);
+ }
+ else if ( m_pickGray->isOn() )
+ {
+ // Gray tonal levels point.
+ m_levels->levelsGrayToneAdjustByColors(m_channelCB->currentItem(), color);
+ m_pickGray->setOn(false);
+ }
+ else if ( m_pickWhite->isOn() )
+ {
+ // White tonal levels point.
+ m_levels->levelsWhiteToneAdjustByColors(m_channelCB->currentItem(), color);
+ m_pickWhite->setOn(false);
+ }
+ else
+ {
+ m_levelsHistogramWidget->setHistogramGuideByColor(color);
+ return;
+ }
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+
+ // restore previous rendering mode.
+ m_previewWidget->setRenderingPreviewMode(m_currentPreviewMode);
+
+ slotEffect();
+}
+
+void AdjustLevelDialog::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void AdjustLevelDialog::slotGammaInputchanged(double val)
+{
+ blockSignals(true);
+ m_levels->setLevelGammaValue(m_channelCB->currentItem(), val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelDialog::slotAdjustMinInputSpinBox(int val)
+{
+ blockSignals(true);
+
+ if ( val < m_hGradientMaxInput->value() )
+ val = m_hGradientMaxInput->value();
+
+ m_minInput->setValue(m_histoSegments - val);
+ m_hGradientMinInput->setValue( val );
+ m_levels->setLevelLowInputValue(m_channelCB->currentItem(), m_histoSegments - val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelDialog::slotAdjustMaxInputSpinBox(int val)
+{
+ blockSignals(true);
+
+ if ( val > m_hGradientMinInput->value() )
+ val = m_hGradientMinInput->value();
+
+ m_maxInput->setValue(m_histoSegments - val);
+ m_hGradientMaxInput->setValue( val );
+ m_levels->setLevelHighInputValue(m_channelCB->currentItem(), m_histoSegments - val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelDialog::slotAdjustMinOutputSpinBox(int val)
+{
+ blockSignals(true);
+
+ if ( val < m_hGradientMaxOutput->value() )
+ val = m_hGradientMaxOutput->value();
+
+ m_minOutput->setValue(m_histoSegments - val);
+ m_hGradientMinOutput->setValue( val );
+ m_levels->setLevelLowOutputValue(m_channelCB->currentItem(), m_histoSegments - val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelDialog::slotAdjustMaxOutputSpinBox(int val)
+{
+ blockSignals(true);
+
+ if ( val > m_hGradientMinOutput->value() )
+ val = m_hGradientMinOutput->value();
+
+ m_maxOutput->setValue(m_histoSegments - val);
+ m_hGradientMaxOutput->setValue( val );
+ m_levels->setLevelHighOutputValue(m_channelCB->currentItem(), m_histoSegments - val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelDialog::slotAdjustSliders()
+{
+ adjustSliders(m_minInput->value(), m_gammaInput->value(),
+ m_maxInput->value(), m_minOutput->value(),
+ m_maxOutput->value());
+}
+
+void AdjustLevelDialog::adjustSliders(int minIn, double gamIn, int maxIn, int minOut, int maxOut)
+{
+ m_hGradientMinInput->setValue(m_histoSegments - minIn);
+ m_hGradientMaxInput->setValue(m_histoSegments - maxIn);
+ m_gammaInput->setValue(gamIn);
+ m_hGradientMinOutput->setValue(m_histoSegments - minOut);
+ m_hGradientMaxOutput->setValue(m_histoSegments - maxOut);
+}
+
+void AdjustLevelDialog::slotResetCurrentChannel()
+{
+ m_levels->levelsChannelReset(m_channelCB->currentItem());
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+ m_levelsHistogramWidget->reset();
+
+ slotEffect();
+ m_histogramWidget->reset();
+}
+
+void AdjustLevelDialog::slotAutoLevels()
+{
+ // Calculate Auto levels.
+ m_levels->levelsAuto(m_levelsHistogramWidget->m_imageHistogram);
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+
+ slotEffect();
+}
+
+void AdjustLevelDialog::slotEffect()
+{
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *orgData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ // Create the new empty destination image data space.
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ m_destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)];
+
+ // Calculate the LUT to apply on the image.
+ m_levels->levelsLutSetup(Digikam::ImageHistogram::AlphaChannel);
+
+ // Apply the lut to the image.
+ m_levels->levelsLutProcess(orgData, m_destinationPreviewData, w, h);
+
+ iface->putPreviewImage(m_destinationPreviewData);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ delete [] orgData;
+}
+
+void AdjustLevelDialog::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *orgData = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ // Create the new empty destination image data space.
+ uchar* desData = new uchar[w*h*(sb ? 8 : 4)];
+
+ // Calculate the LUT to apply on the image.
+ m_levels->levelsLutSetup(Digikam::ImageHistogram::AlphaChannel);
+
+ // Apply the lut to the image.
+ m_levels->levelsLutProcess(orgData, desData, w, h);
+
+ iface->putOriginalImage(i18n("Adjust Level"), desData);
+ kapp->restoreOverrideCursor();
+
+ delete [] orgData;
+ delete [] desData;
+ accept();
+}
+
+void AdjustLevelDialog::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_levelsHistogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_levelsHistogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "red" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "red" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "red" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_levelsHistogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "green" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "green" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "green" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_levelsHistogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+
+ case AlphaChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::AlphaChannelHistogram;
+ m_levelsHistogramWidget->m_channelType = Digikam::HistogramWidget::AlphaChannelHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+ }
+
+ adjustSliders(m_levels->getLevelLowInputValue(channel),
+ m_levels->getLevelGammaValue(channel),
+ m_levels->getLevelHighInputValue(channel),
+ m_levels->getLevelLowOutputValue(channel),
+ m_levels->getLevelHighOutputValue(channel));
+
+ m_levelsHistogramWidget->repaint(false);
+ m_histogramWidget->repaint(false);
+}
+
+void AdjustLevelDialog::slotScaleChanged(int scale)
+{
+ m_levelsHistogramWidget->m_scaleType = scale;
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+ m_levelsHistogramWidget->repaint(false);
+}
+
+void AdjustLevelDialog::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("adjustlevels Tool Dialog");
+
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+
+ for (int i = 0 ; i < 5 ; i++)
+ {
+ bool sb = m_originalImage.sixteenBit();
+ int max = sb ? 65535 : 255;
+ double gamma = config->readDoubleNumEntry(TQString("GammaChannel%1").arg(i), 1.0);
+ int lowInput = config->readNumEntry(TQString("LowInputChannel%1").arg(i), 0);
+ int lowOutput = config->readNumEntry(TQString("LowOutputChannel%1").arg(i), 0);
+ int highInput = config->readNumEntry(TQString("HighInputChannel%1").arg(i), max);
+ int highOutput = config->readNumEntry(TQString("HighOutputChannel%1").arg(i), max);
+
+ m_levels->setLevelGammaValue(i, gamma);
+ m_levels->setLevelLowInputValue(i, sb ? lowInput*255 : lowInput);
+ m_levels->setLevelHighInputValue(i, sb ? highInput*255 : highInput);
+ m_levels->setLevelLowOutputValue(i, sb ? lowOutput*255 : lowOutput);
+ m_levels->setLevelHighOutputValue(i, sb ? highOutput*255 : highOutput);
+ }
+
+ m_levelsHistogramWidget->reset();
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+
+ // This is mandatory here to set spinbox values because slot connections
+ // can be not set completely at plugin startup.
+ m_minInput->setValue(m_levels->getLevelLowInputValue(m_channelCB->currentItem()));
+ m_minOutput->setValue(m_levels->getLevelLowOutputValue(m_channelCB->currentItem()));
+ m_maxInput->setValue(m_levels->getLevelHighInputValue(m_channelCB->currentItem()));
+ m_maxOutput->setValue(m_levels->getLevelHighOutputValue(m_channelCB->currentItem()));
+}
+
+void AdjustLevelDialog::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("adjustlevels Tool Dialog");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+
+ for (int i = 0 ; i < 5 ; i++)
+ {
+ bool sb = m_originalImage.sixteenBit();
+ double gamma = m_levels->getLevelGammaValue(i);
+ int lowInput = m_levels->getLevelLowInputValue(i);
+ int lowOutput = m_levels->getLevelLowOutputValue(i);
+ int highInput = m_levels->getLevelHighInputValue(i);
+ int highOutput = m_levels->getLevelHighOutputValue(i);
+
+ config->writeEntry(TQString("GammaChannel%1").arg(i), gamma);
+ config->writeEntry(TQString("LowInputChannel%1").arg(i), sb ? lowInput/255 : lowInput);
+ config->writeEntry(TQString("LowOutputChannel%1").arg(i), sb ? lowOutput/255 : lowOutput);
+ config->writeEntry(TQString("HighInputChannel%1").arg(i), sb ? highInput/255 : highInput);
+ config->writeEntry(TQString("HighOutputChannel%1").arg(i), sb ? highOutput/255 : highOutput);
+ }
+
+ config->sync();
+}
+
+void AdjustLevelDialog::resetValues()
+{
+ for (int channel = 0 ; channel < 5 ; ++channel)
+ m_levels->levelsChannelReset(channel);
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+ m_levelsHistogramWidget->reset();
+ m_histogramWidget->reset();
+}
+
+// Load all settings.
+void AdjustLevelDialog::slotUser3()
+{
+ KURL loadLevelsFile;
+
+ loadLevelsFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Select Gimp Levels File to Load")) );
+ if( loadLevelsFile.isEmpty() )
+ return;
+
+ if ( m_levels->loadLevelsFromGimpLevelsFile( loadLevelsFile ) == false )
+ {
+ KMessageBox::error(this, i18n("Cannot load from the Gimp levels text file."));
+ return;
+ }
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+}
+
+// Save all settings.
+void AdjustLevelDialog::slotUser2()
+{
+ KURL saveLevelsFile;
+
+ saveLevelsFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Gimp Levels File to Save")) );
+ if( saveLevelsFile.isEmpty() )
+ return;
+
+ if ( m_levels->saveLevelsToGimpLevelsFile( saveLevelsFile ) == false )
+ {
+ KMessageBox::error(this, i18n("Cannot save to the Gimp levels text file."));
+ return;
+ }
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+}
+
+// See B.K.O #146636: use event filter with all level slider to display a
+// guide over level histogram.
+bool AdjustLevelDialog::eventFilter(TQObject *obj, TQEvent *ev)
+{
+ if ( obj == m_hGradientMinInput )
+ {
+ if ( ev->type() == TQEvent::MouseButtonPress)
+ {
+ connect(m_minInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowHistogramGuide(int)));
+
+ return false;
+ }
+ if ( ev->type() == TQEvent::MouseButtonRelease)
+ {
+ disconnect(m_minInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowHistogramGuide(int)));
+
+ m_levelsHistogramWidget->reset();
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ if ( obj == m_hGradientMaxInput )
+ {
+ if ( ev->type() == TQEvent::MouseButtonPress)
+ {
+ connect(m_maxInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowHistogramGuide(int)));
+
+ return false;
+ }
+ if ( ev->type() == TQEvent::MouseButtonRelease)
+ {
+ disconnect(m_maxInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowHistogramGuide(int)));
+
+ m_levelsHistogramWidget->reset();
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ if ( obj == m_hGradientMinOutput )
+ {
+ if ( ev->type() == TQEvent::MouseButtonPress)
+ {
+ connect(m_minOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowHistogramGuide(int)));
+
+ return false;
+ }
+ if ( ev->type() == TQEvent::MouseButtonRelease)
+ {
+ disconnect(m_minOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowHistogramGuide(int)));
+
+ m_levelsHistogramWidget->reset();
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ if ( obj == m_hGradientMaxOutput )
+ {
+ if ( ev->type() == TQEvent::MouseButtonPress)
+ {
+ connect(m_maxOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowHistogramGuide(int)));
+
+ return false;
+ }
+ if ( ev->type() == TQEvent::MouseButtonRelease)
+ {
+ disconnect(m_maxOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowHistogramGuide(int)));
+
+ m_levelsHistogramWidget->reset();
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // pass the event on to the parent class
+ return KDialogBase::eventFilter(obj, ev);
+ }
+}
+
+void AdjustLevelDialog::slotShowHistogramGuide(int v)
+{
+ Digikam::DColor color(v, v, v, v, m_originalImage.sixteenBit());
+ m_levelsHistogramWidget->setHistogramGuideByColor(color);
+}
+
+} // NameSpace DigikamAdjustLevelsImagesPlugin
diff --git a/src/imageplugins/adjustlevels/adjustlevels.h b/src/imageplugins/adjustlevels/adjustlevels.h
new file mode 100644
index 00000000..1b1ad9be
--- /dev/null
+++ b/src/imageplugins/adjustlevels/adjustlevels.h
@@ -0,0 +1,153 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-20
+ * Description : image histogram adjust levels.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ADJUSTLEVELS_H
+#define ADJUSTLEVELS_H
+
+// Digikam includes.
+
+#include "imagedlgbase.h"
+#include "dimg.h"
+
+class TQComboBox;
+class TQSpinBox;
+class TQPushButton;
+class TQHButtonGroup;
+
+class KDoubleSpinBox;
+class KGradientSelector;
+class KDoubleNumInput;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ImageWidget;
+class ImageLevels;
+}
+
+namespace DigikamAdjustLevelsImagesPlugin
+{
+
+class AdjustLevelDialog : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ AdjustLevelDialog(TQWidget *parent);
+ ~AdjustLevelDialog();
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void finalRendering();
+ void adjustSliders(int minIn, double gamIn, int maxIn, int minOut, int maxOut);
+ bool eventFilter(TQObject *o, TQEvent *e);
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+ void slotEffect();
+ void slotResetCurrentChannel();
+ void slotAutoLevels();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotAdjustSliders();
+ void slotGammaInputchanged(double val);
+ void slotAdjustMinInputSpinBox(int val);
+ void slotAdjustMaxInputSpinBox(int val);
+ void slotAdjustMinOutputSpinBox(int val);
+ void slotAdjustMaxOutputSpinBox(int val);
+ void slotSpotColorChanged(const Digikam::DColor &color);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+ void slotPickerColorButtonActived();
+ void slotShowHistogramGuide(int v);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel,
+ AlphaChannel
+ };
+
+ enum ColorPicker
+ {
+ BlackTonal=0,
+ GrayTonal,
+ WhiteTonal
+ };
+
+ uchar *m_destinationPreviewData;
+
+ int m_histoSegments;
+ int m_currentPreviewMode;
+
+ TQComboBox *m_channelCB;
+
+ TQSpinBox *m_minInput;
+ TQSpinBox *m_maxInput;
+ TQSpinBox *m_minOutput;
+ TQSpinBox *m_maxOutput;
+
+ TQPushButton *m_autoButton;
+ TQPushButton *m_resetButton;
+ TQPushButton *m_pickBlack;
+ TQPushButton *m_pickGray;
+ TQPushButton *m_pickWhite;
+
+ TQHButtonGroup *m_pickerColorButtonGroup;
+ TQHButtonGroup *m_scaleBG;
+
+ KDoubleNumInput *m_gammaInput;
+
+ KGradientSelector *m_hGradientMinInput;
+ KGradientSelector *m_hGradientMaxInput;
+ KGradientSelector *m_hGradientMinOutput;
+ KGradientSelector *m_hGradientMaxOutput;
+
+ Digikam::HistogramWidget *m_levelsHistogramWidget;
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ImageLevels *m_levels;
+ Digikam::DImg m_originalImage;
+};
+
+} // NameSpace DigikamAdjustLevelsImagesPlugin
+
+#endif /* ADJUSTLEVELS_H */
diff --git a/src/imageplugins/adjustlevels/adjustlevelstool.cpp b/src/imageplugins/adjustlevels/adjustlevelstool.cpp
new file mode 100644
index 00000000..28066774
--- /dev/null
+++ b/src/imageplugins/adjustlevels/adjustlevelstool.cpp
@@ -0,0 +1,901 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-20
+ * Description : image histogram adjust levels.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqframe.h>
+#include <tqgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqhgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqlayout.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqpushbutton.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdepopupmenu.h>
+#include <tdeselect.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "editortoolsettings.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagehistogram.h"
+#include "imagelevels.h"
+#include "histogramwidget.h"
+#include "dimgimagefilters.h"
+#include "adjustlevelstool.h"
+#include "adjustlevelstool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamAdjustLevelsImagesPlugin
+{
+
+AdjustLevelsTool::AdjustLevelsTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ m_destinationPreviewData = 0;
+
+ ImageIface iface(0, 0);
+ m_originalImage = iface.getOriginalImg();
+
+ m_histoSegments = m_originalImage->sixteenBit() ? 65535 : 255;
+ m_levels = new ImageLevels(m_originalImage->sixteenBit());
+
+ setName("adjustlevels");
+ setToolName(i18n("Adjust Levels"));
+ setToolIcon(SmallIcon("adjustlevels"));
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImageWidget("adjustlevels Tool", 0,
+ i18n("<p>Here you can see the image's "
+ "level-adjustments preview. You can pick a spot on the image "
+ "to see the corresponding level in the histogram."));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 20, 6);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), m_gboxSettings->plainPage());
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, m_gboxSettings->plainPage() );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ m_channelCB->insertItem( i18n("Alpha") );
+ m_channelCB->setCurrentText( i18n("Luminosity") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Here select the histogram channel to display:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"
+ "<b>Alpha</b>: display the alpha image-channel values. "
+ "This channel corresponds to the transparency value and "
+ "is supported by some image formats, such as PNG or TIF."));
+
+ m_scaleBG = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Here select the histogram scale.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "The Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ m_histogramWidget = new HistogramWidget(256, 140, m_gboxSettings->plainPage(), false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing of the "
+ "selected image channel. This one is re-computed at any levels "
+ "settings changes."));
+
+ m_levelsHistogramWidget = new HistogramWidget(256, 140, m_originalImage->bits(), m_originalImage->width(),
+ m_originalImage->height(), m_originalImage->sixteenBit(), m_gboxSettings, false);
+ TQWhatsThis::add( m_levelsHistogramWidget, i18n("<p>This is the histogram drawing of the selected channel "
+ "from original image"));
+
+ // -------------------------------------------------------------
+
+ m_hGradientMinInput = new KGradientSelector( TDESelector::Horizontal, m_gboxSettings->plainPage() );
+ m_hGradientMinInput->setFixedHeight( 20 );
+ m_hGradientMinInput->setMinValue(0);
+ m_hGradientMinInput->setMaxValue(m_histoSegments);
+ TQWhatsThis::add( m_hGradientMinInput, i18n("<p>Select the minimal intensity input value of the histogram."));
+ TQToolTip::add( m_hGradientMinInput, i18n( "Minimal intensity input." ) );
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMinInput->installEventFilter(this);
+
+ m_hGradientMaxInput = new KGradientSelector( TDESelector::Horizontal, m_gboxSettings->plainPage() );
+ m_hGradientMaxInput->setFixedHeight( 20 );
+ m_hGradientMaxInput->setMinValue(0);
+ m_hGradientMaxInput->setMaxValue(m_histoSegments);
+ TQWhatsThis::add( m_hGradientMaxInput, i18n("<p>Select the maximal intensity input value of the histogram."));
+ TQToolTip::add( m_hGradientMaxInput, i18n( "Maximal intensity input." ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxInput->installEventFilter(this);
+
+ m_minInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_minInput->input()->setRange(0, m_histoSegments, 1, false);
+ m_minInput->setDefaultValue(0);
+ TQWhatsThis::add( m_minInput, i18n("<p>Select the minimal intensity input value of the histogram."));
+ TQToolTip::add( m_minInput, i18n( "Minimal intensity input." ) );
+
+ m_gammaInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_gammaInput->setPrecision(2);
+ m_gammaInput->setRange(0.1, 3.0, 0.01, true);
+ m_gammaInput->setDefaultValue(1.0);
+ TQToolTip::add( m_gammaInput, i18n( "Gamma input value." ) );
+ TQWhatsThis::add( m_gammaInput, i18n("<p>Select the gamma input value."));
+
+ m_maxInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_maxInput->input()->setRange(0, m_histoSegments, 1, false);
+ m_maxInput->setDefaultValue(m_histoSegments);
+ TQToolTip::add( m_maxInput, i18n( "Maximal intensity input." ) );
+ TQWhatsThis::add( m_maxInput, i18n("<p>Select the maximal intensity input value of the histogram."));
+
+ m_hGradientMinOutput = new KGradientSelector( TDESelector::Horizontal, m_gboxSettings->plainPage() );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ TQWhatsThis::add( m_hGradientMinOutput, i18n("<p>Select the minimal intensity output value of the histogram."));
+ TQToolTip::add( m_hGradientMinOutput, i18n( "Minimal intensity output." ) );
+ m_hGradientMinOutput->setFixedHeight( 20 );
+ m_hGradientMinOutput->setMinValue(0);
+ m_hGradientMinOutput->setMaxValue(m_histoSegments);
+ m_hGradientMinOutput->installEventFilter(this);
+
+ m_hGradientMaxOutput = new KGradientSelector( TDESelector::Horizontal, m_gboxSettings->plainPage() );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ TQWhatsThis::add( m_hGradientMaxOutput, i18n("<p>Select the maximal intensity output value of the histogram."));
+ TQToolTip::add( m_hGradientMaxOutput, i18n( "Maximal intensity output." ) );
+ m_hGradientMaxOutput->setFixedHeight( 20 );
+ m_hGradientMaxOutput->setMinValue(0);
+ m_hGradientMaxOutput->setMaxValue(m_histoSegments);
+ m_hGradientMaxOutput->installEventFilter(this);
+
+ m_minOutput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_minOutput->input()->setRange(0, m_histoSegments, 1, false);
+ m_minOutput->setDefaultValue(0);
+ TQToolTip::add( m_minOutput, i18n( "Minimal intensity output." ) );
+ TQWhatsThis::add( m_minOutput, i18n("<p>Select the minimal intensity output value of the histogram."));
+
+ m_maxOutput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_maxOutput->input()->setRange(0, m_histoSegments, 1, false);
+ m_maxOutput->setDefaultValue(m_histoSegments);
+ TQToolTip::add( m_maxOutput, i18n( "Maximal intensity output." ) );
+ TQWhatsThis::add( m_maxOutput, i18n("<p>Select the maximal intensity output value of the histogram."));
+
+ // -------------------------------------------------------------
+
+ m_pickerColorButtonGroup = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_pickBlack = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickBlack, BlackTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-black", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-black", "color-picker-black.png");
+ m_pickBlack->setPixmap( TQPixmap( directory + "color-picker-black.png" ) );
+ m_pickBlack->setToggleButton(true);
+ TQToolTip::add( m_pickBlack, i18n( "All channels shadow tone color picker" ) );
+ TQWhatsThis::add( m_pickBlack, i18n("<p>With this button, you can pick the color from original image used to set <b>Shadow Tone</b> "
+ "levels input on Red, Green, Blue, and Luminosity channels."));
+ m_pickGray = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickGray, GrayTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-gray", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-grey", "color-picker-grey.png");
+ m_pickGray->setPixmap( TQPixmap( directory + "color-picker-grey.png" ) );
+ m_pickGray->setToggleButton(true);
+ TQToolTip::add( m_pickGray, i18n( "All channels middle tone color picker" ) );
+ TQWhatsThis::add( m_pickGray, i18n("<p>With this button, you can pick the color from original image used to set <b>Middle Tone</b> "
+ "levels input on Red, Green, Blue, and Luminosity channels."));
+ m_pickWhite = new TQPushButton(m_pickerColorButtonGroup);
+ m_pickerColorButtonGroup->insert(m_pickWhite, WhiteTonal);
+ TDEGlobal::dirs()->addResourceType("color-picker-white", TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-white", "color-picker-white.png");
+ m_pickWhite->setPixmap( TQPixmap( directory + "color-picker-white.png" ) );
+ m_pickWhite->setToggleButton(true);
+ TQToolTip::add( m_pickWhite, i18n( "All channels highlight tone color picker" ) );
+ TQWhatsThis::add( m_pickWhite, i18n("<p>With this button, you can pick the color from original image used to set <b>Highlight Tone</b> "
+ "levels input on Red, Green, Blue, and Luminosity channels."));
+ m_pickerColorButtonGroup->setExclusive(true);
+ m_pickerColorButtonGroup->setFrameShape(TQFrame::NoFrame);
+
+ m_autoButton = new TQPushButton(m_gboxSettings->plainPage());
+ m_autoButton->setPixmap(kapp->iconLoader()->loadIcon("system-run", (TDEIcon::Group)TDEIcon::Toolbar)); TQToolTip::add( m_autoButton, i18n( "Adjust all levels automatically." ) );
+ TQWhatsThis::add( m_autoButton, i18n("<p>If you press this button, all channel levels will be adjusted "
+ "automatically."));
+
+ m_resetButton = new TQPushButton(i18n("&Reset"), m_gboxSettings->plainPage());
+ m_resetButton->setPixmap(kapp->iconLoader()->loadIcon("reload_page", (TDEIcon::Group)TDEIcon::Toolbar));
+ TQToolTip::add( m_resetButton, i18n( "Reset current channel levels' values." ) );
+ TQWhatsThis::add( m_resetButton, i18n("<p>If you press this button, all levels' values "
+ "from the current selected channel "
+ "will be reset to the default values."));
+
+ TQLabel *space = new TQLabel(m_gboxSettings->plainPage());
+ space->setFixedWidth(m_gboxSettings->spacingHint());
+
+ TQHBoxLayout* l3 = new TQHBoxLayout();
+ l3->addWidget(m_pickerColorButtonGroup);
+ l3->addWidget(m_autoButton);
+ l3->addWidget(space);
+ l3->addWidget(m_resetButton);
+ l3->addStretch(10);
+
+ // -------------------------------------------------------------
+
+ grid->addMultiCellLayout(l1, 0, 0, 0, 6);
+ grid->addMultiCellWidget(m_histogramWidget, 2, 2, 1, 5);
+ grid->addMultiCellWidget(m_levelsHistogramWidget, 4, 4, 1, 5);
+ grid->addMultiCellWidget(m_hGradientMinInput, 5, 5, 0, 6);
+ grid->addMultiCellWidget(m_hGradientMaxInput, 7, 7, 0, 6);
+ grid->addMultiCellWidget(m_minInput, 9, 9, 1, 1);
+ grid->addMultiCellWidget(m_maxInput, 9, 9, 5, 5);
+ grid->addMultiCellWidget(m_gammaInput, 11, 11, 0, 6);
+ grid->addMultiCellWidget(m_hGradientMinOutput, 13, 13, 0, 6);
+ grid->addMultiCellWidget(m_hGradientMaxOutput, 15, 15, 0, 6);
+ grid->addMultiCellWidget(m_minOutput, 17, 17, 1, 1);
+ grid->addMultiCellWidget(m_maxOutput, 17, 17, 5, 5);
+ grid->addMultiCellLayout(l3, 19, 19, 0, 6);
+ grid->setRowStretch(20, 10);
+ grid->setColStretch(3, 10);
+ grid->setMargin(0);
+ grid->setSpacing(5);
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+ // Channels and scale selection slots.
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotSpotColorChanged(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotColorSelectedFromTarget(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+ // Color sliders and spinbox slots.
+
+ connect(m_hGradientMinInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustMinInputSpinBox(int)));
+
+ connect(m_minInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustSliders()));
+
+ connect(m_gammaInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotGammaInputchanged(double)));
+
+ connect(m_hGradientMaxInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustMaxInputSpinBox(int)));
+
+ connect(m_maxInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustSliders()));
+
+ connect(m_hGradientMinOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustMinOutputSpinBox(int)));
+
+ connect(m_minOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustSliders()));
+
+ connect(m_hGradientMaxOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustMaxOutputSpinBox(int)));
+
+ connect(m_maxOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotAdjustSliders()));
+
+ // -------------------------------------------------------------
+ // Bouttons slots.
+
+ connect(m_autoButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotAutoLevels()));
+
+ connect(m_resetButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotResetCurrentChannel()));
+
+ connect(m_pickerColorButtonGroup, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotPickerColorButtonActived()));
+}
+
+AdjustLevelsTool::~AdjustLevelsTool()
+{
+ delete [] m_destinationPreviewData;
+ delete m_levels;
+}
+
+void AdjustLevelsTool::slotPickerColorButtonActived()
+{
+ // Save previous rendering mode and toggle to original image.
+ m_currentPreviewMode = m_previewWidget->getRenderingPreviewMode();
+ m_previewWidget->setRenderingPreviewMode(ImageGuideWidget::PreviewOriginalImage);
+}
+
+void AdjustLevelsTool::slotSpotColorChanged(const DColor& color)
+{
+ if ( m_pickBlack->isOn() )
+ {
+ // Black tonal levels point.
+ m_levels->levelsBlackToneAdjustByColors(m_channelCB->currentItem(), color);
+ m_pickBlack->setOn(false);
+ }
+ else if ( m_pickGray->isOn() )
+ {
+ // Gray tonal levels point.
+ m_levels->levelsGrayToneAdjustByColors(m_channelCB->currentItem(), color);
+ m_pickGray->setOn(false);
+ }
+ else if ( m_pickWhite->isOn() )
+ {
+ // White tonal levels point.
+ m_levels->levelsWhiteToneAdjustByColors(m_channelCB->currentItem(), color);
+ m_pickWhite->setOn(false);
+ }
+ else
+ {
+ m_levelsHistogramWidget->setHistogramGuideByColor(color);
+ return;
+ }
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+
+ // restore previous rendering mode.
+ m_previewWidget->setRenderingPreviewMode(m_currentPreviewMode);
+
+ slotEffect();
+}
+
+void AdjustLevelsTool::slotColorSelectedFromTarget(const DColor& color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void AdjustLevelsTool::slotGammaInputchanged(double val)
+{
+ blockSignals(true);
+ m_levels->setLevelGammaValue(m_channelCB->currentItem(), val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelsTool::slotAdjustMinInputSpinBox(int val)
+{
+ blockSignals(true);
+
+ if ( val < m_hGradientMaxInput->value() )
+ val = m_hGradientMaxInput->value();
+
+ m_minInput->setValue(m_histoSegments - val);
+ m_hGradientMinInput->setValue( val );
+ m_levels->setLevelLowInputValue(m_channelCB->currentItem(), m_histoSegments - val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelsTool::slotAdjustMaxInputSpinBox(int val)
+{
+ blockSignals(true);
+
+ if ( val > m_hGradientMinInput->value() )
+ val = m_hGradientMinInput->value();
+
+ m_maxInput->setValue(m_histoSegments - val);
+ m_hGradientMaxInput->setValue( val );
+ m_levels->setLevelHighInputValue(m_channelCB->currentItem(), m_histoSegments - val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelsTool::slotAdjustMinOutputSpinBox(int val)
+{
+ blockSignals(true);
+
+ if ( val < m_hGradientMaxOutput->value() )
+ val = m_hGradientMaxOutput->value();
+
+ m_minOutput->setValue(m_histoSegments - val);
+ m_hGradientMinOutput->setValue( val );
+ m_levels->setLevelLowOutputValue(m_channelCB->currentItem(), m_histoSegments - val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelsTool::slotAdjustMaxOutputSpinBox(int val)
+{
+ blockSignals(true);
+
+ if ( val > m_hGradientMinOutput->value() )
+ val = m_hGradientMinOutput->value();
+
+ m_maxOutput->setValue(m_histoSegments - val);
+ m_hGradientMaxOutput->setValue( val );
+ m_levels->setLevelHighOutputValue(m_channelCB->currentItem(), m_histoSegments - val);
+ blockSignals(false);
+ slotTimer();
+}
+
+void AdjustLevelsTool::slotAdjustSliders()
+{
+ adjustSliders(m_minInput->value(), m_gammaInput->value(),
+ m_maxInput->value(), m_minOutput->value(),
+ m_maxOutput->value());
+}
+
+void AdjustLevelsTool::adjustSliders(int minIn, double gamIn, int maxIn, int minOut, int maxOut)
+{
+ m_hGradientMinInput->setValue(m_histoSegments - minIn);
+ m_hGradientMaxInput->setValue(m_histoSegments - maxIn);
+ m_gammaInput->setValue(gamIn);
+ m_hGradientMinOutput->setValue(m_histoSegments - minOut);
+ m_hGradientMaxOutput->setValue(m_histoSegments - maxOut);
+}
+
+void AdjustLevelsTool::slotResetCurrentChannel()
+{
+ m_levels->levelsChannelReset(m_channelCB->currentItem());
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+ m_levelsHistogramWidget->reset();
+
+ slotEffect();
+ m_histogramWidget->reset();
+}
+
+void AdjustLevelsTool::slotAutoLevels()
+{
+ // Calculate Auto levels.
+ m_levels->levelsAuto(m_levelsHistogramWidget->m_imageHistogram);
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+
+ slotEffect();
+}
+
+void AdjustLevelsTool::slotEffect()
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *orgData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ // Create the new empty destination image data space.
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ m_destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)];
+
+ // Calculate the LUT to apply on the image.
+ m_levels->levelsLutSetup(ImageHistogram::AlphaChannel);
+
+ // Apply the lut to the image.
+ m_levels->levelsLutProcess(orgData, m_destinationPreviewData, w, h);
+
+ iface->putPreviewImage(m_destinationPreviewData);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ delete [] orgData;
+}
+
+void AdjustLevelsTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *orgData = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ // Create the new empty destination image data space.
+ uchar* desData = new uchar[w*h*(sb ? 8 : 4)];
+
+ // Calculate the LUT to apply on the image.
+ m_levels->levelsLutSetup(ImageHistogram::AlphaChannel);
+
+ // Apply the lut to the image.
+ m_levels->levelsLutProcess(orgData, desData, w, h);
+
+ iface->putOriginalImage(i18n("Adjust Level"), desData);
+ kapp->restoreOverrideCursor();
+
+ delete [] orgData;
+ delete [] desData;
+}
+
+void AdjustLevelsTool::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_levelsHistogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_levelsHistogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "red" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "red" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "red" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_levelsHistogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "green" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "green" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "green" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_levelsHistogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+
+ case AlphaChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::AlphaChannelHistogram;
+ m_levelsHistogramWidget->m_channelType = HistogramWidget::AlphaChannelHistogram;
+ m_hGradientMinInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxInput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMinOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ m_hGradientMaxOutput->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+ }
+
+ adjustSliders(m_levels->getLevelLowInputValue(channel),
+ m_levels->getLevelGammaValue(channel),
+ m_levels->getLevelHighInputValue(channel),
+ m_levels->getLevelLowOutputValue(channel),
+ m_levels->getLevelHighOutputValue(channel));
+
+ m_levelsHistogramWidget->repaint(false);
+ m_histogramWidget->repaint(false);
+}
+
+void AdjustLevelsTool::slotScaleChanged(int scale)
+{
+ m_levelsHistogramWidget->m_scaleType = scale;
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+ m_levelsHistogramWidget->repaint(false);
+}
+
+void AdjustLevelsTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("adjustlevels Tool");
+
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+
+ for (int i = 0 ; i < 5 ; i++)
+ {
+ bool sb = m_originalImage->sixteenBit();
+ int max = sb ? 65535 : 255;
+ double gamma = config->readDoubleNumEntry(TQString("GammaChannel%1").arg(i), 1.0);
+ int lowInput = config->readNumEntry(TQString("LowInputChannel%1").arg(i), 0);
+ int lowOutput = config->readNumEntry(TQString("LowOutputChannel%1").arg(i), 0);
+ int highInput = config->readNumEntry(TQString("HighInputChannel%1").arg(i), max);
+ int highOutput = config->readNumEntry(TQString("HighOutputChannel%1").arg(i), max);
+
+ m_levels->setLevelGammaValue(i, gamma);
+ m_levels->setLevelLowInputValue(i, sb ? lowInput*255 : lowInput);
+ m_levels->setLevelHighInputValue(i, sb ? highInput*255 : highInput);
+ m_levels->setLevelLowOutputValue(i, sb ? lowOutput*255 : lowOutput);
+ m_levels->setLevelHighOutputValue(i, sb ? highOutput*255 : highOutput);
+ }
+
+ m_levelsHistogramWidget->reset();
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+
+ // This is mandatory here to set spinbox values because slot connections
+ // can be not set completely at plugin startup.
+ m_minInput->setValue(m_levels->getLevelLowInputValue(m_channelCB->currentItem()));
+ m_minOutput->setValue(m_levels->getLevelLowOutputValue(m_channelCB->currentItem()));
+ m_maxInput->setValue(m_levels->getLevelHighInputValue(m_channelCB->currentItem()));
+ m_maxOutput->setValue(m_levels->getLevelHighOutputValue(m_channelCB->currentItem()));
+}
+
+void AdjustLevelsTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("adjustlevels Tool");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+
+ for (int i = 0 ; i < 5 ; i++)
+ {
+ bool sb = m_originalImage->sixteenBit();
+ double gamma = m_levels->getLevelGammaValue(i);
+ int lowInput = m_levels->getLevelLowInputValue(i);
+ int lowOutput = m_levels->getLevelLowOutputValue(i);
+ int highInput = m_levels->getLevelHighInputValue(i);
+ int highOutput = m_levels->getLevelHighOutputValue(i);
+
+ config->writeEntry(TQString("GammaChannel%1").arg(i), gamma);
+ config->writeEntry(TQString("LowInputChannel%1").arg(i), sb ? lowInput/255 : lowInput);
+ config->writeEntry(TQString("LowOutputChannel%1").arg(i), sb ? lowOutput/255 : lowOutput);
+ config->writeEntry(TQString("HighInputChannel%1").arg(i), sb ? highInput/255 : highInput);
+ config->writeEntry(TQString("HighOutputChannel%1").arg(i), sb ? highOutput/255 : highOutput);
+ }
+
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void AdjustLevelsTool::slotResetSettings()
+{
+ for (int channel = 0 ; channel < 5 ; ++channel)
+ m_levels->levelsChannelReset(channel);
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+ m_levelsHistogramWidget->reset();
+ slotEffect();
+ m_histogramWidget->reset();
+}
+
+void AdjustLevelsTool::slotLoadSettings()
+{
+ KURL loadLevelsFile;
+
+ loadLevelsFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Select Gimp Levels File to Load")) );
+ if( loadLevelsFile.isEmpty() )
+ return;
+
+ if ( m_levels->loadLevelsFromGimpLevelsFile( loadLevelsFile ) == false )
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot load from the Gimp levels text file."));
+ return;
+ }
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+}
+
+void AdjustLevelsTool::slotSaveAsSettings()
+{
+ KURL saveLevelsFile;
+
+ saveLevelsFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Gimp Levels File to Save")) );
+ if( saveLevelsFile.isEmpty() )
+ return;
+
+ if ( m_levels->saveLevelsToGimpLevelsFile( saveLevelsFile ) == false )
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot save to the Gimp levels text file."));
+ return;
+ }
+
+ // Refresh the current levels config.
+ slotChannelChanged(m_channelCB->currentItem());
+}
+
+// See B.K.O #146636: use event filter with all level slider to display a
+// guide over level histogram.
+bool AdjustLevelsTool::eventFilter(TQObject *obj, TQEvent *ev)
+{
+ if ( obj == m_hGradientMinInput )
+ {
+ if ( ev->type() == TQEvent::MouseButtonPress)
+ {
+ connect(m_minInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowInputHistogramGuide(int)));
+
+ return false;
+ }
+ if ( ev->type() == TQEvent::MouseButtonRelease)
+ {
+ disconnect(m_minInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowInputHistogramGuide(int)));
+
+ m_levelsHistogramWidget->reset();
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ if ( obj == m_hGradientMaxInput )
+ {
+ if ( ev->type() == TQEvent::MouseButtonPress)
+ {
+ connect(m_maxInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowInputHistogramGuide(int)));
+
+ return false;
+ }
+ if ( ev->type() == TQEvent::MouseButtonRelease)
+ {
+ disconnect(m_maxInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowInputHistogramGuide(int)));
+
+ m_levelsHistogramWidget->reset();
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ if ( obj == m_hGradientMinOutput )
+ {
+ if ( ev->type() == TQEvent::MouseButtonPress)
+ {
+ connect(m_minOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowOutputHistogramGuide(int)));
+
+ return false;
+ }
+ if ( ev->type() == TQEvent::MouseButtonRelease)
+ {
+ disconnect(m_minOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowOutputHistogramGuide(int)));
+
+ m_histogramWidget->reset();
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ if ( obj == m_hGradientMaxOutput )
+ {
+ if ( ev->type() == TQEvent::MouseButtonPress)
+ {
+ connect(m_maxOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowOutputHistogramGuide(int)));
+
+ return false;
+ }
+ if ( ev->type() == TQEvent::MouseButtonRelease)
+ {
+ disconnect(m_maxOutput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotShowOutputHistogramGuide(int)));
+
+ m_histogramWidget->reset();
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // pass the event on to the parent class
+ return EditorTool::eventFilter(obj, ev);
+ }
+}
+
+void AdjustLevelsTool::slotShowInputHistogramGuide(int v)
+{
+ DColor color(v, v, v, v, m_originalImage->sixteenBit());
+ m_levelsHistogramWidget->setHistogramGuideByColor(color);
+}
+
+void AdjustLevelsTool::slotShowOutputHistogramGuide(int v)
+{
+ DColor color(v, v, v, v, m_originalImage->sixteenBit());
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+} // NameSpace DigikamAdjustLevelsImagesPlugin
diff --git a/src/imageplugins/adjustlevels/adjustlevelstool.h b/src/imageplugins/adjustlevels/adjustlevelstool.h
new file mode 100644
index 00000000..9fdadf91
--- /dev/null
+++ b/src/imageplugins/adjustlevels/adjustlevelstool.h
@@ -0,0 +1,160 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-20
+ * Description : image histogram adjust levels.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ADJUSTLEVELSTOOL_H
+#define ADJUSTLEVELSTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQComboBox;
+class TQPushButton;
+class TQHButtonGroup;
+
+class KGradientSelector;
+
+namespace KDcrawIface
+{
+class RDoubleNumInput;
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class HistogramWidget;
+class ImageWidget;
+class ImageLevels;
+class DImg;
+class DColor;
+}
+
+namespace DigikamAdjustLevelsImagesPlugin
+{
+
+class AdjustLevelsTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ AdjustLevelsTool(TQObject *parent);
+ ~AdjustLevelsTool();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+ void adjustSliders(int minIn, double gamIn, int maxIn, int minOut, int maxOut);
+ bool eventFilter(TQObject *o, TQEvent *e);
+
+private slots:
+
+ void slotLoadSettings();
+ void slotSaveAsSettings();
+ void slotEffect();
+ void slotResetSettings();
+ void slotResetCurrentChannel();
+ void slotAutoLevels();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotAdjustSliders();
+ void slotGammaInputchanged(double val);
+ void slotAdjustMinInputSpinBox(int val);
+ void slotAdjustMaxInputSpinBox(int val);
+ void slotAdjustMinOutputSpinBox(int val);
+ void slotAdjustMaxOutputSpinBox(int val);
+ void slotSpotColorChanged(const Digikam::DColor& color);
+ void slotColorSelectedFromTarget(const Digikam::DColor& color);
+ void slotPickerColorButtonActived();
+ void slotShowInputHistogramGuide(int v);
+ void slotShowOutputHistogramGuide(int v);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel,
+ AlphaChannel
+ };
+
+ enum ColorPicker
+ {
+ BlackTonal=0,
+ GrayTonal,
+ WhiteTonal
+ };
+
+ uchar *m_destinationPreviewData;
+
+ int m_histoSegments;
+ int m_currentPreviewMode;
+
+ TQComboBox *m_channelCB;
+
+ TQPushButton *m_autoButton;
+ TQPushButton *m_resetButton;
+ TQPushButton *m_pickBlack;
+ TQPushButton *m_pickGray;
+ TQPushButton *m_pickWhite;
+
+ TQHButtonGroup *m_pickerColorButtonGroup;
+ TQHButtonGroup *m_scaleBG;
+
+ KGradientSelector *m_hGradientMinInput;
+ KGradientSelector *m_hGradientMaxInput;
+ KGradientSelector *m_hGradientMinOutput;
+ KGradientSelector *m_hGradientMaxOutput;
+
+ KDcrawIface::RDoubleNumInput *m_gammaInput;
+
+ KDcrawIface::RIntNumInput *m_minInput;
+ KDcrawIface::RIntNumInput *m_maxInput;
+ KDcrawIface::RIntNumInput *m_minOutput;
+ KDcrawIface::RIntNumInput *m_maxOutput;
+
+ Digikam::HistogramWidget *m_levelsHistogramWidget;
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+
+ Digikam::ImageLevels *m_levels;
+ Digikam::DImg *m_originalImage;
+};
+
+} // NameSpace DigikamAdjustLevelsImagesPlugin
+
+#endif /* ADJUSTLEVELSTOOL_H */
diff --git a/src/imageplugins/adjustlevels/digikamimageplugin_adjustlevels.desktop b/src/imageplugins/adjustlevels/digikamimageplugin_adjustlevels.desktop
new file mode 100644
index 00000000..b601ebbf
--- /dev/null
+++ b/src/imageplugins/adjustlevels/digikamimageplugin_adjustlevels.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_AdjustLevels
+Name[bg]=Приставка за снимки - Настройка на нивата
+Name[da]=Billedplugin_Niveaujustering
+Name[el]=ΠρόσθετοΕικόνας_ΠροσαρμογήΕπιπέδων
+Name[fi]=TasonsäätöHistogrammi
+Name[hr]=Podešavanje razina
+Name[it]=PluginImmagini_RegolaLivelli
+Name[nl]=Afbeeldingsplugin_NiveausAanpassen
+Name[sr]=Подешавање нивоа
+Name[sr@Latn]=Podešavanje nivoa
+Name[sv]=Insticksprogram för nivåjustering
+Name[tr]=ResimEklentisi_DüzeyAyarla
+Name[xx]=xxImagePlugin_AdjustLevelsxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+
+Comment=Image histogram adjust levels plugin for digiKam
+Comment[bg]=Приставка на digiKam за настройка нивата на хистограмите на снимки
+Comment[ca]=Connector pel digiKam d'ajust dels nivells de l'histograma d'imatges
+Comment[da]=Plugin til niveaujustering i Digikam
+Comment[de]=digiKam-Modul zur Justierung der Bildhistogrammwerte
+Comment[el]=Πρόσθετο προσαρμογής των επιπέδων του ιστογράμματος εικόνας για το digiKam
+Comment[es]=Plugin de digiKam para ajustar los niveles de color de una imagen
+Comment[et]=DigiKami pildi histogrammi tasemete kohendamise plugin
+Comment[fa]=وصلۀ سطوح تنظیم سابقه‌نمای تصویر برای digiKam
+Comment[fi]=Muokkaa värikanavien raja-arvoja
+Comment[fr]=Module externe pour ajuster les niveaux de l'histogramme dans digiKam
+Comment[gl]=Un plugin de digiKam para axustar os níveis do histograma
+Comment[hr]=digiKam dodatak za histogramsko podešavanje razina
+Comment[is]=Íforrit fyrir digiKam sem breytir tíðnidreifingu (levels) í stuðlariti myndar
+Comment[it]=Plugin di regolazione dei livelli degli istogrammi delle immagini per digiKam
+Comment[ja]=digiKam レベル補正プラグイン
+Comment[nds]=digiKam-Moduul för't Topassen vun Klöörkanaal-Toonrebeden
+Comment[nl]=Digikam-plugin voor niveauaanpassing van afbeeldingshistogram
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਚਿੱਤਰ ਹਿਸਟੋਗਰਾਮ ਅਨੁਕੂਲ ਪੱਧਰ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam dostosowująca poziomy histogramu
+Comment[pt]=Um 'plugin' do digiKam para ajustar os níveis do histograma do digiKam
+Comment[pt_BR]=Plugin de ajuste de níveis do histograma da imagem
+Comment[ru]=Модуль digiKam подстройки уровней гистограммы изображения
+Comment[sk]=digiKam plugin histogramu úrovní obrázku
+Comment[sr]=digiKam-ов прикључак за подешавање нивоа хистограма слика
+Comment[sr@Latn]=digiKam-ov priključak za podešavanje nivoa histograma slika
+Comment[sv]=Digikam insticksprogram för justering av nivåer i bildhistogram
+Comment[tr]=digiKam için resim histogram düzeyleri ayarlama eklentisi
+Comment[uk]=Втулок коригування рівнів гістограми зображень для digiKam
+Comment[vi]=Phần bổ sung biểu đồ tần xuất điều chỉnh lớp ảnh cho digiKam
+Comment[xx]=xxImage histogram adjust levels plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_adjustlevels
+author=Caulier Gilles, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/adjustlevels/digikamimageplugin_adjustlevels_ui.rc b/src/imageplugins/adjustlevels/digikamimageplugin_adjustlevels_ui.rc
new file mode 100644
index 00000000..8036e124
--- /dev/null
+++ b/src/imageplugins/adjustlevels/digikamimageplugin_adjustlevels_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_adjustlevels" >
+
+ <MenuBar>
+
+ <Menu name="Color" ><text>&amp;Color</text>
+ <Action name="imageplugin_adjustlevels" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action name="imageplugin_adjustlevels" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/adjustlevels/imageplugin_adjustlevels.cpp b/src/imageplugins/adjustlevels/imageplugin_adjustlevels.cpp
new file mode 100644
index 00000000..0f9dcb9e
--- /dev/null
+++ b/src/imageplugins/adjustlevels/imageplugin_adjustlevels.cpp
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-04
+ * Description : image histogram adjust levels.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "adjustlevelstool.h"
+#include "imageplugin_adjustlevels.h"
+#include "imageplugin_adjustlevels.moc"
+
+using namespace DigikamAdjustLevelsImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_adjustlevels,
+ KGenericFactory<ImagePlugin_AdjustLevels>("digikamimageplugin_adjustlevels"))
+
+ImagePlugin_AdjustLevels::ImagePlugin_AdjustLevels(TQObject *parent, const char*,
+ const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_AdjustLevels")
+{
+ m_levelsAction = new TDEAction(i18n("Levels Adjust..."), "adjustlevels",
+ CTRL+Key_L, // NOTE: Photoshop 7 use CTRL+L.
+ this, TQ_SLOT(slotLevelsAdjust()),
+ actionCollection(), "imageplugin_adjustlevels");
+
+ setXMLFile("digikamimageplugin_adjustlevels_ui.rc");
+
+ DDebug() << "ImagePlugin_AdjustLevels plugin loaded" << endl;
+}
+
+ImagePlugin_AdjustLevels::~ImagePlugin_AdjustLevels()
+{
+}
+
+void ImagePlugin_AdjustLevels::setEnabledActions(bool enable)
+{
+ m_levelsAction->setEnabled(enable);
+}
+
+void ImagePlugin_AdjustLevels::slotLevelsAdjust()
+{
+ AdjustLevelsTool *levels = new AdjustLevelsTool(this);
+ loadTool(levels);
+}
diff --git a/src/imageplugins/adjustlevels/imageplugin_adjustlevels.h b/src/imageplugins/adjustlevels/imageplugin_adjustlevels.h
new file mode 100644
index 00000000..16af4f32
--- /dev/null
+++ b/src/imageplugins/adjustlevels/imageplugin_adjustlevels.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-04
+ * Description : image histogram adjust levels.
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_ADJUSTLEVELS_H
+#define IMAGEPLUGIN_ADJUSTLEVELS_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_AdjustLevels : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_AdjustLevels(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_AdjustLevels();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotLevelsAdjust();
+
+private:
+
+ TDEAction *m_levelsAction;
+};
+
+#endif /* IMAGEPLUGIN_ADJUSTLEVELS_H */
diff --git a/src/imageplugins/antivignetting/Makefile.am b/src/imageplugins/antivignetting/Makefile.am
new file mode 100644
index 00000000..54539672
--- /dev/null
+++ b/src/imageplugins/antivignetting/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_antivignetting_la_SOURCES = imageplugin_antivignetting.cpp \
+ antivignettingtool.cpp antivignetting.cpp
+
+digikamimageplugin_antivignetting_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_antivignetting_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_antivignetting.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_antivignetting.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_antivignetting_ui.rc
+
diff --git a/src/imageplugins/antivignetting/antivignetting.cpp b/src/imageplugins/antivignetting/antivignetting.cpp
new file mode 100644
index 00000000..dec0a9ea
--- /dev/null
+++ b/src/imageplugins/antivignetting/antivignetting.cpp
@@ -0,0 +1,149 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Antivignetting threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original AntiVignetting algorithm copyrighted 2003 by
+ * John Walker from 'pnmctrfilt' implementation. See
+ * http://www.fourmilab.ch/netpbm/pnmctrfilt for more
+ * information.
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "antivignetting.h"
+
+namespace DigikamAntiVignettingImagesPlugin
+{
+
+AntiVignetting::AntiVignetting(Digikam::DImg *orgImage, TQObject *parent, double density,
+ double power, double radius, int xshift, int yshift, bool normalize)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "AntiVignetting")
+{
+ m_density = density;
+ m_power = power;
+ m_radius = radius;
+ m_xshift = xshift;
+ m_yshift = yshift;
+ m_normalize = normalize;
+
+ initFilter();
+}
+
+// This method is inspired from John Walker 'pnmctrfilt' algorithm code.
+
+void AntiVignetting::filterImage(void)
+{
+ int progress;
+ int col, row, xd, td, yd, p;
+ int i, xsize, ysize, diagonal, erad, xctr, yctr;
+ double *ldens;
+
+ uchar* NewBits = m_destImage.bits();
+ uchar* data = m_orgImage.bits();
+
+ unsigned short* NewBits16 = (unsigned short*)m_destImage.bits();
+ unsigned short* data16 = (unsigned short*)m_orgImage.bits();
+
+ int Width = m_orgImage.width();
+ int Height = m_orgImage.height();
+
+ // Determine the radius of the filter. This is the half diagonal
+ // measure of the image multiplied by the command line radius factor.
+
+ xsize = (Height + 1) / 2;
+ ysize = (Width + 1) / 2;
+ erad = (int)((sqrt((xsize * xsize) + (ysize * ysize)) + 0.5) * m_radius);
+
+ // Build the in-memory table which maps distance from the
+ // center of the image (as adjusted by the X and Y offset,
+ // if any) to the density of the filter at this remove. This
+ // table needs to be as large as the diagonal from the
+ // (possibly offset) center to the most distant corner
+ // of the image.
+
+ xsize = ((Height + 1) / 2) + abs(m_xshift);
+ ysize = ((Width + 1) / 2) + abs(m_yshift);
+ diagonal = ((int) (sqrt((xsize * xsize) + (ysize * ysize)) + 0.5)) + 1;
+
+ ldens = new double[diagonal];
+
+ for (i = 0 ; !m_cancel && (i < diagonal) ; i++)
+ {
+ if ( i >= erad )
+ ldens[i] = 1;
+ else
+ ldens[i] = (1.0 + (m_density - 1) * pow(1.0 - (((double) i) / (erad - 1)), m_power));
+ }
+
+ xctr = ((Height + 1) / 2) + m_xshift;
+ yctr = ((Width + 1) / 2) + m_yshift;
+
+ for (row = 0 ; !m_cancel && (row < Width) ; row++)
+ {
+ yd = abs(yctr - row);
+
+ for (col = 0 ; !m_cancel && (col < Height) ; col++)
+ {
+ p = (col * Width + row)*4;
+
+ xd = abs(xctr - col);
+ td = (int) (sqrt((xd * xd) + (yd * yd)) + 0.5);
+
+ if (!m_orgImage.sixteenBit()) // 8 bits image
+ {
+ NewBits[ p ] = (uchar)(data[ p ] / ldens[td]);
+ NewBits[p+1] = (uchar)(data[p+1] / ldens[td]);
+ NewBits[p+2] = (uchar)(data[p+2] / ldens[td]);
+ NewBits[p+3] = data[p+3];
+ }
+ else // 16 bits image.
+ {
+ NewBits16[ p ] = (unsigned short)(data16[ p ] / ldens[td]);
+ NewBits16[p+1] = (unsigned short)(data16[p+1] / ldens[td]);
+ NewBits16[p+2] = (unsigned short)(data16[p+2] / ldens[td]);
+ NewBits16[p+3] = data16[p+3];
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int)(((double)row * 100.0) / Width);
+ if (progress%5 == 0)
+ postProgress( progress );
+ }
+
+ // Normalize colors for a best rendering.
+ if (m_normalize)
+ {
+ Digikam::DImgImageFilters filters;
+ filters.normalizeImage(m_destImage.bits(), Width, Height, m_destImage.sixteenBit());
+ }
+
+ delete [] ldens;
+}
+
+} // NameSpace DigikamAntiVignettingImagesPlugin
diff --git a/src/imageplugins/antivignetting/antivignetting.h b/src/imageplugins/antivignetting/antivignetting.h
new file mode 100644
index 00000000..f5311da0
--- /dev/null
+++ b/src/imageplugins/antivignetting/antivignetting.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Antivignetting threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ANTIVIGNETTING_H
+#define ANTIVIGNETTING_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamAntiVignettingImagesPlugin
+{
+
+class AntiVignetting : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ AntiVignetting(Digikam::DImg *orgImage, TQObject *parent=0, double density=2.0,
+ double power=1.0, double radius=1.0, int xshift=0, int yshift=0, bool normalize=true);
+
+ ~AntiVignetting(){};
+
+private:
+
+ virtual void filterImage(void);
+
+private:
+
+ bool m_normalize;
+
+ int m_xshift;
+ int m_yshift;
+
+ double m_density;
+ double m_power;
+ double m_radius;
+};
+
+} // NameSpace DigikamAntiVignettingImagesPlugin
+
+#endif /* ANTIVIGNETTING_H */
diff --git a/src/imageplugins/antivignetting/antivignettingtool.cpp b/src/imageplugins/antivignetting/antivignettingtool.cpp
new file mode 100644
index 00000000..d8f211c7
--- /dev/null
+++ b/src/imageplugins/antivignetting/antivignettingtool.cpp
@@ -0,0 +1,378 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-25
+ * Description : a digiKam image plugin to reduce
+ * vignetting on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqtabwidget.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <kseparator.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "bcgmodifier.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "editortoolsettings.h"
+#include "dimgimagefilters.h"
+#include "antivignetting.h"
+#include "antivignettingtool.h"
+#include "antivignettingtool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamAntiVignettingImagesPlugin
+{
+
+AntiVignettingTool::AntiVignettingTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("antivignettings");
+ setToolName(i18n("Vignetting Correction"));
+ setToolIcon(SmallIcon("antivignetting"));
+
+ m_previewWidget = new ImageWidget("antivignetting Tool", 0, TQString(),
+ false, ImageGuideWidget::HVGuideMode, false);
+
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 14, 2);
+
+ m_maskPreviewLabel = new TQLabel( m_gboxSettings->plainPage() );
+ m_maskPreviewLabel->setAlignment ( TQt::AlignHCenter | TQt::AlignVCenter );
+ TQWhatsThis::add( m_maskPreviewLabel, i18n("<p>You can see here a thumbnail preview of the anti-vignetting "
+ "mask applied to the image.") );
+
+ // -------------------------------------------------------------
+
+ TQLabel *label1 = new TQLabel(i18n("Density:"), m_gboxSettings->plainPage());
+
+ m_densityInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_densityInput->setPrecision(1);
+ m_densityInput->setRange(1.0, 20.0, 0.1);
+ m_densityInput->setDefaultValue(2.0);
+ TQWhatsThis::add( m_densityInput, i18n("<p>This value controls the degree of intensity attenuation by the filter "
+ "at its point of maximum density."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Power:"), m_gboxSettings->plainPage());
+
+ m_powerInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_powerInput->setPrecision(1);
+ m_powerInput->setRange(0.1, 2.0, 0.1);
+ m_powerInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_powerInput, i18n("<p>This value is used as the exponent controlling the fall-off in density "
+ "from the center of the filter to the periphery."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Radius:"), m_gboxSettings->plainPage());
+
+ m_radiusInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_radiusInput->setPrecision(1);
+ m_radiusInput->setRange(-100.0, 100.0, 0.1);
+ m_radiusInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_radiusInput, i18n("<p>This value is the radius of the center filter. It is a multiple of the "
+ "half-diagonal measure of the image, at which the density of the filter falls "
+ "to zero."));
+
+ KSeparator *line = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ // -------------------------------------------------------------
+
+ TQLabel *label4 = new TQLabel(i18n("Brightness:"), m_gboxSettings->plainPage());
+
+ m_brightnessInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_brightnessInput->setRange(0, 100, 1);
+ m_brightnessInput->setDefaultValue(0);
+ TQWhatsThis::add( m_brightnessInput, i18n("<p>Set here the brightness re-adjustment of the target image."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label5 = new TQLabel(i18n("Contrast:"), m_gboxSettings->plainPage());
+
+ m_contrastInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_contrastInput->setRange(0, 100, 1);
+ m_contrastInput->setDefaultValue(0);
+ TQWhatsThis::add( m_contrastInput, i18n("<p>Set here the contrast re-adjustment of the target image."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label6 = new TQLabel(i18n("Gamma:"), m_gboxSettings->plainPage());
+
+ m_gammaInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_gammaInput->setPrecision(2);
+ m_gammaInput->setRange(0.1, 3.0, 0.01);
+ m_gammaInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_gammaInput, i18n("<p>Set here the gamma re-adjustment of the target image."));
+
+ grid->addMultiCellWidget(m_maskPreviewLabel, 0, 0, 0, 2);
+ grid->addMultiCellWidget(label1, 1, 1, 0, 2);
+ grid->addMultiCellWidget(m_densityInput, 2, 2, 0, 2);
+ grid->addMultiCellWidget(label2, 3, 3, 0, 2);
+ grid->addMultiCellWidget(m_powerInput, 4, 4, 0, 2);
+ grid->addMultiCellWidget(label3, 5, 5, 0, 2);
+ grid->addMultiCellWidget(m_radiusInput, 6, 6, 0, 2);
+ grid->addMultiCellWidget(line, 7, 7, 0, 2);
+ grid->addMultiCellWidget(label4, 8, 8, 0, 2);
+ grid->addMultiCellWidget(m_brightnessInput, 9, 9, 0, 2);
+ grid->addMultiCellWidget(label5, 10, 10, 0, 2);
+ grid->addMultiCellWidget(m_contrastInput, 11, 11, 0, 2);
+ grid->addMultiCellWidget(label6, 12, 12, 0, 2);
+ grid->addMultiCellWidget(m_gammaInput, 13, 13, 0, 2);
+ grid->setRowStretch(14, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_densityInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_powerInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_radiusInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_brightnessInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_contrastInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gammaInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+AntiVignettingTool::~AntiVignettingTool()
+{
+}
+
+void AntiVignettingTool::renderingFinished()
+{
+ m_densityInput->setEnabled(true);
+ m_powerInput->setEnabled(true);
+ m_radiusInput->setEnabled(true);
+ m_brightnessInput->setEnabled(true);
+ m_contrastInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+}
+
+void AntiVignettingTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("antivignettings Tool");
+
+ m_densityInput->blockSignals(true);
+ m_powerInput->blockSignals(true);
+ m_radiusInput->blockSignals(true);
+ m_brightnessInput->blockSignals(true);
+ m_contrastInput->blockSignals(true);
+ m_gammaInput->blockSignals(true);
+
+ m_densityInput->setValue(config->readDoubleNumEntry("DensityAjustment", m_densityInput->defaultValue()));
+ m_powerInput->setValue(config->readDoubleNumEntry("PowerAjustment", m_powerInput->defaultValue()));
+ m_radiusInput->setValue(config->readDoubleNumEntry("RadiusAjustment", m_radiusInput->defaultValue()));
+ m_brightnessInput->setValue(config->readNumEntry("BrightnessAjustment", m_brightnessInput->defaultValue()));
+ m_contrastInput->setValue(config->readNumEntry("ContrastAjustment", m_contrastInput->defaultValue()));
+ m_gammaInput->setValue(config->readDoubleNumEntry("GammaAjustment", m_gammaInput->defaultValue()));
+
+ m_densityInput->blockSignals(false);
+ m_powerInput->blockSignals(false);
+ m_radiusInput->blockSignals(false);
+ m_brightnessInput->blockSignals(false);
+ m_contrastInput->blockSignals(false);
+ m_gammaInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void AntiVignettingTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("antivignettings Tool");
+ config->writeEntry("DensityAjustment", m_densityInput->value());
+ config->writeEntry("PowerAjustment", m_powerInput->value());
+ config->writeEntry("RadiusAjustment", m_radiusInput->value());
+ config->writeEntry("BrightnessAjustment", m_brightnessInput->value());
+ config->writeEntry("ContrastAjustment", m_contrastInput->value());
+ config->writeEntry("GammaAjustment", m_gammaInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void AntiVignettingTool::slotResetSettings()
+{
+ m_densityInput->blockSignals(true);
+ m_powerInput->blockSignals(true);
+ m_radiusInput->blockSignals(true);
+ m_brightnessInput->blockSignals(true);
+ m_contrastInput->blockSignals(true);
+ m_gammaInput->blockSignals(true);
+
+ m_densityInput->slotReset();
+ m_powerInput->slotReset();
+ m_radiusInput->slotReset();
+ m_brightnessInput->slotReset();
+ m_contrastInput->slotReset();
+ m_gammaInput->slotReset();
+
+ m_densityInput->blockSignals(false);
+ m_powerInput->blockSignals(false);
+ m_radiusInput->blockSignals(false);
+ m_brightnessInput->blockSignals(false);
+ m_contrastInput->blockSignals(false);
+ m_gammaInput->blockSignals(false);
+}
+
+void AntiVignettingTool::prepareEffect()
+{
+ m_densityInput->setEnabled(false);
+ m_powerInput->setEnabled(false);
+ m_radiusInput->setEnabled(false);
+ m_brightnessInput->setEnabled(false);
+ m_contrastInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+
+ double d = m_densityInput->value();
+ double p = m_powerInput->value();
+ double r = m_radiusInput->value();
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int orgWidth = iface->originalWidth();
+ int orgHeight = iface->originalHeight();
+ TQSize ps(orgWidth, orgHeight);
+ ps.scale( TQSize(120, 120), TQSize::ScaleMin );
+
+ // Calc mask preview.
+ DImg preview(ps.width(), ps.height(), false);
+ memset(preview.bits(), 255, preview.numBytes());
+ AntiVignetting maskPreview(&preview, 0L, d, p, r, 0, 0, false);
+ TQPixmap pix = maskPreview.getTargetImage().convertToPixmap();
+ TQPainter pt(&pix);
+ pt.setPen( TQPen(TQt::black, 1) );
+ pt.drawRect( 0, 0, pix.width(), pix.height() );
+ pt.end();
+ m_maskPreviewLabel->setPixmap( pix );
+
+ DImg orgImage(orgWidth, orgHeight, iface->originalSixteenBit(),
+ iface->originalHasAlpha(), data);
+ delete [] data;
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new AntiVignetting(&orgImage, this, d, p, r, 0, 0, true)));
+}
+
+void AntiVignettingTool::prepareFinal()
+{
+ m_densityInput->setEnabled(false);
+ m_powerInput->setEnabled(false);
+ m_radiusInput->setEnabled(false);
+ m_brightnessInput->setEnabled(false);
+ m_contrastInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+
+ double d = m_densityInput->value();
+ double p = m_powerInput->value();
+ double r = m_radiusInput->value();
+
+ ImageIface iface(0, 0);
+
+ uchar *data = iface.getOriginalImage();
+ DImg orgImage(iface.originalWidth(), iface.originalHeight(), iface.originalSixteenBit(),
+ iface.originalHasAlpha(), data);
+ delete [] data;
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new AntiVignetting(&orgImage, this, d, p, r, 0, 0, true)));
+}
+
+void AntiVignettingTool::putPreviewData(void)
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+ DImg imDest = filter()->getTargetImage();
+
+ // Adjust Image BCG.
+
+ double b = (double)(m_brightnessInput->value() / 100.0);
+ double c = (double)(m_contrastInput->value() / 100.0) + (double)(1.00);
+ double g = m_gammaInput->value();
+
+ BCGModifier cmod;
+ cmod.setGamma(g);
+ cmod.setBrightness(b);
+ cmod.setContrast(c);
+ cmod.applyBCG(imDest);
+
+ iface->putPreviewImage((imDest.smoothScale(iface->previewWidth(),
+ iface->previewHeight())).bits());
+ m_previewWidget->updatePreview();
+}
+
+void AntiVignettingTool::putFinalData(void)
+{
+ ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Vignetting Correction"),
+ filter()->getTargetImage().bits());
+
+ double b = (double)(m_brightnessInput->value() / 100.0);
+ double c = (double)(m_contrastInput->value() / 100.0) + (double)(1.00);
+ double g = m_gammaInput->value();
+
+ // Adjust Image BCG.
+ iface.setOriginalBCG(b, c, g);
+}
+
+} // NameSpace DigikamAntiVignettingImagesPlugin
diff --git a/src/imageplugins/antivignetting/antivignettingtool.h b/src/imageplugins/antivignetting/antivignettingtool.h
new file mode 100644
index 00000000..467a19da
--- /dev/null
+++ b/src/imageplugins/antivignetting/antivignettingtool.h
@@ -0,0 +1,92 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : a digiKam image plugin to reduce
+ * vignetting on an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ANTIVIGNETTINGTOOL_H
+#define ANTIVIGNETTINGTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQLabel;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RDoubleNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImageWidget;
+}
+
+namespace DigikamAntiVignettingImagesPlugin
+{
+
+class AntiVignettingTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ AntiVignettingTool(TQObject *parent);
+ ~AntiVignettingTool();
+
+private slots:
+
+ void slotResetSettings();
+
+private:
+
+ void writeSettings();
+ void readSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQLabel *m_maskPreviewLabel;
+
+ KDcrawIface::RIntNumInput *m_brightnessInput;
+ KDcrawIface::RIntNumInput *m_contrastInput;
+
+ KDcrawIface::RDoubleNumInput *m_gammaInput;
+ KDcrawIface::RDoubleNumInput *m_densityInput;
+ KDcrawIface::RDoubleNumInput *m_powerInput;
+ KDcrawIface::RDoubleNumInput *m_radiusInput;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamAntiVignettingImagesPlugin
+
+#endif /* ANTIVIGNETTINGTOOL_H */
diff --git a/src/imageplugins/antivignetting/digikamimageplugin_antivignetting.desktop b/src/imageplugins/antivignetting/digikamimageplugin_antivignetting.desktop
new file mode 100644
index 00000000..f70a4752
--- /dev/null
+++ b/src/imageplugins/antivignetting/digikamimageplugin_antivignetting.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Name=ImagePlugin_AntiVignetting
+Name[bg]=Приставка за снимки - Премахване на винетиране
+Name[da]=Billedplugin_Anti-vignettering
+Name[el]=ΠρόσθετοΕικόνας_Αντισκίασης
+Name[fi]=ReunatummentumienPoisto
+Name[hr]=Uklanjanje vinjeta
+Name[it]=PluginImmagini_Antivignettatura
+Name[nl]=Afbeeldingsplugin_Antivignetting
+Name[sr]=Девињетизација
+Name[sr@Latn]=Devinjetizacija
+Name[sv]=Insticksprogram för antivinjettering
+Name[tr]=ResimEklentisi_KenarKararmalarınıDüzelt
+Name[xx]=xxImagePlugin_AntiVignettingxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Anti Vignetting image effect plugin for digiKam
+Comment[bg]=Приставка на digiKam за намаляване на винетирането на снимки
+Comment[ca]=Connector pel digiKam d'efecte anti-vinyetatge
+Comment[da]=Anti-vignetteringsplugin for Digikam
+Comment[de]=digiKam-Modul zur Reduzierung von Vignettierung im Bild
+Comment[el]=Πρόσθετο εφέ αντισκίασης εικόνας για το digiKam
+Comment[es]=Un plugin para digiKam para eliminar efectos tipo "Vignetting"
+Comment[et]=DigiKami pildi vinjeti kohendamise plugin
+Comment[fa]=وصلۀ جلوۀ تصویر ضد عکس برای digiKam
+Comment[fi]=Keskialueen portaaton tummennus
+Comment[gl]=Un plugin de digiKam para efeitos antiviñeta de imaxe
+Comment[hr]=digiKam dodatak za efekt protiv vinjeta
+Comment[is]=Íforrit fyrir digiKam sem minnkar linsuskyggingu í hornum
+Comment[it]=Plugin per l'effetto delle immagini di antivignettatura per digiKam
+Comment[ja]=digiKam 口径食補正プラグイン
+Comment[nds]=digiKam-Bildeffektmoduul gegen Randschaddens
+Comment[nl]=Digikam-plugin voor anti-vignetting
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਐਂਟੀ ਵੀਜਨਿੰਟ ਚਿੱਤਰ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam usuwająca efekt winietowania
+Comment[pt]=Um 'plugin' do digiKam para efeitos anti-vinheta de imagem
+Comment[pt_BR]=Plugin de efeito anti-Vignetting para o digiKam
+Comment[ru]=Модуль эффекта анти-виньетирования изображения для digiKam
+Comment[sk]=Plugin korekcie vignetácie obrázku pre digiKam
+Comment[sr]=digiKam-ов прикључак за ефекат девињетизације
+Comment[sr@Latn]=digiKam-ov priključak za efekat devinjetizacije
+Comment[sv]=Digikam insticksprogram för antivinjetteringsbildeffekt
+Comment[tr]=digiKam için kenar kararmalarını düzeltme eklentisi
+Comment[uk]=Втулок противіньєткового ефекту зображень для digiKam
+Comment[vi]=Phần bổ sung hiệu ứng chống làm mờ nét ảnh cho digiKam
+Comment[xx]=xxAnti Vignetting image effect plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_antivignetting
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/antivignetting/digikamimageplugin_antivignetting_ui.rc b/src/imageplugins/antivignetting/digikamimageplugin_antivignetting_ui.rc
new file mode 100644
index 00000000..7a54a1f3
--- /dev/null
+++ b/src/imageplugins/antivignetting/digikamimageplugin_antivignetting_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_antivignetting" >
+
+ <MenuBar>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ <Action name="imageplugin_antivignetting" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action name="imageplugin_antivignetting" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/antivignetting/imageeffect_antivignetting.cpp b/src/imageplugins/antivignetting/imageeffect_antivignetting.cpp
new file mode 100644
index 00000000..7d7a00c6
--- /dev/null
+++ b/src/imageplugins/antivignetting/imageeffect_antivignetting.cpp
@@ -0,0 +1,380 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-25
+ * Description : a digiKam image plugin to reduce
+ * vignetting on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqtabwidget.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+#include <kseparator.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "bcgmodifier.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "dimgimagefilters.h"
+#include "antivignetting.h"
+#include "imageeffect_antivignetting.h"
+#include "imageeffect_antivignetting.moc"
+
+namespace DigikamAntiVignettingImagesPlugin
+{
+
+ImageEffect_AntiVignetting::ImageEffect_AntiVignetting(TQWidget* parent)
+ : Digikam::ImageGuideDlg(parent, i18n("Vignetting Correction"),
+ "antivignettings", false, true, false,
+ Digikam::ImageGuideWidget::HVGuideMode, 0, true)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Vignetting Correction"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to reduce image vignetting."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("John Walker", I18N_NOOP("Anti Vignetting algorithm"), 0,
+ "http://www.fourmilab.ch/netpbm/pnmctrfilt");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 13, 2, spacingHint());
+
+ m_maskPreviewLabel = new TQLabel( gboxSettings );
+ m_maskPreviewLabel->setAlignment ( TQt::AlignHCenter | TQt::AlignVCenter );
+ TQWhatsThis::add( m_maskPreviewLabel, i18n("<p>You can see here a thumbnail preview of the anti-vignetting "
+ "mask applied to the image.") );
+ gridSettings->addMultiCellWidget(m_maskPreviewLabel, 0, 0, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label1 = new TQLabel(i18n("Density:"), gboxSettings);
+
+ m_densityInput = new KDoubleNumInput(gboxSettings);
+ m_densityInput->setPrecision(1);
+ m_densityInput->setRange(1.0, 20.0, 0.1, true);
+ TQWhatsThis::add( m_densityInput, i18n("<p>This value controls the degree of intensity attenuation by the filter "
+ "at its point of maximum density."));
+
+ gridSettings->addMultiCellWidget(label1, 1, 1, 0, 2);
+ gridSettings->addMultiCellWidget(m_densityInput, 2, 2, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Power:"), gboxSettings);
+
+ m_powerInput = new KDoubleNumInput(gboxSettings);
+ m_powerInput->setPrecision(1);
+ m_powerInput->setRange(0.1, 2.0, 0.1, true);
+ TQWhatsThis::add( m_powerInput, i18n("<p>This value is used as the exponent controlling the fall-off in density "
+ "from the center of the filter to the periphery."));
+
+ gridSettings->addMultiCellWidget(label2, 3, 3, 0, 2);
+ gridSettings->addMultiCellWidget(m_powerInput, 4, 4, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Radius:"), gboxSettings);
+
+ m_radiusInput = new KDoubleNumInput(gboxSettings);
+ m_radiusInput->setPrecision(1);
+ m_radiusInput->setRange(-100.0, 100.0, 0.1, true);
+ TQWhatsThis::add( m_radiusInput, i18n("<p>This value is the radius of the center filter. It is a multiple of the "
+ "half-diagonal measure of the image, at which the density of the filter falls "
+ "to zero."));
+
+ gridSettings->addMultiCellWidget(label3, 5, 5, 0, 2);
+ gridSettings->addMultiCellWidget(m_radiusInput, 6, 6, 0, 2);
+
+ KSeparator *line = new KSeparator(Horizontal, gboxSettings);
+ gridSettings->addMultiCellWidget(line, 7, 7, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label4 = new TQLabel(i18n("Brightness:"), gboxSettings);
+
+ m_brightnessInput = new KIntNumInput(gboxSettings);
+ m_brightnessInput->setRange(0, 100, 1, true);
+ TQWhatsThis::add( m_brightnessInput, i18n("<p>Set here the brightness re-adjustment of the target image."));
+
+ gridSettings->addMultiCellWidget(label4, 8, 8, 0, 2);
+ gridSettings->addMultiCellWidget(m_brightnessInput, 9, 9, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label5 = new TQLabel(i18n("Contrast:"), gboxSettings);
+
+ m_contrastInput = new KIntNumInput(gboxSettings);
+ m_contrastInput->setRange(0, 100, 1, true);
+ TQWhatsThis::add( m_contrastInput, i18n("<p>Set here the contrast re-adjustment of the target image."));
+
+ gridSettings->addMultiCellWidget(label5, 10, 10, 0, 2);
+ gridSettings->addMultiCellWidget(m_contrastInput, 11, 11, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label6 = new TQLabel(i18n("Gamma:"), gboxSettings);
+
+ m_gammaInput = new KDoubleNumInput(gboxSettings);
+ m_gammaInput->setPrecision(2);
+ m_gammaInput->setRange(0.1, 3.0, 0.01, true);
+ m_gammaInput->setValue(1.0);
+ TQWhatsThis::add( m_gammaInput, i18n("<p>Set here the gamma re-adjustment of the target image."));
+
+ gridSettings->addMultiCellWidget(label6, 12, 12, 0, 2);
+ gridSettings->addMultiCellWidget(m_gammaInput, 13, 13, 0, 2);
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_densityInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_powerInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_radiusInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_brightnessInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_contrastInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gammaInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_AntiVignetting::~ImageEffect_AntiVignetting()
+{
+}
+
+void ImageEffect_AntiVignetting::renderingFinished()
+{
+ m_densityInput->setEnabled(true);
+ m_powerInput->setEnabled(true);
+ m_radiusInput->setEnabled(true);
+ m_brightnessInput->setEnabled(true);
+ m_contrastInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+}
+
+void ImageEffect_AntiVignetting::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("antivignettings Tool Dialog");
+
+ m_densityInput->blockSignals(true);
+ m_powerInput->blockSignals(true);
+ m_radiusInput->blockSignals(true);
+ m_brightnessInput->blockSignals(true);
+ m_contrastInput->blockSignals(true);
+ m_gammaInput->blockSignals(true);
+
+ m_densityInput->setValue(config->readDoubleNumEntry("DensityAjustment", 2.0));
+ m_powerInput->setValue(config->readDoubleNumEntry("PowerAjustment", 1.0));
+ m_radiusInput->setValue(config->readDoubleNumEntry("RadiusAjustment", 1.0));
+ m_brightnessInput->setValue(config->readNumEntry("BrightnessAjustment", 0));
+ m_contrastInput->setValue(config->readNumEntry("ContrastAjustment", 0));
+ m_gammaInput->setValue(config->readDoubleNumEntry("GammaAjustment", 1.0));
+
+ m_densityInput->blockSignals(false);
+ m_powerInput->blockSignals(false);
+ m_radiusInput->blockSignals(false);
+ m_brightnessInput->blockSignals(false);
+ m_contrastInput->blockSignals(false);
+ m_gammaInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ImageEffect_AntiVignetting::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("antivignettings Tool Dialog");
+ config->writeEntry("DensityAjustment", m_densityInput->value());
+ config->writeEntry("PowerAjustment", m_powerInput->value());
+ config->writeEntry("RadiusAjustment", m_radiusInput->value());
+ config->writeEntry("BrightnessAjustment", m_brightnessInput->value());
+ config->writeEntry("ContrastAjustment", m_contrastInput->value());
+ config->writeEntry("GammaAjustment", m_gammaInput->value());
+ config->sync();
+}
+
+void ImageEffect_AntiVignetting::resetValues()
+{
+ m_densityInput->blockSignals(true);
+ m_powerInput->blockSignals(true);
+ m_radiusInput->blockSignals(true);
+ m_brightnessInput->blockSignals(true);
+ m_contrastInput->blockSignals(true);
+ m_gammaInput->blockSignals(true);
+
+ m_densityInput->setValue(2.0);
+ m_powerInput->setValue(1.0);
+ m_radiusInput->setValue(1.0);
+ m_brightnessInput->setValue(0);
+ m_contrastInput->setValue(0);
+ m_gammaInput->setValue(1.0);
+
+ m_densityInput->blockSignals(false);
+ m_powerInput->blockSignals(false);
+ m_radiusInput->blockSignals(false);
+ m_brightnessInput->blockSignals(false);
+ m_contrastInput->blockSignals(false);
+ m_gammaInput->blockSignals(false);
+}
+
+void ImageEffect_AntiVignetting::prepareEffect()
+{
+ m_densityInput->setEnabled(false);
+ m_powerInput->setEnabled(false);
+ m_radiusInput->setEnabled(false);
+ m_brightnessInput->setEnabled(false);
+ m_contrastInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+
+ double d = m_densityInput->value();
+ double p = m_powerInput->value();
+ double r = m_radiusInput->value();
+
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int orgWidth = iface->originalWidth();
+ int orgHeight = iface->originalHeight();
+ TQSize ps(orgWidth, orgHeight);
+ ps.scale( TQSize(120, 120), TQSize::ScaleMin );
+
+ // Calc mask preview.
+ Digikam::DImg preview(ps.width(), ps.height(), false);
+ memset(preview.bits(), 255, preview.numBytes());
+ AntiVignetting maskPreview(&preview, 0L, d, p, r, 0, 0, false);
+ TQPixmap pix = maskPreview.getTargetImage().convertToPixmap();
+ TQPainter pt(&pix);
+ pt.setPen( TQPen(TQt::black, 1) );
+ pt.drawRect( 0, 0, pix.width(), pix.height() );
+ pt.end();
+ m_maskPreviewLabel->setPixmap( pix );
+
+ Digikam::DImg orgImage(orgWidth, orgHeight, iface->originalSixteenBit(),
+ iface->originalHasAlpha(), data);
+ delete [] data;
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new AntiVignetting(&orgImage, this, d, p, r, 0, 0, true));
+}
+
+void ImageEffect_AntiVignetting::prepareFinal()
+{
+ m_densityInput->setEnabled(false);
+ m_powerInput->setEnabled(false);
+ m_radiusInput->setEnabled(false);
+ m_brightnessInput->setEnabled(false);
+ m_contrastInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+
+ double d = m_densityInput->value();
+ double p = m_powerInput->value();
+ double r = m_radiusInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+
+ uchar *data = iface.getOriginalImage();
+ Digikam::DImg orgImage(iface.originalWidth(), iface.originalHeight(), iface.originalSixteenBit(),
+ iface.originalHasAlpha(), data);
+ delete [] data;
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new AntiVignetting(&orgImage, this, d, p, r, 0, 0, true));
+}
+
+void ImageEffect_AntiVignetting::putPreviewData(void)
+{
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage();
+
+ // Adjust Image BCG.
+
+ double b = (double)(m_brightnessInput->value() / 100.0);
+ double c = (double)(m_contrastInput->value() / 100.0) + (double)(1.00);
+ double g = m_gammaInput->value();
+
+ Digikam::BCGModifier cmod;
+ cmod.setGamma(g);
+ cmod.setBrightness(b);
+ cmod.setContrast(c);
+ cmod.applyBCG(imDest);
+
+ iface->putPreviewImage((imDest.smoothScale(iface->previewWidth(),
+ iface->previewHeight())).bits());
+ m_imagePreviewWidget->updatePreview();
+}
+
+void ImageEffect_AntiVignetting::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Vignetting Correction"),
+ m_threadedFilter->getTargetImage().bits());
+
+ double b = (double)(m_brightnessInput->value() / 100.0);
+ double c = (double)(m_contrastInput->value() / 100.0) + (double)(1.00);
+ double g = m_gammaInput->value();
+
+ // Adjust Image BCG.
+ iface.setOriginalBCG(b, c, g);
+}
+
+} // NameSpace DigikamAntiVignettingImagesPlugin
+
diff --git a/src/imageplugins/antivignetting/imageeffect_antivignetting.h b/src/imageplugins/antivignetting/imageeffect_antivignetting.h
new file mode 100644
index 00000000..3ee6f158
--- /dev/null
+++ b/src/imageplugins/antivignetting/imageeffect_antivignetting.h
@@ -0,0 +1,79 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : a digiKam image plugin to reduce
+ * vignetting on an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_ANTIVIGNETTING_H
+#define IMAGEEFFECT_ANTIVIGNETTING_H
+
+// Digikam includes.
+
+#include "imageguidedlg.h"
+
+class TQLabel;
+
+class KIntNumInput;
+class KDoubleNumInput;
+
+namespace DigikamAntiVignettingImagesPlugin
+{
+
+class ImageEffect_AntiVignetting : public Digikam::ImageGuideDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_AntiVignetting(TQWidget *parent);
+ ~ImageEffect_AntiVignetting();
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQLabel *m_maskPreviewLabel;
+
+ KIntNumInput *m_brightnessInput;
+ KIntNumInput *m_contrastInput;
+
+ KDoubleNumInput *m_gammaInput;
+ KDoubleNumInput *m_densityInput;
+ KDoubleNumInput *m_powerInput;
+ KDoubleNumInput *m_radiusInput;
+};
+
+} // NameSpace DigikamAntiVignettingImagesPlugin
+
+#endif /* IMAGEEFFECT_ANTIVIGNETTING_H */
diff --git a/src/imageplugins/antivignetting/imageplugin_antivignetting.cpp b/src/imageplugins/antivignetting/imageplugin_antivignetting.cpp
new file mode 100644
index 00000000..239d9842
--- /dev/null
+++ b/src/imageplugins/antivignetting/imageplugin_antivignetting.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-25
+ * Description : a digiKam image plugin to reduce
+ * vignetting on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "antivignettingtool.h"
+#include "imageplugin_antivignetting.h"
+#include "imageplugin_antivignetting.moc"
+
+using namespace DigikamAntiVignettingImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_antivignetting,
+ KGenericFactory<ImagePlugin_AntiVignetting>("digikamimageplugin_antivignetting"));
+
+ImagePlugin_AntiVignetting::ImagePlugin_AntiVignetting(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_AntiVignetting")
+{
+ m_antivignettingAction = new TDEAction(i18n("Vignetting Correction..."), "antivignetting", 0,
+ this, TQ_SLOT(slotAntiVignetting()),
+ actionCollection(), "imageplugin_antivignetting");
+
+ setXMLFile("digikamimageplugin_antivignetting_ui.rc");
+
+ DDebug() << "ImagePlugin_AntiVignetting plugin loaded" << endl;
+}
+
+ImagePlugin_AntiVignetting::~ImagePlugin_AntiVignetting()
+{
+}
+
+void ImagePlugin_AntiVignetting::setEnabledActions(bool enable)
+{
+ m_antivignettingAction->setEnabled(enable);
+}
+
+void ImagePlugin_AntiVignetting::slotAntiVignetting()
+{
+ AntiVignettingTool *tool = new AntiVignettingTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/antivignetting/imageplugin_antivignetting.h b/src/imageplugins/antivignetting/imageplugin_antivignetting.h
new file mode 100644
index 00000000..d8d4eedd
--- /dev/null
+++ b/src/imageplugins/antivignetting/imageplugin_antivignetting.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-25
+ * Description : a digiKam image plugin to reduce
+ * vignetting on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_ANTIVIGNETTING_H
+#define IMAGEPLUGIN_ANTIVIGNETTING_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_AntiVignetting : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_AntiVignetting(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_AntiVignetting();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotAntiVignetting();
+
+private:
+
+ TDEAction *m_antivignettingAction;
+};
+
+#endif /* IMAGEPLUGIN_ANTIVIGNETTING_H */
diff --git a/src/imageplugins/blurfx/Makefile.am b/src/imageplugins/blurfx/Makefile.am
new file mode 100644
index 00000000..51a78977
--- /dev/null
+++ b/src/imageplugins/blurfx/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_blurfx_la_SOURCES = imageplugin_blurfx.cpp \
+ blurfxtool.cpp blurfx.cpp
+
+digikamimageplugin_blurfx_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_blurfx_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_blurfx.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_blurfx.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_blurfx_ui.rc
+
diff --git a/src/imageplugins/blurfx/blurfx.cpp b/src/imageplugins/blurfx/blurfx.cpp
new file mode 100644
index 00000000..ec5ff30e
--- /dev/null
+++ b/src/imageplugins/blurfx/blurfx.cpp
@@ -0,0 +1,1445 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Blur FX threaded image filter.
+ *
+ * Copyright 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Blur algorithms copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Represents 1
+#define ANGLE_RATIO 0.017453292519943295769236907685
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
+// TQt includes.
+
+#include <tqdatetime.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dimggaussianblur.h"
+#include "blurfx.h"
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+BlurFX::BlurFX(Digikam::DImg *orgImage, TQObject *parent, int blurFXType, int distance, int level)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "BlurFX")
+{
+ m_blurFXType = blurFXType;
+ m_distance = distance;
+ m_level = level;
+
+ initFilter();
+}
+
+void BlurFX::filterImage(void)
+{
+ int w = m_orgImage.width();
+ int h = m_orgImage.height();
+
+ switch (m_blurFXType)
+ {
+ case ZoomBlur:
+ zoomBlur(&m_orgImage, &m_destImage, w/2, h/2, m_distance);
+ break;
+
+ case RadialBlur:
+ radialBlur(&m_orgImage, &m_destImage, w/2, h/2, m_distance);
+ break;
+
+ case FarBlur:
+ farBlur(&m_orgImage, &m_destImage, m_distance);
+ break;
+
+ case MotionBlur:
+ motionBlur(&m_orgImage, &m_destImage, m_distance, (double)m_level);
+ break;
+
+ case SoftenerBlur:
+ softenerBlur(&m_orgImage, &m_destImage);
+ break;
+
+ case ShakeBlur:
+ shakeBlur(&m_orgImage, &m_destImage, m_distance);
+ break;
+
+ case FocusBlur:
+ focusBlur(&m_orgImage, &m_destImage, w/2, h/2, m_distance, m_level*10);
+ break;
+
+ case SmartBlur:
+ smartBlur(&m_orgImage, &m_destImage, m_distance, m_level);
+ break;
+
+ case FrostGlass:
+ frostGlass(&m_orgImage, &m_destImage, m_distance);
+ break;
+
+ case Mosaic:
+ mosaic(&m_orgImage, &m_destImage, m_distance, m_distance);
+ break;
+ }
+}
+
+/* Function to apply the ZoomBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * X, Y => Center of zoom in the image
+ * Distance => Distance value
+ * pArea => Preview area.
+ *
+ * Theory => Here we have a effect similar to RadialBlur mode Zoom from
+ * Photoshop. The theory is very similar to RadialBlur, but has one
+ * difference. Instead we use pixels with the same radius and
+ * near angles, we take pixels with the same angle but near radius
+ * This radius is always from the center to out of the image, we
+ * calc a proportional radius from the center.
+ */
+void BlurFX::zoomBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int X, int Y, int Distance, TQRect pArea)
+{
+ if (Distance <= 1) return;
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ // We working on full image.
+ int xMin = 0;
+ int xMax = Width;
+ int yMin = 0;
+ int yMax = Height;
+
+ // If we working in preview mode, else we using the preview area.
+ if ( pArea.isValid() )
+ {
+ xMin = pArea.x();
+ xMax = pArea.x() + pArea.width();
+ yMin = pArea.y();
+ yMax = pArea.y() + pArea.height();
+ }
+
+ int h, w, nh, nw, r;
+ int sumR, sumG, sumB, nCount;
+ double lfRadius, lfNewRadius, lfRadMax, lfAngle;
+
+ Digikam::DColor color;
+ int offset;
+
+ lfRadMax = sqrt (Height * Height + Width * Width);
+
+ // number of added pixels
+ nCount = 0;
+
+ // we have reached the main loop
+ for (h = yMin; !m_cancel && (h < yMax); h++)
+ {
+ for (w = xMin; !m_cancel && (w < xMax); w++)
+ {
+ // ...we enter this loop to sum the bits
+
+ // we initialize the variables
+ sumR = sumG = sumB = nCount = 0;
+
+ nw = X - w;
+ nh = Y - h;
+
+ lfRadius = sqrt (nw * nw + nh * nh);
+ lfAngle = atan2 ((double)nh, (double)nw);
+ lfNewRadius = (lfRadius * Distance) / lfRadMax;
+
+ for (r = 0; !m_cancel && (r <= lfNewRadius); r++)
+ {
+ // we need to calc the positions
+ nw = (int)(X - (lfRadius - r) * cos (lfAngle));
+ nh = (int)(Y - (lfRadius - r) * sin (lfAngle));
+
+ if (IsInside(Width, Height, nw, nh))
+ {
+ // read color
+ offset = GetOffset(Width, nw, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ nCount++;
+ }
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)(h - yMin) * 100.0) / (yMax - yMin));
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the radialBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * X, Y => Center of radial in the image
+ * Distance => Distance value
+ * pArea => Preview area.
+ *
+ * Theory => Similar to RadialBlur from Photoshop, its an amazing effect
+ * Very easy to understand but a little hard to implement.
+ * We have all the image and find the center pixel. Now, we analize
+ * all the pixels and calc the radius from the center and find the
+ * angle. After this, we sum this pixel with others with the same
+ * radius, but different angles. Here I'm using degrees angles.
+ */
+void BlurFX::radialBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int X, int Y, int Distance, TQRect pArea)
+{
+ if (Distance <= 1) return;
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ // We working on full image.
+ int xMin = 0;
+ int xMax = Width;
+ int yMin = 0;
+ int yMax = Height;
+
+ // If we working in preview mode, else we using the preview area.
+ if ( pArea.isValid() )
+ {
+ xMin = pArea.x();
+ xMax = pArea.x() + pArea.width();
+ yMin = pArea.y();
+ yMax = pArea.y() + pArea.height();
+ }
+
+ int sumR, sumG, sumB, nw, nh;
+ double Radius, Angle, AngleRad;
+
+ Digikam::DColor color;
+ int offset;
+
+ double *nMultArray = new double[Distance * 2 + 1];
+
+ for (int i = -Distance; i <= Distance; i++)
+ nMultArray[i + Distance] = i * ANGLE_RATIO;
+
+ // number of added pixels
+ int nCount = 0;
+
+ // we have reached the main loop
+
+ for (int h = yMin; !m_cancel && (h < yMax); h++)
+ {
+ for (int w = xMin; !m_cancel && (w < xMax); w++)
+ {
+ // ...we enter this loop to sum the bits
+
+ // we initialize the variables
+ sumR = sumG = sumB = nCount = 0;
+
+ nw = X - w;
+ nh = Y - h;
+
+ Radius = sqrt (nw * nw + nh * nh);
+ AngleRad = atan2 ((double)nh, (double)nw);
+
+ for (int a = -Distance; !m_cancel && (a <= Distance); a++)
+ {
+ Angle = AngleRad + nMultArray[a + Distance];
+ // we need to calc the positions
+ nw = (int)(X - Radius * cos (Angle));
+ nh = (int)(Y - Radius * sin (Angle));
+
+ if (IsInside(Width, Height, nw, nh))
+ {
+ // read color
+ offset = GetOffset(Width, nw, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ nCount++;
+ }
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)(h - yMin) * 100.0) / (yMax - yMin));
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete [] nMultArray;
+}
+
+/* Function to apply the focusBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * BlurRadius => Radius of blurred image.
+ * BlendRadius => Radius of blending effect.
+ * bInversed => If true, invert focus effect.
+ * pArea => Preview area.
+ *
+ */
+void BlurFX::focusBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int X, int Y, int BlurRadius, int BlendRadius,
+ bool bInversed, TQRect pArea)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ // We working on full image.
+ int xMin = 0;
+ int xMax = Width;
+ int yMin = 0;
+ int yMax = Height;
+
+ // If we working in preview mode, else we using the preview area.
+ if ( pArea.isValid() )
+ {
+ xMin = pArea.x();
+ xMax = pArea.x() + pArea.width();
+ yMin = pArea.y();
+ yMax = pArea.y() + pArea.height();
+ }
+
+ if (pArea.isValid())
+ {
+ //UNTESTED (unused)
+
+ // We do not have access to the loop of the Gaussian blur,
+ // so we have to cut the image that we run the effect on.
+ int xMinBlur = xMin - BlurRadius;
+ int xMaxBlur = xMax + BlurRadius;
+ int yMinBlur = yMin - BlurRadius;
+ int yMaxBlur = yMax + BlurRadius;
+ Digikam::DImg areaImage = orgImage->copy(xMinBlur, yMaxBlur, xMaxBlur - xMinBlur, yMaxBlur - yMinBlur);
+
+ Digikam::DImgGaussianBlur(this, *orgImage, *destImage, 10, 75, BlurRadius);
+
+ // I am unsure about differences of 1 pixel
+ destImage->bitBltImage(&areaImage, xMinBlur, yMinBlur);
+ destImage->bitBltImage(orgImage, 0, 0, Width, yMinBlur, 0, 0);
+ destImage->bitBltImage(orgImage, 0, yMinBlur, xMinBlur, yMaxBlur - yMinBlur, 0, yMinBlur);
+ destImage->bitBltImage(orgImage, xMaxBlur + 1, yMinBlur, Width - xMaxBlur - 1, yMaxBlur - yMinBlur, yMaxBlur, yMinBlur);
+ destImage->bitBltImage(orgImage, 0, yMaxBlur + 1, Width, Height - yMaxBlur - 1, 0, yMaxBlur);
+
+ postProgress(80);
+ }
+ else
+ {
+ // copy bits for blurring
+ memcpy(pResBits, data, orgImage->numBytes());
+
+ // Gaussian blur using the BlurRadius parameter.
+ Digikam::DImgGaussianBlur(this, *orgImage, *destImage, 10, 80, BlurRadius);
+ }
+
+ // Blending results.
+
+ int nBlendFactor;
+ double lfRadius;
+ int offset;
+
+ Digikam::DColor colorOrgImage, colorBlurredImage;
+ int alpha;
+ uchar *ptr;
+
+ // get composer for default blending
+ Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(Digikam::DColorComposer::PorterDuffNone);
+
+ int nh = 0, nw = 0;
+
+ for (int h = yMin; !m_cancel && (h < yMax); h++)
+ {
+ nh = Y - h;
+
+ for (int w = xMin; !m_cancel && (w < xMax); w++)
+ {
+ nw = X - w;
+
+ lfRadius = sqrt (nh * nh + nw * nw);
+
+ if (sixteenBit)
+ nBlendFactor = LimitValues16 ((int)(65535.0 * lfRadius / (double)BlendRadius));
+ else
+ nBlendFactor = LimitValues8 ((int)(255.0 * lfRadius / (double)BlendRadius));
+
+ // Read color values
+ offset = GetOffset(Width, w, h, bytesDepth);
+ ptr = pResBits + offset;
+ colorOrgImage.setColor(data + offset, sixteenBit);
+ colorBlurredImage.setColor(ptr, sixteenBit);
+
+ // Preserve alpha
+ alpha = colorOrgImage.alpha();
+
+ // In normal mode, the image is focused in the middle
+ // and less focused towards the border.
+ // In inversed mode, the image is more focused towards the edge
+ // and less focused in the middle.
+ // This is achieved by swapping src and dest while blending.
+ if (bInversed)
+ {
+ // set blending alpha value as src alpha. Original value is stored above.
+ colorOrgImage.setAlpha(nBlendFactor);
+ // compose colors, writing to dest - colorBlurredImage
+ composer->compose(colorBlurredImage, colorOrgImage);
+ // restore alpha
+ colorBlurredImage.setAlpha(alpha);
+ // write color to destination
+ colorBlurredImage.setPixel(ptr);
+ }
+ else
+ {
+ // set blending alpha value as src alpha. Original value is stored above.
+ colorBlurredImage.setAlpha(nBlendFactor);
+ // compose colors, writing to dest - colorOrgImage
+ composer->compose(colorOrgImage, colorBlurredImage);
+ // restore alpha
+ colorOrgImage.setAlpha(alpha);
+ // write color to destination
+ colorOrgImage.setPixel(ptr);
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (80.0 + ((double)(h - yMin) * 20.0) / (yMax - yMin));
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete composer;
+}
+
+/* Function to apply the farBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Distance => Distance value
+ *
+ * Theory => This is an interesting effect, the blur is applied in that
+ * way: (the value "1" means pixel to be used in a blur calc, ok?)
+ * e.g. With distance = 2
+ * |1|1|1|1|1|
+ * |1|0|0|0|1|
+ * |1|0|C|0|1|
+ * |1|0|0|0|1|
+ * |1|1|1|1|1|
+ * We sum all the pixels with value = 1 and apply at the pixel with*
+ * the position "C".
+ */
+void BlurFX::farBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance)
+{
+ if (Distance < 1) return;
+
+ // we need to create our kernel
+ // e.g. distance = 3, so kernel={3 1 1 2 1 1 3}
+
+ int *nKern = new int[Distance * 2 + 1];
+
+ for (int i = 0; i < Distance * 2 + 1; i++)
+ {
+ // the first element is 3
+ if (i == 0)
+ nKern[i] = 2;
+ // the center element is 2
+ else if (i == Distance)
+ nKern[i] = 3;
+ // the last element is 3
+ else if (i == Distance * 2)
+ nKern[i] = 3;
+ // all other elements will be 1
+ else
+ nKern[i] = 1;
+ }
+
+ // now, we apply a convolution with kernel
+ MakeConvolution(orgImage, destImage, Distance, nKern);
+
+ // we must delete to free memory
+ delete [] nKern;
+}
+
+/* Function to apply the SmartBlur effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Radius => blur matrix radius.
+ * Strenght => Color strenght.
+ *
+ * Theory => Similar to SmartBlur from Photoshop, this function has the
+ * same engine as Blur function, but, in a matrix with n
+ * dimentions, we take only colors that pass by sensibility filter
+ * The result is a clean image, not totally blurred, but a image
+ * with correction between pixels.
+ */
+
+void BlurFX::smartBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Radius, int Strength)
+{
+ if (Radius <= 0) return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int progress;
+ int sumR, sumG, sumB, nCount, w, h, a;
+
+ int StrengthRange = Strength;
+ if (sixteenBit)
+ StrengthRange = (StrengthRange + 1) * 256 - 1;
+
+ Digikam::DColor color, radiusColor, radiusColorBlur;
+ int offset, loopOffset;
+
+ uchar* pBlur = new uchar[orgImage->numBytes()];
+
+ // We need to copy our bits to blur bits
+
+ memcpy (pBlur, data, orgImage->numBytes());
+
+ // we have reached the main loop
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ // we initialize the variables
+ sumR = sumG = sumB = nCount = 0;
+
+ // read color
+ offset = GetOffset(Width, w, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // ...we enter this loop to sum the bits
+ for (a = -Radius; !m_cancel && (a <= Radius); a++)
+ {
+ // verify if is inside the rect
+ if (IsInside( Width, Height, w + a, h))
+ {
+ // read color
+ loopOffset = GetOffset(Width, w+a, h, bytesDepth);
+ radiusColor.setColor(data + loopOffset, sixteenBit);
+
+ // now, we have to check if is inside the sensibility filter
+ if (IsColorInsideTheRange (color.red(), color.green(), color.blue(),
+ radiusColor.red(), radiusColor.green(), radiusColor.blue(),
+ StrengthRange))
+ {
+ // finally we sum the bits
+ sumR += radiusColor.red();
+ sumG += radiusColor.green();
+ sumB += radiusColor.blue();
+ }
+ else
+ {
+ // finally we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ }
+
+ // increment counter
+ nCount++;
+ }
+ }
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pBlur + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 50.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ // we have reached the second part of main loop
+
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ for (h = 0;!m_cancel && ( h < Height); h++)
+ {
+ // we initialize the variables
+ sumR = sumG = sumB = nCount = 0;
+
+ // read color
+ offset = GetOffset(Width, w, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // ...we enter this loop to sum the bits
+ for (a = -Radius; !m_cancel && (a <= Radius); a++)
+ {
+ // verify if is inside the rect
+ if (IsInside( Width, Height, w, h + a))
+ {
+ // read color
+ loopOffset = GetOffset(Width, w, h+a, bytesDepth);
+ radiusColor.setColor(data + loopOffset, sixteenBit);
+
+ // now, we have to check if is inside the sensibility filter
+ if (IsColorInsideTheRange (color.red(), color.green(), color.blue(),
+ radiusColor.red(), radiusColor.green(), radiusColor.blue(),
+ StrengthRange))
+ {
+ radiusColorBlur.setColor(pBlur + loopOffset, sixteenBit);
+ // finally we sum the bits
+ sumR += radiusColorBlur.red();
+ sumG += radiusColorBlur.green();
+ sumB += radiusColorBlur.blue();
+ }
+ else
+ {
+ // finally we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ }
+
+ // increment counter
+ nCount++;
+ }
+ }
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (50.0 + ((double)w * 50.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ // now, we must free memory
+ delete [] pBlur;
+}
+
+/* Function to apply the motionBlur effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Distance => Distance value
+ * Angle => Angle direction (degrees)
+ *
+ * Theory => Similar to MotionBlur from Photoshop, the engine is very
+ * simple to undertand, we take a pixel (duh!), with the angle we
+ * will taking near pixels. After this we blur (add and do a
+ * division).
+ */
+void BlurFX::motionBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance, double Angle)
+{
+ if (Distance == 0) return;
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ Digikam::DColor color;
+ int offset;
+
+ // we try to avoid division by 0 (zero)
+ if (Angle == 0.0) Angle = 360.0;
+
+ int sumR, sumG, sumB, nCount, nw, nh;
+ double nAngX, nAngY;
+
+ // we initialize cos and sin for a best performance
+ nAngX = cos ((2.0 * M_PI) / (360.0 / Angle));
+ nAngY = sin ((2.0 * M_PI) / (360.0 / Angle));
+
+ // total of bits to be taken is given by this formula
+ nCount = Distance * 2 + 1;
+
+ // we will alloc size and calc the possible results
+ int *lpXArray = new int[nCount];
+ int *lpYArray = new int[nCount];
+
+ for (int i = 0; i < nCount; i++)
+ {
+ lpXArray[i] = lround( (double)(i - Distance) * nAngX);
+ lpYArray[i] = lround( (double)(i - Distance) * nAngY);
+ }
+
+ // we have reached the main loop
+
+ for (int h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (int w = 0; !m_cancel && (w < Width); w++)
+ {
+ // we initialize the variables
+ sumR = sumG = sumB = 0;
+
+ // ...we enter this loop to sum the bits
+ for (int a = -Distance; !m_cancel && (a <= Distance); a++)
+ {
+ // we need to calc the positions
+ nw = w + lpXArray[a + Distance];
+ nh = h + lpYArray[a + Distance];
+
+ offset = GetOffsetAdjusted(Width, Height, nw, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // we sum the bits
+ sumR += color.red();
+ sumG += color.green();
+ sumB += color.blue();
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ color.setRed (sumR / nCount);
+ color.setGreen(sumG / nCount);
+ color.setBlue (sumB / nCount);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete [] lpXArray;
+ delete [] lpYArray;
+}
+
+/* Function to apply the softenerBlur effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ *
+ * Theory => An interesting blur-like function. In dark tones we apply a
+ * blur with 3x3 dimentions, in light tones, we apply a blur with
+ * 5x5 dimentions. Easy, hun?
+ */
+void BlurFX::softenerBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int SomaR = 0, SomaG = 0, SomaB = 0;
+ int Gray;
+
+ Digikam::DColor color, colorSoma;
+ int offset, offsetSoma;
+
+ int grayLimit = sixteenBit ? 32767 : 127;
+
+ for (int h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (int w = 0; !m_cancel && (w < Width); w++)
+ {
+ SomaR = SomaG = SomaB = 0;
+
+ offset = GetOffset(Width, w, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ Gray = (color.red() + color.green() + color.blue()) / 3;
+
+ if (Gray > grayLimit)
+ {
+ // 7x7
+ for (int a = -3; !m_cancel && (a <= 3); a++)
+ {
+ for (int b = -3; !m_cancel && (b <= 3); b++)
+ {
+ if ((h + a < 0) || (w + b < 0))
+ offsetSoma = offset;
+ else
+ offsetSoma = GetOffset(Width, (w + Lim_Max (w, b, Width)),
+ (h + Lim_Max (h, a, Height)), bytesDepth);
+ colorSoma.setColor(data + offsetSoma, sixteenBit);
+
+ SomaR += colorSoma.red();
+ SomaG += colorSoma.green();
+ SomaB += colorSoma.blue();
+ }
+ }
+
+ // 7*7 = 49
+ color.setRed (SomaR / 49);
+ color.setGreen(SomaG / 49);
+ color.setBlue (SomaB / 49);
+ color.setPixel(pResBits + offset);
+ }
+ else
+ {
+ // 3x3
+ for (int a = -1; !m_cancel && (a <= 1); a++)
+ {
+ for (int b = -1; !m_cancel && (b <= 1); b++)
+ {
+ if ((h + a < 0) || (w + b < 0))
+ offsetSoma = offset;
+ else
+ offsetSoma = GetOffset(Width, (w + Lim_Max (w, b, Width)),
+ (h + Lim_Max (h, a, Height)), bytesDepth);
+ colorSoma.setColor(data + offsetSoma, sixteenBit);
+
+ SomaR += colorSoma.red();
+ SomaG += colorSoma.green();
+ SomaB += colorSoma.blue();
+ }
+ }
+
+ // 3*3 = 9
+ color.setRed (SomaR / 9);
+ color.setGreen(SomaG / 9);
+ color.setBlue (SomaB / 9);
+ color.setPixel(pResBits + offset);
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the shake blur effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Distance => Distance between layers (from origin)
+ *
+ * Theory => Similar to Fragment effect from Photoshop. We create 4 layers
+ * each one has the same distance from the origin, but have
+ * different positions (top, button, left and right), with these 4
+ * layers, we join all the pixels.
+ */
+void BlurFX::shakeBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ Digikam::DColor color, colorLayer, color1, color2, color3, color4;
+ int offset, offsetLayer;
+
+ int numBytes = orgImage->numBytes();
+ uchar* Layer1 = new uchar[numBytes];
+ uchar* Layer2 = new uchar[numBytes];
+ uchar* Layer3 = new uchar[numBytes];
+ uchar* Layer4 = new uchar[numBytes];
+
+ int h, w, nw, nh;
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ offsetLayer = GetOffset(Width, w, h, bytesDepth);
+
+ nh = (h + Distance >= Height) ? Height - 1 : h + Distance;
+ offset = GetOffset(Width, w, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(Layer1 + offsetLayer);
+
+ nh = (h - Distance < 0) ? 0 : h - Distance;
+ offset = GetOffset(Width, w, nh, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(Layer2 + offsetLayer);
+
+ nw = (w + Distance >= Width) ? Width - 1 : w + Distance;
+ offset = GetOffset(Width, nw, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(Layer3 + offsetLayer);
+
+ nw = (w - Distance < 0) ? 0 : w - Distance;
+ offset = GetOffset(Width, nw, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(Layer4 + offsetLayer);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 50.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ for (int h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (int w = 0; !m_cancel && (w < Width); w++)
+ {
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read original data to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+ // read colors from all four layers
+ color1.setColor(Layer1 + offset, sixteenBit);
+ color2.setColor(Layer2 + offset, sixteenBit);
+ color3.setColor(Layer3 + offset, sixteenBit);
+ color4.setColor(Layer4 + offset, sixteenBit);
+
+ // set color components of resulting color
+ color.setRed ( (color1.red() + color2.red() + color3.red() + color4.red()) / 4 );
+ color.setGreen( (color1.green() + color2.green() + color3.green() + color4.green()) / 4 );
+ color.setBlue ( (color1.blue() + color2.blue() + color3.blue() + color4.blue()) / 4 );
+
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (50.0 + ((double)h * 50.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete [] Layer1;
+ delete [] Layer2;
+ delete [] Layer3;
+ delete [] Layer4;
+}
+
+/* Function to apply the frostGlass effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Frost => Frost value
+ *
+ * Theory => Similar to Diffuse effect, but the random byte is defined
+ * in a matrix. Diffuse uses a random diagonal byte.
+ */
+void BlurFX::frostGlass(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Frost)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ Frost = (Frost < 1) ? 1 : (Frost > 10) ? 10 : Frost;
+
+ int h, w;
+
+ Digikam::DColor color;
+ int offset;
+
+ // Randomize.
+
+ TQDateTime dt = TQDateTime::currentDateTime();
+ TQDateTime Y2000( TQDate(2000, 1, 1), TQTime(0, 0, 0) );
+ uint seed = dt.secsTo(Y2000);
+
+ int range = sixteenBit ? 65535 : 255;
+
+ // it is a huge optimizsation to allocate these here once
+ uchar *IntensityCount = new uchar[range + 1];
+ uint *AverageColorR = new uint[range + 1];
+ uint *AverageColorG = new uint[range + 1];
+ uint *AverageColorB = new uint[range + 1];
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // get random color from surrounding of w|h
+ color = RandomColor (data, Width, Height, sixteenBit, bytesDepth,
+ w, h, Frost, color.alpha(), &seed, range, IntensityCount,
+ AverageColorR, AverageColorG, AverageColorB);
+
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete [] IntensityCount;
+ delete [] AverageColorR;
+ delete [] AverageColorG;
+ delete [] AverageColorB;
+}
+
+/* Function to apply the mosaic effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Size => Size of mosaic .
+ *
+ * Theory => Ok, you can find some mosaic effects on PSC, but this one
+ * has a great feature, if you see a mosaic in other code you will
+ * see that the corner pixel doesn't change. The explanation is
+ * simple, the color of the mosaic is the same as the first pixel
+ * get. Here, the color of the mosaic is the same as the mosaic
+ * center pixel.
+ * Now the function scan the rows from the top (like photoshop).
+ */
+void BlurFX::mosaic(Digikam::DImg *orgImage, Digikam::DImg *destImage, int SizeW, int SizeH)
+{
+ int progress;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ // we need to check for valid values
+ if (SizeW < 1) SizeW = 1;
+ if (SizeH < 1) SizeH = 1;
+ if ((SizeW == 1) && (SizeH == 1)) return;
+
+ Digikam::DColor color;
+ int offsetCenter, offset;
+
+ // this loop will never look for transparent colors
+
+ for (int h = 0; !m_cancel && (h < Height); h += SizeH)
+ {
+ for (int w = 0; !m_cancel && (w < Width); w += SizeW)
+ {
+ // we have to find the center pixel for mosaic's rectangle
+
+ offsetCenter = GetOffsetAdjusted(Width, Height, w + (SizeW / 2), h + (SizeH / 2), bytesDepth);
+ color.setColor(data + offsetCenter, sixteenBit);
+
+ // now, we fill the mosaic's rectangle with the center pixel color
+
+ for (int subw = w; !m_cancel && (subw <= w + SizeW); subw++)
+ {
+ for (int subh = h; !m_cancel && (subh <= h + SizeH); subh++)
+ {
+ // if is inside...
+ if (IsInside(Width, Height, subw, subh))
+ {
+ // set color
+ offset = GetOffset(Width, subw, subh, bytesDepth);
+ color.setPixel(pResBits + offset);
+ }
+ }
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to get a color in a matriz with a determined size
+ *
+ * Bits => Bits array
+ * Width => Image width
+ * Height => Image height
+ * X => Position horizontal
+ * Y => Position vertical
+ * Radius => The radius of the matrix to be created
+ *
+ * Theory => This function takes from a distinct matrix a random color
+ */
+Digikam::DColor BlurFX::RandomColor(uchar *Bits, int Width, int Height, bool sixteenBit, int bytesDepth,
+ int X, int Y, int Radius,
+ int alpha, uint *randomSeed, int range, uchar *IntensityCount,
+ uint *AverageColorR, uint *AverageColorG, uint *AverageColorB)
+{
+ Digikam::DColor color;
+ int offset;
+
+ int w, h, counter = 0;
+
+ int I;
+
+ // For 16 bit we have a problem here because this takes 255 times longer,
+ // and the algorithm is really slow for 16 bit, but I think this cannot be avoided.
+ memset(IntensityCount, 0, range );
+ memset(AverageColorR, 0, range );
+ memset(AverageColorG, 0, range );
+ memset(AverageColorB, 0, range );
+
+ for (w = X - Radius; !m_cancel && (w <= X + Radius); w++)
+ {
+ for (h = Y - Radius; !m_cancel && (h <= Y + Radius); h++)
+ {
+ if ((w >= 0) && (w < Width) && (h >= 0) && (h < Height))
+ {
+ offset = GetOffset(Width, w, h, bytesDepth);
+ color.setColor(Bits + offset, sixteenBit);
+ I = GetIntensity (color.red(), color.green(), color.blue());
+ IntensityCount[I]++;
+ counter++;
+
+ if (IntensityCount[I] == 1)
+ {
+ AverageColorR[I] = color.red();
+ AverageColorG[I] = color.green();
+ AverageColorB[I] = color.blue();
+ }
+ else
+ {
+ AverageColorR[I] += color.red();
+ AverageColorG[I] += color.green();
+ AverageColorB[I] += color.blue();
+ }
+ }
+ }
+ }
+
+ // check for m_cancel here before entering the do loop (will crash with SIGFPE otherwise)
+ if (m_cancel)
+ return Digikam::DColor(0, 0, 0, 0, sixteenBit);
+
+ int RandNumber, count, Index, ErrorCount = 0;
+ int J;
+
+ do
+ {
+ RandNumber = abs( (int)((rand_r(randomSeed) + 1) * ((double)counter / (1 + (double) RAND_MAX))) );
+ count = 0;
+ Index = 0;
+
+ do
+ {
+ count += IntensityCount[Index];
+ Index++;
+ }
+ while (count < RandNumber && !m_cancel);
+
+ J = Index - 1;
+ ErrorCount++;
+ }
+ while ((IntensityCount[J] == 0) && (ErrorCount <= counter) && !m_cancel);
+
+ if (m_cancel)
+ return Digikam::DColor(0, 0, 0, 0, sixteenBit);
+
+
+ color.setSixteenBit(sixteenBit);
+ color.setAlpha(alpha);
+
+ if (ErrorCount >= counter)
+ {
+ color.setRed (AverageColorR[J] / counter);
+ color.setGreen(AverageColorG[J] / counter);
+ color.setBlue (AverageColorB[J] / counter);
+ }
+ else
+ {
+ color.setRed (AverageColorR[J] / IntensityCount[J]);
+ color.setGreen(AverageColorG[J] / IntensityCount[J]);
+ color.setBlue (AverageColorB[J] / IntensityCount[J]);
+ }
+
+ return color;
+}
+
+/* Function to simple convolve a unique pixel with a determined radius
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Radius => kernel radius, e.g. rad=1, so array will be 3X3
+ * Kernel => kernel array to apply.
+ *
+ * Theory => I've worked hard here, but I think this is a very smart
+ * way to convolve an array, its very hard to explain how I reach
+ * this, but the trick here its to store the sum used by the
+ * previous pixel, so we sum with the other pixels that wasn't get
+ */
+void BlurFX::MakeConvolution (Digikam::DImg *orgImage, Digikam::DImg *destImage, int Radius, int Kernel[])
+{
+ if (Radius <= 0) return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pOutBits = destImage->bits();
+
+ int progress;
+ int n, h, w;
+
+ int nSumR, nSumG, nSumB, nCount;
+ int nKernelWidth = Radius * 2 + 1;
+ int range = sixteenBit ? 65536 : 256;
+ Digikam::DColor color;
+ int offset;
+
+ uchar* pBlur = new uchar[orgImage->numBytes()];
+
+ // We need to copy our bits to blur bits
+
+ memcpy (pBlur, data, orgImage->numBytes());
+
+ // We need to alloc a 2d array to help us to store the values
+
+ int** arrMult = Alloc2DArray (nKernelWidth, range);
+
+ for (int i = 0; i < nKernelWidth; i++)
+ for (int j = 0; j < range; j++)
+ arrMult[i][j] = j * Kernel[i];
+
+ // Now, we enter in the main loop
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ // initialize the variables
+ nSumR = nSumG = nSumB = nCount = 0;
+
+ // first of all, we need to blur the horizontal lines
+
+ for (n = -Radius; !m_cancel && (n <= Radius); n++)
+ {
+ // if is inside...
+ if (IsInside (Width, Height, w + n, h))
+ {
+ // read color from orgImage
+ offset = GetOffset(Width, w+n, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+
+ // finally, we sum the pixels using a method similar to assigntables
+ nSumR += arrMult[n + Radius][color.red()];
+ nSumG += arrMult[n + Radius][color.green()];
+ nSumB += arrMult[n + Radius][color.blue()];
+
+ // we need to add the kernel value to the counter
+ nCount += Kernel[n + Radius];
+ }
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color from orgImage to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ if (sixteenBit)
+ {
+ color.setRed (LimitValues16(nSumR / nCount));
+ color.setGreen(LimitValues16(nSumG / nCount));
+ color.setBlue (LimitValues16(nSumB / nCount));
+ }
+ else
+ {
+ color.setRed (LimitValues8(nSumR / nCount));
+ color.setGreen(LimitValues8(nSumG / nCount));
+ color.setBlue (LimitValues8(nSumB / nCount));
+ }
+
+ // write color to blur bits
+ color.setPixel(pBlur + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 50.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ // We enter in the second main loop
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ // initialize the variables
+ nSumR = nSumG = nSumB = nCount = 0;
+
+ // first of all, we need to blur the vertical lines
+ for (n = -Radius; !m_cancel && (n <= Radius); n++)
+ {
+ // if is inside...
+ if (IsInside(Width, Height, w, h + n))
+ {
+ // read color from blur bits
+ offset = GetOffset(Width, w, h+n, bytesDepth);
+ color.setColor(pBlur + offset, sixteenBit);
+
+ // finally, we sum the pixels using a method similar to assigntables
+ nSumR += arrMult[n + Radius][color.red()];
+ nSumG += arrMult[n + Radius][color.green()];
+ nSumB += arrMult[n + Radius][color.blue()];
+
+ // we need to add the kernel value to the counter
+ nCount += Kernel[n + Radius];
+ }
+ }
+
+ if (nCount == 0) nCount = 1;
+
+ // calculate pointer
+ offset = GetOffset(Width, w, h, bytesDepth);
+ // read color from orgImage to preserve alpha
+ color.setColor(data + offset, sixteenBit);
+
+ // now, we have to calc the arithmetic average
+ if (sixteenBit)
+ {
+ color.setRed (LimitValues16(nSumR / nCount));
+ color.setGreen(LimitValues16(nSumG / nCount));
+ color.setBlue (LimitValues16(nSumB / nCount));
+ }
+ else
+ {
+ color.setRed (LimitValues8(nSumR / nCount));
+ color.setGreen(LimitValues8(nSumG / nCount));
+ color.setBlue (LimitValues8(nSumB / nCount));
+ }
+
+ // write color to destination
+ color.setPixel(pOutBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (50.0 + ((double)w * 50.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ // now, we must free memory
+ Free2DArray (arrMult, nKernelWidth);
+ delete [] pBlur;
+}
+
+} // NameSpace DigikamBlurFXImagesPlugin
diff --git a/src/imageplugins/blurfx/blurfx.h b/src/imageplugins/blurfx/blurfx.h
new file mode 100644
index 00000000..4a4397b4
--- /dev/null
+++ b/src/imageplugins/blurfx/blurfx.h
@@ -0,0 +1,191 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Blur FX threaded image filter.
+ *
+ * Copyright 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Blur algorithms copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef BLURFX_H
+#define BLURFX_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+class BlurFX : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ BlurFX(Digikam::DImg *orgImage, TQObject *parent=0, int blurFXType=ZoomBlur,
+ int distance=100, int level=45);
+
+ ~BlurFX(){};
+
+public:
+
+ enum BlurFXTypes
+ {
+ ZoomBlur=0,
+ RadialBlur,
+ FarBlur,
+ MotionBlur,
+ SoftenerBlur,
+ ShakeBlur,
+ FocusBlur,
+ SmartBlur,
+ FrostGlass,
+ Mosaic
+ };
+
+private: // BlurFX filter data.
+
+ int m_blurFXType;
+ int m_distance;
+ int m_level;
+
+private: // BlurFX filter methods.
+
+ virtual void filterImage(void);
+
+ // Backported from ImageProcessing version 1
+ void softenerBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage);
+ void shakeBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance);
+ void frostGlass(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Frost);
+
+ // Backported from ImageProcessing version 2
+ void zoomBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int X, int Y, int Distance, TQRect pArea=TQRect());
+ void radialBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int X, int Y, int Distance, TQRect pArea=TQRect());
+ void focusBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int X, int Y, int BlurRadius, int BlendRadius,
+ bool bInversed=false, TQRect pArea=TQRect());
+ void farBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance);
+ void motionBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Distance, double Angle=0.0);
+ void smartBlur(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Radius, int Strenght);
+ void mosaic(Digikam::DImg *orgImage, Digikam::DImg *destImage, int SizeW, int SizeH);
+
+private: // Internal filter methods.
+
+ void MakeConvolution(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Radius, int Kernel[]);
+
+ Digikam::DColor RandomColor(uchar *Bits, int Width, int Height, bool sixteenBit, int bytesDepth,
+ int X, int Y, int Radius,
+ int alpha, uint *randomSeed, int range, uchar *IntensityCount,
+ uint *AverageColorR, uint *AverageColorG, uint *AverageColorB);
+
+ // Return the limit defined the max and min values.
+ inline int Lim_Max(int Now, int Up, int Max)
+ {
+ --Max;
+ while (Now > Max - Up) --Up;
+ return (Up);
+ };
+
+ // Return the luminance (Y) component of YIQ color model.
+ inline int GetIntensity (int R, int G, int B)
+ {
+ return (int)(R * 0.3 + G * 0.59 + B * 0.11);
+ };
+
+ // function to allocate a 2d array
+ inline int** Alloc2DArray (int Columns, int Rows)
+ {
+ // First, we declare our future 2d array to be returned
+ int** lpcArray = NULL;
+
+ // Now, we alloc the main pointer with Columns
+ lpcArray = new int*[Columns];
+
+ for (int i = 0; i < Columns; i++)
+ lpcArray[i] = new int[Rows];
+
+ return (lpcArray);
+ }
+
+ // Function to deallocates the 2d array previously created
+ inline void Free2DArray (int** lpcArray, int Columns)
+ {
+ // loop to dealocate the columns
+ for (int i = 0; i < Columns; i++)
+ delete [] lpcArray[i];
+
+ // now, we delete the main pointer
+ delete [] lpcArray;
+ }
+
+ inline bool IsInside (int Width, int Height, int X, int Y)
+ {
+ bool bIsWOk = ((X < 0) ? false : (X >= Width ) ? false : true);
+ bool bIsHOk = ((Y < 0) ? false : (Y >= Height) ? false : true);
+ return (bIsWOk && bIsHOk);
+ };
+
+ inline uchar LimitValues8(int ColorValue)
+ {
+ if (ColorValue > 255) ColorValue = 255;
+ if (ColorValue < 0) ColorValue = 0;
+ return ((uchar) ColorValue);
+ };
+
+
+ inline int LimitValues16(int ColorValue)
+ {
+ if (ColorValue > 65535) ColorValue = 65535;
+ if (ColorValue < 0) ColorValue = 0;
+ return ColorValue;
+ };
+
+ inline int GetOffset(int Width, int X, int Y, int bytesDepth)
+ {
+ return (Y * Width * bytesDepth) + (X * bytesDepth);
+ };
+
+ inline int GetOffsetAdjusted(int Width, int Height, int X, int Y, int bytesDepth)
+ {
+ X = (X < 0) ? 0 : ((X >= Width ) ? (Width - 1) : X);
+ Y = (Y < 0) ? 0 : ((Y >= Height) ? (Height - 1) : Y);
+ return GetOffset(Width, X, Y, bytesDepth);
+ };
+
+ inline bool IsColorInsideTheRange (int cR, int cG, int cB,
+ int nR, int nG, int nB,
+ int Range)
+ {
+ if ((nR >= cR - Range) && (nR <= cR + Range))
+ if ((nG >= cG - Range) && (nG <= cG + Range))
+ if ((nB >= cB - Range) && (nB <= cB + Range))
+ return (true);
+
+ return (false);
+ };
+
+};
+
+} // NameSpace DigikamBlurFXImagesPlugin
+
+#endif /* BLURFX_H */
diff --git a/src/imageplugins/blurfx/blurfxtool.cpp b/src/imageplugins/blurfx/blurfxtool.cpp
new file mode 100644
index 00000000..2998dbde
--- /dev/null
+++ b/src/imageplugins/blurfx/blurfxtool.cpp
@@ -0,0 +1,402 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqdatetime.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqslider.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <kiconloader.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "blurfx.h"
+#include "blurfxtool.h"
+#include "blurfxtool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+BlurFXTool::BlurFXTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("blurfx");
+ setToolName(i18n("Blur FX"));
+ setToolIcon(SmallIcon("blurfx"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 6, 1);
+
+ m_effectTypeLabel = new TQLabel(i18n("Type:"), m_gboxSettings->plainPage());
+
+ m_effectType = new RComboBox(m_gboxSettings->plainPage());
+ m_effectType->insertItem(i18n("Zoom Blur"));
+ m_effectType->insertItem(i18n("Radial Blur"));
+ m_effectType->insertItem(i18n("Far Blur"));
+ m_effectType->insertItem(i18n("Motion Blur"));
+ m_effectType->insertItem(i18n("Softener Blur"));
+ m_effectType->insertItem(i18n("Skake Blur"));
+ m_effectType->insertItem(i18n("Focus Blur"));
+ m_effectType->insertItem(i18n("Smart Blur"));
+ m_effectType->insertItem(i18n("Frost Glass"));
+ m_effectType->insertItem(i18n("Mosaic"));
+ m_effectType->setDefaultItem(BlurFX::ZoomBlur);
+ TQWhatsThis::add( m_effectType, i18n("<p>Select the blurring effect to apply to the image.<p>"
+ "<b>Zoom Blur</b>: blurs the image along radial lines starting from "
+ "a specified center point. This simulates the blur of a zooming camera.<p>"
+ "<b>Radial Blur</b>: blurs the image by rotating the pixels around "
+ "the specified center point. This simulates the blur of a rotating camera.<p>"
+ "<b>Far Blur</b>: blurs the image by using far pixels. This simulates the blur "
+ "of an unfocalized camera lens.<p>"
+ "<b>Motion Blur</b>: blurs the image by moving the pixels horizontally. "
+ "This simulates the blur of a linear moving camera.<p>"
+ "<b>Softener Blur</b>: blurs the image softly in dark tones and hardly in light "
+ "tones. This gives images a dreamy and glossy soft focus effect. It's ideal "
+ "for creating romantic portraits, glamour photographs, or giving images a warm "
+ "and subtle glow.<p>"
+ "<b>Skake Blur</b>: blurs the image by skaking randomly the pixels. "
+ "This simulates the blur of a random moving camera.<p>"
+ "<b>Focus Blur</b>: blurs the image corners to reproduce the astigmatism distortion "
+ "of a lens.<p>"
+ "<b>Smart Blur</b>: finds the edges of color in your image and blurs them without "
+ "muddying the rest of the image.<p>"
+ "<b>Frost Glass</b>: blurs the image by randomly disperse light coming through "
+ "a frosted glass.<p>"
+ "<b>Mosaic</b>: divides the photograph into rectangular cells and then "
+ "recreates it by filling those cells with average pixel value."));
+
+ m_distanceLabel = new TQLabel(i18n("Distance:"), m_gboxSettings->plainPage());
+ m_distanceInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_distanceInput->setRange(0, 100, 1);
+ m_distanceInput->setDefaultValue(3);
+ TQWhatsThis::add( m_distanceInput, i18n("<p>Set here the blur distance in pixels."));
+
+ m_levelLabel = new TQLabel(i18n("Level:"), m_gboxSettings->plainPage());
+ m_levelInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_levelInput->setRange(0, 360, 1);
+ m_levelInput->setDefaultValue(128);
+ TQWhatsThis::add( m_levelInput, i18n("<p>This value controls the level to use with the current effect."));
+
+ grid->addMultiCellWidget(m_effectTypeLabel, 0, 0, 0, 1);
+ grid->addMultiCellWidget(m_effectType, 1, 1, 0, 1);
+ grid->addMultiCellWidget(m_distanceLabel, 2, 2, 0, 1);
+ grid->addMultiCellWidget(m_distanceInput, 3, 3, 0, 1);
+ grid->addMultiCellWidget(m_levelLabel, 4, 4, 0, 1);
+ grid->addMultiCellWidget(m_levelInput, 5, 5, 0, 1);
+ grid->setRowStretch(6, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "blurfx Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_effectType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffectTypeChanged(int)));
+
+ connect(m_distanceInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_levelInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+BlurFXTool::~BlurFXTool()
+{
+}
+
+void BlurFXTool::renderingFinished(void)
+{
+
+ m_effectTypeLabel->setEnabled(true);
+ m_effectType->setEnabled(true);
+ m_distanceInput->setEnabled(true);
+ m_distanceLabel->setEnabled(true);
+
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FarBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ break;
+
+ case BlurFX::MotionBlur:
+ case BlurFX::FocusBlur:
+ case BlurFX::SmartBlur:
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ break;
+
+ case BlurFX::SoftenerBlur:
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ break;
+ }
+}
+
+void BlurFXTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("blurfx Tool");
+ m_effectType->blockSignals(true);
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+
+ m_effectType->setCurrentItem(config->readNumEntry("EffectType", m_effectType->defaultItem()));
+ m_distanceInput->setValue(config->readNumEntry("DistanceAjustment", m_distanceInput->defaultValue()));
+ m_levelInput->setValue(config->readNumEntry("LevelAjustment", m_levelInput->defaultValue()));
+
+ m_effectType->blockSignals(false);
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+}
+
+void BlurFXTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("blurfx Tool");
+ config->writeEntry("EffectType", m_effectType->currentItem());
+ config->writeEntry("DistanceAjustment", m_distanceInput->value());
+ config->writeEntry("LevelAjustment", m_levelInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void BlurFXTool::slotResetSettings()
+{
+ m_effectType->blockSignals(true);
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+
+ m_effectType->slotReset();
+ m_distanceInput->slotReset();
+ m_levelInput->slotReset();
+
+ m_effectType->blockSignals(false);
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+
+ slotEffectTypeChanged(m_effectType->defaultItem());
+}
+
+void BlurFXTool::slotEffectTypeChanged(int type)
+{
+ m_distanceInput->setEnabled(true);
+ m_distanceLabel->setEnabled(true);
+
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+
+ m_distanceInput->setRange(0, 200, 1);
+ m_distanceInput->setValue(100);
+ m_levelInput->setRange(0, 360, 1);
+ m_levelInput->setValue(45);
+
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ switch (type)
+ {
+ case BlurFX::ZoomBlur:
+ break;
+
+ case BlurFX::RadialBlur:
+ case BlurFX::FrostGlass:
+ m_distanceInput->setRange(0, 10, 1);
+ m_distanceInput->setValue(3);
+ break;
+
+ case BlurFX::FarBlur:
+ m_distanceInput->setRange(0, 20, 1);
+ m_distanceInput->input()->setMaxValue(20);
+ m_distanceInput->setValue(10);
+ break;
+
+ case BlurFX::MotionBlur:
+ case BlurFX::FocusBlur:
+ m_distanceInput->setRange(0, 100, 1);
+ m_distanceInput->setValue(20);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ break;
+
+ case BlurFX::SoftenerBlur:
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ break;
+
+ case BlurFX::ShakeBlur:
+ m_distanceInput->setRange(0, 100, 1);
+ m_distanceInput->setValue(20);
+ break;
+
+ case BlurFX::SmartBlur:
+ m_distanceInput->setRange(0, 20, 1);
+ m_distanceInput->setValue(3);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ m_levelInput->setRange(0, 255, 1);
+ m_levelInput->setValue(128);
+ break;
+
+ case BlurFX::Mosaic:
+ m_distanceInput->setRange(0, 50, 1);
+ m_distanceInput->setValue(3);
+ break;
+ }
+
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void BlurFXTool::prepareEffect()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ DImg image;
+
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FocusBlur:
+ {
+ ImageIface iface(0, 0);
+ image = *iface.getOriginalImg();
+ break;
+ }
+
+ case BlurFX::FarBlur:
+ case BlurFX::MotionBlur:
+ case BlurFX::SoftenerBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::SmartBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ image = m_previewWidget->getOriginalRegionImage();
+ break;
+ }
+
+ int t = m_effectType->currentItem();
+ int d = m_distanceInput->value();
+ int l = m_levelInput->value();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new BlurFX(&image, this, t, d, l)));
+}
+
+void BlurFXTool::prepareFinal()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ int t = m_effectType->currentItem();
+ int d = m_distanceInput->value();
+ int l = m_levelInput->value();
+
+ ImageIface iface(0, 0);
+ setFilter(dynamic_cast<DImgThreadedFilter *>(new BlurFX(iface.getOriginalImg(), this, t, d, l)));
+}
+
+void BlurFXTool::putPreviewData()
+{
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FocusBlur:
+ {
+ TQRect pRect = m_previewWidget->getOriginalImageRegionToRender();
+ DImg destImg = filter()->getTargetImage().copy(pRect);
+ m_previewWidget->setPreviewImage(destImg);
+ break;
+ }
+ case BlurFX::FarBlur:
+ case BlurFX::MotionBlur:
+ case BlurFX::SoftenerBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::SmartBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+ break;
+ }
+}
+
+void BlurFXTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Blur Effects"), filter()->getTargetImage().bits());
+}
+
+} // NameSpace DigikamBlurFXImagesPlugin
diff --git a/src/imageplugins/blurfx/blurfxtool.h b/src/imageplugins/blurfx/blurfxtool.h
new file mode 100644
index 00000000..9726e65d
--- /dev/null
+++ b/src/imageplugins/blurfx/blurfxtool.h
@@ -0,0 +1,93 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef BLURFXTOOL_H
+#define BLURFXTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQLabel;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+class BlurFXTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ BlurFXTool(TQObject *parent);
+ ~BlurFXTool();
+
+private slots:
+
+ void slotEffectTypeChanged(int type);
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQLabel *m_effectTypeLabel;
+ TQLabel *m_distanceLabel;
+ TQLabel *m_levelLabel;
+
+ KDcrawIface::RComboBox *m_effectType;
+
+ KDcrawIface::RIntNumInput *m_distanceInput;
+ KDcrawIface::RIntNumInput *m_levelInput;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamBlurFXImagesPlugin
+
+#endif /* BLURFXTOOL_H */
diff --git a/src/imageplugins/blurfx/digikamimageplugin_blurfx.desktop b/src/imageplugins/blurfx/digikamimageplugin_blurfx.desktop
new file mode 100644
index 00000000..e7968a80
--- /dev/null
+++ b/src/imageplugins/blurfx/digikamimageplugin_blurfx.desktop
@@ -0,0 +1,49 @@
+[Desktop Entry]
+Name=ImagePlugin_BlurFX
+Name[bg]=Приставка за снимки - Ефекти за замъгляване
+Name[el]=ΠρόσθετοΕικόνας_ΕφέΘολώματος
+Name[fi]=Sumennus
+Name[hr]=Zamućenje
+Name[it]=PluginImmagini_EffettiDiSfocatura
+Name[nl]=Afbeeldingsplugin_Vervaageffect
+Name[sr]=Ефекти замућења
+Name[sr@Latn]=Efekti zamućenja
+Name[sv]=Insticksprogram för oskärpeeffekt
+Name[tr]=ResimEklentisi_Bulanıklaştır
+Name[xx]=xxImagePlugin_BlurFXxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Blur special effects plugin for digiKam
+Comment[bg]=Приставка на digiKam с ефекти за замъгляване на снимки
+Comment[ca]=Connector pel digiKam d'efectes especials de difuminat
+Comment[da]=Digikam plugin med specialeffekter for udviskning
+Comment[de]=digiKam-Modul zum Erzeugen von speziellen Unschärfe-Effekten
+Comment[el]=Πρόσθετο ειδικών εφέ θολώματος για το digiKam
+Comment[es]=Plugin para digiKam con efectos especiales de difusión
+Comment[et]=DigiKami spetsiaalsete hägustamisefektide plugin
+Comment[fa]=وصلۀ جلوه‌های ویژۀ محو برای digiKam
+Comment[fi]=Sumennustehosteita
+Comment[gl]=Un plugin de digiKam para efeitos especiais de borrón
+Comment[hr]=digiKam dodatak za efekt zamućenja
+Comment[is]=Íforrit fyrir digiKam sem mýkir eða afskerpir myndir
+Comment[it]=Plugin degli effetti speciali di sfocatura per digiKam
+Comment[ja]=digiKam ぼかし特殊効果プラグイン
+Comment[nds]=digiKam-Moduul för't Opstellen vun Weekteek-Effekten
+Comment[nl]=Digikam-plugin voor vervaageffect
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਬਲੱਰ (ਧੁੰਧਲਾਪਨ) ਖਾਸ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka specjalnych efektów rozmycia do programu digiKam
+Comment[pt]=Um 'plugin' do digiKam para efeitos especiais de borrão
+Comment[pt_BR]=Plugin de efeitos especiais de desfocalização
+Comment[ru]=Модуль специальных эффектов размытия для digiKam
+Comment[sk]=digiKam plugin pre špeciálne efekty rozmazania
+Comment[sr]=Прикључак ефеката замућења за digiKam
+Comment[sr@Latn]=Priključak efekata zamućenja za digiKam
+Comment[sv]=Digikam insticksprogram med specialeffekter för oskärpa
+Comment[tr]=digiKam için bulanıklaştırma eklentisi
+Comment[uk]=Втулок спеціальних ефектів розмивання для digiKam
+Comment[vi]=Phần bổ sung hiệu ứng che mờ cho digiKam
+Comment[xx]=xxBlur special effects plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_blurfx
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/blurfx/digikamimageplugin_blurfx_ui.rc b/src/imageplugins/blurfx/digikamimageplugin_blurfx_ui.rc
new file mode 100644
index 00000000..085b4c68
--- /dev/null
+++ b/src/imageplugins/blurfx/digikamimageplugin_blurfx_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_blurfx" >
+
+ <MenuBar>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_blurfx" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_blurfx" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/blurfx/imageeffect_blurfx.cpp b/src/imageplugins/blurfx/imageeffect_blurfx.cpp
new file mode 100644
index 00000000..62bcd525
--- /dev/null
+++ b/src/imageplugins/blurfx/imageeffect_blurfx.cpp
@@ -0,0 +1,388 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqslider.h>
+#include <tqimage.h>
+#include <tqcombobox.h>
+#include <tqdatetime.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <knuminput.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "blurfx.h"
+#include "imageeffect_blurfx.h"
+#include "imageeffect_blurfx.moc"
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+ImageEffect_BlurFX::ImageEffect_BlurFX(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Apply Blurring Special Effect to Photograph"),
+ "blurfx", false, false, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Blur Effects"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to apply blurring special effect "
+ "to an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2005, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Pieter Z. Voloshyn", I18N_NOOP("Blurring algorithms"),
+ "pieter dot voloshyn at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 5, 1, 0, spacingHint());
+
+ m_effectTypeLabel = new TQLabel(i18n("Type:"), gboxSettings);
+
+ m_effectType = new TQComboBox( false, gboxSettings );
+ m_effectType->insertItem( i18n("Zoom Blur") );
+ m_effectType->insertItem( i18n("Radial Blur") );
+ m_effectType->insertItem( i18n("Far Blur") );
+ m_effectType->insertItem( i18n("Motion Blur") );
+ m_effectType->insertItem( i18n("Softener Blur") );
+ m_effectType->insertItem( i18n("Skake Blur") );
+ m_effectType->insertItem( i18n("Focus Blur") );
+ m_effectType->insertItem( i18n("Smart Blur") );
+ m_effectType->insertItem( i18n("Frost Glass") );
+ m_effectType->insertItem( i18n("Mosaic") );
+ TQWhatsThis::add( m_effectType, i18n("<p>Select the blurring effect to apply to the image.<p>"
+ "<b>Zoom Blur</b>: blurs the image along radial lines starting from "
+ "a specified center point. This simulates the blur of a zooming camera.<p>"
+ "<b>Radial Blur</b>: blurs the image by rotating the pixels around "
+ "the specified center point. This simulates the blur of a rotating camera.<p>"
+ "<b>Far Blur</b>: blurs the image by using far pixels. This simulates the blur "
+ "of an unfocalized camera lens.<p>"
+ "<b>Motion Blur</b>: blurs the image by moving the pixels horizontally. "
+ "This simulates the blur of a linear moving camera.<p>"
+ "<b>Softener Blur</b>: blurs the image softly in dark tones and hardly in light "
+ "tones. This gives images a dreamy and glossy soft focus effect. It's ideal "
+ "for creating romantic portraits, glamour photographs, or giving images a warm "
+ "and subtle glow.<p>"
+ "<b>Skake Blur</b>: blurs the image by skaking randomly the pixels. "
+ "This simulates the blur of a random moving camera.<p>"
+ "<b>Focus Blur</b>: blurs the image corners to reproduce the astigmatism distortion "
+ "of a lens.<p>"
+ "<b>Smart Blur</b>: finds the edges of color in your image and blurs them without "
+ "muddying the rest of the image.<p>"
+ "<b>Frost Glass</b>: blurs the image by randomly disperse light coming through "
+ "a frosted glass.<p>"
+ "<b>Mosaic</b>: divides the photograph into rectangular cells and then "
+ "recreates it by filling those cells with average pixel value."));
+ gridSettings->addMultiCellWidget(m_effectTypeLabel, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_effectType, 1, 1, 0, 1);
+
+ m_distanceLabel = new TQLabel(i18n("Distance:"), gboxSettings);
+ m_distanceInput = new KIntNumInput(gboxSettings);
+ m_distanceInput->setRange(0, 100, 1, true);
+ TQWhatsThis::add( m_distanceInput, i18n("<p>Set here the blur distance in pixels."));
+
+ gridSettings->addMultiCellWidget(m_distanceLabel, 2, 2, 0, 1);
+ gridSettings->addMultiCellWidget(m_distanceInput, 3, 3, 0, 1);
+
+ m_levelLabel = new TQLabel(i18n("Level:"), gboxSettings);
+ m_levelInput = new KIntNumInput(gboxSettings);
+ m_levelInput->setRange(0, 360, 1, true);
+ TQWhatsThis::add( m_levelInput, i18n("<p>This value controls the level to use with the current effect."));
+
+ gridSettings->addMultiCellWidget(m_levelLabel, 4, 4, 0, 1);
+ gridSettings->addMultiCellWidget(m_levelInput, 5, 5, 0, 1);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_effectType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffectTypeChanged(int)));
+
+ connect(m_distanceInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_levelInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_BlurFX::~ImageEffect_BlurFX()
+{
+}
+
+void ImageEffect_BlurFX::renderingFinished(void)
+{
+
+ m_effectTypeLabel->setEnabled(true);
+ m_effectType->setEnabled(true);
+ m_distanceInput->setEnabled(true);
+ m_distanceLabel->setEnabled(true);
+
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FarBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ break;
+
+ case BlurFX::MotionBlur:
+ case BlurFX::FocusBlur:
+ case BlurFX::SmartBlur:
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ break;
+
+ case BlurFX::SoftenerBlur:
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ break;
+ }
+}
+
+void ImageEffect_BlurFX::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("blurfx Tool Dialog");
+ m_effectType->blockSignals(true);
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+ m_effectType->setCurrentItem(config->readNumEntry("EffectType", BlurFX::ZoomBlur));
+ m_distanceInput->setValue(config->readNumEntry("DistanceAjustment", 3));
+ m_levelInput->setValue(config->readNumEntry("LevelAjustment", 128));
+ m_effectType->blockSignals(false);
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+}
+
+void ImageEffect_BlurFX::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("blurfx Tool Dialog");
+ config->writeEntry("EffectType", m_effectType->currentItem());
+ config->writeEntry("DistanceAjustment", m_distanceInput->value());
+ config->writeEntry("LevelAjustment", m_levelInput->value());
+ config->sync();
+}
+
+void ImageEffect_BlurFX::resetValues()
+{
+ m_effectType->setCurrentItem(BlurFX::ZoomBlur);
+ slotEffectTypeChanged(BlurFX::ZoomBlur);
+}
+
+void ImageEffect_BlurFX::slotEffectTypeChanged(int type)
+{
+ m_distanceInput->setEnabled(true);
+ m_distanceLabel->setEnabled(true);
+
+ m_distanceInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+ m_distanceInput->setRange(0, 200, 1, true);
+ m_distanceInput->setValue(100);
+ m_levelInput->setRange(0, 360, 1, true);
+ m_levelInput->setValue(45);
+
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ switch (type)
+ {
+ case BlurFX::ZoomBlur:
+ break;
+
+ case BlurFX::RadialBlur:
+ case BlurFX::FrostGlass:
+ m_distanceInput->setRange(0, 10, 1, true);
+ m_distanceInput->setValue(3);
+ break;
+
+ case BlurFX::FarBlur:
+ m_distanceInput->setRange(0, 20, 1, true);
+ m_distanceInput->setMaxValue(20);
+ m_distanceInput->setValue(10);
+ break;
+
+ case BlurFX::MotionBlur:
+ case BlurFX::FocusBlur:
+ m_distanceInput->setRange(0, 100, 1, true);
+ m_distanceInput->setValue(20);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ break;
+
+ case BlurFX::SoftenerBlur:
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ break;
+
+ case BlurFX::ShakeBlur:
+ m_distanceInput->setRange(0, 100, 1, true);
+ m_distanceInput->setValue(20);
+ break;
+
+ case BlurFX::SmartBlur:
+ m_distanceInput->setRange(0, 20, 1, true);
+ m_distanceInput->setValue(3);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ m_levelInput->setRange(0, 255, 1, true);
+ m_levelInput->setValue(128);
+ break;
+
+ case BlurFX::Mosaic:
+ m_distanceInput->setRange(0, 50, 1, true);
+ m_distanceInput->setValue(3);
+ break;
+ }
+
+ m_distanceInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ImageEffect_BlurFX::prepareEffect()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ Digikam::DImg image;
+
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FocusBlur:
+ {
+ Digikam::ImageIface iface(0, 0);
+ image = *iface.getOriginalImg();
+ break;
+ }
+
+ case BlurFX::FarBlur:
+ case BlurFX::MotionBlur:
+ case BlurFX::SoftenerBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::SmartBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ image = m_imagePreviewWidget->getOriginalRegionImage();
+ break;
+ }
+
+ int t = m_effectType->currentItem();
+ int d = m_distanceInput->value();
+ int l = m_levelInput->value();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new BlurFX(&image, this, t, d, l));
+}
+
+void ImageEffect_BlurFX::prepareFinal()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_distanceInput->setEnabled(false);
+ m_distanceLabel->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+
+ int t = m_effectType->currentItem();
+ int d = m_distanceInput->value();
+ int l = m_levelInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new BlurFX(iface.getOriginalImg(), this, t, d, l));
+}
+
+void ImageEffect_BlurFX::putPreviewData(void)
+{
+ switch (m_effectType->currentItem())
+ {
+ case BlurFX::ZoomBlur:
+ case BlurFX::RadialBlur:
+ case BlurFX::FocusBlur:
+ {
+ TQRect pRect = m_imagePreviewWidget->getOriginalImageRegionToRender();
+ Digikam::DImg destImg = m_threadedFilter->getTargetImage().copy(pRect);
+ m_imagePreviewWidget->setPreviewImage(destImg);
+ break;
+ }
+ case BlurFX::FarBlur:
+ case BlurFX::MotionBlur:
+ case BlurFX::SoftenerBlur:
+ case BlurFX::ShakeBlur:
+ case BlurFX::SmartBlur:
+ case BlurFX::FrostGlass:
+ case BlurFX::Mosaic:
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+ break;
+ }
+}
+
+void ImageEffect_BlurFX::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Blur Effects"),
+ m_threadedFilter->getTargetImage().bits());
+}
+
+} // NameSpace DigikamBlurFXImagesPlugin
+
diff --git a/src/imageplugins/blurfx/imageeffect_blurfx.h b/src/imageplugins/blurfx/imageeffect_blurfx.h
new file mode 100644
index 00000000..e2517d4f
--- /dev/null
+++ b/src/imageplugins/blurfx/imageeffect_blurfx.h
@@ -0,0 +1,80 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_BLURFX_H
+#define IMAGEEFFECT_BLURFX_H
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+class TQComboBox;
+class TQLabel;
+
+class KIntNumInput;
+
+namespace DigikamBlurFXImagesPlugin
+{
+
+class ImageEffect_BlurFX : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_BlurFX(TQWidget *parent);
+ ~ImageEffect_BlurFX();
+
+private slots:
+
+ void slotEffectTypeChanged(int type);
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQComboBox *m_effectType;
+
+ TQLabel *m_effectTypeLabel;
+ TQLabel *m_distanceLabel;
+ TQLabel *m_levelLabel;
+
+ KIntNumInput *m_distanceInput;
+ KIntNumInput *m_levelInput;
+};
+
+} // NameSpace DigikamBlurFXImagesPlugin
+
+#endif /* IMAGEEFFECT_BLURFX_H */
diff --git a/src/imageplugins/blurfx/imageplugin_blurfx.cpp b/src/imageplugins/blurfx/imageplugin_blurfx.cpp
new file mode 100644
index 00000000..3bbd05e0
--- /dev/null
+++ b/src/imageplugins/blurfx/imageplugin_blurfx.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "blurfxtool.h"
+#include "imageplugin_blurfx.h"
+#include "imageplugin_blurfx.moc"
+
+using namespace DigikamBlurFXImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_blurfx,
+ KGenericFactory<ImagePlugin_BlurFX>("digikamimageplugin_blurfx"));
+
+ImagePlugin_BlurFX::ImagePlugin_BlurFX(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_BlurFX")
+{
+ m_blurfxAction = new TDEAction(i18n("Blur Effects..."), "blurfx", 0,
+ this, TQ_SLOT(slotBlurFX()),
+ actionCollection(), "imageplugin_blurfx");
+
+ setXMLFile( "digikamimageplugin_blurfx_ui.rc" );
+
+ DDebug() << "ImagePlugin_BlurFX plugin loaded" << endl;
+}
+
+ImagePlugin_BlurFX::~ImagePlugin_BlurFX()
+{
+}
+
+void ImagePlugin_BlurFX::setEnabledActions(bool enable)
+{
+ m_blurfxAction->setEnabled(enable);
+}
+
+void ImagePlugin_BlurFX::slotBlurFX()
+{
+ BlurFXTool *tool = new BlurFXTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/blurfx/imageplugin_blurfx.h b/src/imageplugins/blurfx/imageplugin_blurfx.h
new file mode 100644
index 00000000..13df6534
--- /dev/null
+++ b/src/imageplugins/blurfx/imageplugin_blurfx.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-09
+ * Description : a plugin to apply Blur FX to images
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_BLURFX_H
+#define IMAGEPLUGIN_BLURFX_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_BlurFX : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_BlurFX(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_BlurFX();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotBlurFX();
+
+private:
+
+ TDEAction *m_blurfxAction;
+};
+
+#endif /* IMAGEPLUGIN_BLURFX_H */
diff --git a/src/imageplugins/border/Makefile.am b/src/imageplugins/border/Makefile.am
new file mode 100644
index 00000000..385acfab
--- /dev/null
+++ b/src/imageplugins/border/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+SUBDIRS = patterns
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_border_la_SOURCES = imageplugin_border.cpp \
+ bordertool.cpp border.cpp
+
+digikamimageplugin_border_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_border_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_border.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_border.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_border_ui.rc
diff --git a/src/imageplugins/border/border.cpp b/src/imageplugins/border/border.cpp
new file mode 100644
index 00000000..00726f58
--- /dev/null
+++ b/src/imageplugins/border/border.cpp
@@ -0,0 +1,393 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : border threaded image filter.
+ *
+ * Copyright 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqpoint.h>
+#include <tqregion.h>
+#include <tqpointarray.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "ddebug.h"
+#include "border.h"
+
+namespace DigikamBorderImagesPlugin
+{
+
+Border::Border(Digikam::DImg *image, TQObject *parent, int orgWidth, int orgHeight,
+ TQString borderPath, int borderType, float borderPercent,
+ Digikam::DColor solidColor,
+ Digikam::DColor niepceBorderColor,
+ Digikam::DColor niepceLineColor,
+ Digikam::DColor bevelUpperLeftColor,
+ Digikam::DColor bevelLowerRightColor,
+ Digikam::DColor decorativeFirstColor,
+ Digikam::DColor decorativeSecondColor)
+ : Digikam::DImgThreadedFilter(image, parent, "Border")
+{
+ m_orgWidth = orgWidth;
+ m_orgHeight = orgHeight;
+ m_orgRatio = (float)m_orgWidth / (float)m_orgHeight;
+ m_borderType = borderType;
+ m_borderPath = borderPath;
+ int size = (image->width() > image->height()) ? image->height() : image->width();
+ m_borderMainWidth = (int)(size * borderPercent);
+ m_border2ndWidth = (int)(size * 0.005);
+
+ // Clamp internal border with to 1 pixel to be visible with small image.
+ if (m_border2ndWidth < 1) m_border2ndWidth = 1;
+
+ m_solidColor = solidColor;
+ m_niepceBorderColor = niepceBorderColor;
+ m_niepceLineColor = niepceLineColor;
+ m_bevelUpperLeftColor = bevelUpperLeftColor;
+ m_bevelLowerRightColor = bevelLowerRightColor;
+ m_decorativeFirstColor = decorativeFirstColor;
+ m_decorativeSecondColor = decorativeSecondColor;
+
+ m_preserveAspectRatio = true;
+
+ initFilter();
+}
+
+Border::Border(Digikam::DImg *orgImage, TQObject *parent, int orgWidth, int orgHeight,
+ TQString borderPath, int borderType,
+ int borderWidth1, int borderWidth2, int borderWidth3, int borderWidth4,
+ Digikam::DColor solidColor,
+ Digikam::DColor niepceBorderColor,
+ Digikam::DColor niepceLineColor,
+ Digikam::DColor bevelUpperLeftColor,
+ Digikam::DColor bevelLowerRightColor,
+ Digikam::DColor decorativeFirstColor,
+ Digikam::DColor decorativeSecondColor)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "Border")
+{
+ m_orgWidth = orgWidth;
+ m_orgHeight = orgHeight;
+
+ m_borderType = borderType;
+ m_borderWidth1 = borderWidth1;
+ m_borderWidth2 = borderWidth2;
+ m_borderWidth3 = borderWidth3;
+ m_borderWidth4 = borderWidth4;
+
+ m_solidColor = solidColor;
+ m_niepceBorderColor = niepceBorderColor;
+ m_niepceLineColor = niepceLineColor;
+ m_bevelUpperLeftColor = bevelUpperLeftColor;
+ m_bevelLowerRightColor = bevelLowerRightColor;
+ m_decorativeFirstColor = decorativeFirstColor;
+ m_decorativeSecondColor = decorativeSecondColor;
+
+ m_borderPath = borderPath;
+
+ m_preserveAspectRatio = false;
+
+ initFilter();
+}
+
+void Border::filterImage(void)
+{
+ switch (m_borderType)
+ {
+ case SolidBorder:
+ if (m_preserveAspectRatio)
+ solid(m_orgImage, m_destImage, m_solidColor, m_borderMainWidth);
+ else
+ solid2(m_orgImage, m_destImage, m_solidColor, m_borderWidth1);
+ break;
+
+ case NiepceBorder:
+ if (m_preserveAspectRatio)
+ niepce(m_orgImage, m_destImage, m_niepceBorderColor, m_borderMainWidth,
+ m_niepceLineColor, m_border2ndWidth);
+ else
+ niepce2(m_orgImage, m_destImage, m_niepceBorderColor, m_borderWidth1,
+ m_niepceLineColor, m_borderWidth4);
+ break;
+
+ case BeveledBorder:
+ if (m_preserveAspectRatio)
+ bevel(m_orgImage, m_destImage, m_bevelUpperLeftColor,
+ m_bevelLowerRightColor, m_borderMainWidth);
+ else
+ bevel2(m_orgImage, m_destImage, m_bevelUpperLeftColor,
+ m_bevelLowerRightColor, m_borderWidth1);
+ break;
+
+ case PineBorder:
+ case WoodBorder:
+ case PaperBorder:
+ case ParqueBorder:
+ case IceBorder:
+ case LeafBorder:
+ case MarbleBorder:
+ case RainBorder:
+ case CratersBorder:
+ case DriedBorder:
+ case PinkBorder:
+ case StoneBorder:
+ case ChalkBorder:
+ case GraniteBorder:
+ case RockBorder:
+ case WallBorder:
+ if (m_preserveAspectRatio)
+ pattern(m_orgImage, m_destImage, m_borderMainWidth,
+ m_decorativeFirstColor, m_decorativeSecondColor,
+ m_border2ndWidth, m_border2ndWidth);
+ else
+ pattern2(m_orgImage, m_destImage, m_borderWidth1,
+ m_decorativeFirstColor, m_decorativeSecondColor,
+ m_borderWidth2, m_borderWidth2);
+ break;
+ }
+}
+
+// -- Methods to preserve aspect ratio of image ------------------------------------------
+
+void Border::solid(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth)
+{
+ if (m_orgWidth > m_orgHeight)
+ {
+ int height = src.height() + borderWidth*2;
+ dest = Digikam::DImg((int)(height*m_orgRatio), height, src.sixteenBit(), src.hasAlpha());
+ dest.fill(fg);
+ dest.bitBltImage(&src, (dest.width()-src.width())/2, borderWidth);
+ }
+ else
+ {
+ int width = src.width() + borderWidth*2;
+ dest = Digikam::DImg(width, (int)(width/m_orgRatio), src.sixteenBit(), src.hasAlpha());
+ dest.fill(fg);
+ dest.bitBltImage(&src, borderWidth, (dest.height()-src.height())/2);
+ }
+}
+
+void Border::niepce(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg,
+ int borderWidth, const Digikam::DColor &bg, int lineWidth)
+{
+ Digikam::DImg tmp;
+ solid(src, tmp, bg, lineWidth);
+ solid(tmp, dest, fg, borderWidth);
+}
+
+void Border::bevel(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &topColor,
+ const Digikam::DColor &btmColor, int borderWidth)
+{
+ int width, height;
+
+ if (m_orgWidth > m_orgHeight)
+ {
+ height = src.height() + borderWidth*2;
+ width = (int)(height*m_orgRatio);
+ }
+ else
+ {
+ width = src.width() + borderWidth*2;
+ height = (int)(width/m_orgRatio);
+ }
+
+ dest = Digikam::DImg(width, height, src.sixteenBit(), src.hasAlpha());
+ dest.fill(topColor);
+
+ TQPointArray btTriangle(3);
+ btTriangle.setPoint(0, width, 0);
+ btTriangle.setPoint(1, 0, height);
+ btTriangle.setPoint(2, width, height);
+ TQRegion btRegion(btTriangle);
+
+ for(int x=0 ; x < width ; x++)
+ {
+ for(int y=0 ; y < height ; y++)
+ {
+ if (btRegion.contains(TQPoint(x, y)))
+ dest.setPixelColor(x, y, btmColor);
+ }
+ }
+
+ if (m_orgWidth > m_orgHeight)
+ {
+ dest.bitBltImage(&src, (dest.width()-src.width())/2, borderWidth);
+ }
+ else
+ {
+ dest.bitBltImage(&src, borderWidth, (dest.height()-src.height())/2);
+ }
+}
+
+void Border::pattern(Digikam::DImg &src, Digikam::DImg &dest, int borderWidth,
+ const Digikam::DColor &firstColor, const Digikam::DColor &secondColor,
+ int firstWidth, int secondWidth)
+{
+ // Original image with the first solid border around.
+ Digikam::DImg tmp;
+ solid(src, tmp, firstColor, firstWidth);
+
+ // Border tiled image using pattern with second solid border around.
+ int width, height;
+
+ if (m_orgWidth > m_orgHeight)
+ {
+ height = tmp.height() + borderWidth*2;
+ width = (int)(height*m_orgRatio);
+ }
+ else
+ {
+ width = tmp.width() + borderWidth*2;
+ height = (int)(width/m_orgRatio);
+ }
+
+ Digikam::DImg tmp2(width, height, tmp.sixteenBit(), tmp.hasAlpha());
+ DDebug() << "Border File:" << m_borderPath << endl;
+ Digikam::DImg border(m_borderPath);
+ if ( border.isNull() )
+ return;
+
+ border.convertToDepthOfImage(&tmp2);
+
+ for (int x = 0 ; x < width ; x+=border.width())
+ for (int y = 0 ; y < height ; y+=border.height())
+ tmp2.bitBltImage(&border, x, y);
+
+ solid(tmp2, dest, secondColor, secondWidth);
+
+ // Merge both images to one.
+ if (m_orgWidth > m_orgHeight)
+ {
+ dest.bitBltImage(&tmp, (dest.width()-tmp.width())/2, borderWidth);
+ }
+ else
+ {
+ dest.bitBltImage(&tmp, borderWidth, (dest.height()-tmp.height())/2);
+ }
+}
+
+// -- Methods to not-preserve aspect ratio of image ------------------------------------------
+
+
+void Border::solid2(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth)
+{
+ dest = Digikam::DImg(src.width() + borderWidth*2, src.height() + borderWidth*2,
+ src.sixteenBit(), src.hasAlpha());
+ dest.fill(fg);
+ dest.bitBltImage(&src, borderWidth, borderWidth);
+}
+
+void Border::niepce2(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth,
+ const Digikam::DColor &bg, int lineWidth)
+{
+ Digikam::DImg tmp;
+ solid2(src, tmp, bg, lineWidth);
+ solid2(tmp, dest, fg, borderWidth);
+}
+
+void Border::bevel2(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &topColor,
+ const Digikam::DColor &btmColor, int borderWidth)
+{
+ int x, y;
+ int wc;
+
+ dest = Digikam::DImg(src.width() + borderWidth*2,
+ src.height() + borderWidth*2,
+ src.sixteenBit(), src.hasAlpha());
+
+ // top
+
+ for(y=0, wc = (int)dest.width()-1; y < borderWidth; ++y, --wc)
+ {
+ for(x=0; x < wc; ++x)
+ dest.setPixelColor(x, y, topColor);
+
+ for(;x < (int)dest.width(); ++x)
+ dest.setPixelColor(x, y, btmColor);
+ }
+
+ // left and right
+
+ for(; y < (int)dest.height()-borderWidth; ++y)
+ {
+ for(x=0; x < borderWidth; ++x)
+ dest.setPixelColor(x, y, topColor);
+
+ for(x = (int)dest.width()-1; x > (int)dest.width()-borderWidth-1; --x)
+ dest.setPixelColor(x, y, btmColor);
+ }
+
+ // bottom
+
+ for(wc = borderWidth; y < (int)dest.height(); ++y, --wc)
+ {
+ for(x=0; x < wc; ++x)
+ dest.setPixelColor(x, y, topColor);
+
+ for(; x < (int)dest.width(); ++x)
+ dest.setPixelColor(x, y, btmColor);
+ }
+
+ dest.bitBltImage(&src, borderWidth, borderWidth);
+}
+
+void Border::pattern2(Digikam::DImg &src, Digikam::DImg &dest, int borderWidth,
+ const Digikam::DColor &firstColor, const Digikam::DColor &secondColor,
+ int firstWidth, int secondWidth)
+{
+ // Border tile.
+
+ int w = m_orgWidth + borderWidth*2;
+ int h = m_orgHeight + borderWidth*2;
+
+ DDebug() << "Border File:" << m_borderPath << endl;
+ Digikam::DImg border(m_borderPath);
+ if ( border.isNull() )
+ return;
+
+ Digikam::DImg borderImg(w, h, src.sixteenBit(), src.hasAlpha());
+ border.convertToDepthOfImage(&borderImg);
+
+ for (int x = 0 ; x < w ; x+=border.width())
+ for (int y = 0 ; y < h ; y+=border.height())
+ borderImg.bitBltImage(&border, x, y);
+
+ // First line around the pattern tile.
+ Digikam::DImg tmp = borderImg.smoothScale(src.width() + borderWidth*2,
+ src.height() + borderWidth*2 );
+
+ solid2(tmp, dest, firstColor, firstWidth);
+
+ // Second line around original image.
+ tmp.reset();
+ solid2(src, tmp, secondColor, secondWidth);
+
+ // Copy original image.
+ dest.bitBltImage(&tmp, borderWidth, borderWidth);
+}
+
+} // NameSpace DigikamBorderImagesPlugin
diff --git a/src/imageplugins/border/border.h b/src/imageplugins/border/border.h
new file mode 100644
index 00000000..b213e27a
--- /dev/null
+++ b/src/imageplugins/border/border.h
@@ -0,0 +1,151 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : border threaded image filter.
+ *
+ * Copyright 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef BORDER_H
+#define BORDER_H
+
+// TQt includes.
+
+#include <tqstring.h>
+#include <tqcolor.h>
+#include <tqimage.h>
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamBorderImagesPlugin
+{
+
+class Border : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ enum BorderTypes
+ {
+ SolidBorder=0,
+ NiepceBorder,
+ BeveledBorder,
+ PineBorder,
+ WoodBorder,
+ PaperBorder,
+ ParqueBorder,
+ IceBorder,
+ LeafBorder,
+ MarbleBorder,
+ RainBorder,
+ CratersBorder,
+ DriedBorder,
+ PinkBorder,
+ StoneBorder,
+ ChalkBorder,
+ GraniteBorder,
+ RockBorder,
+ WallBorder
+ };
+
+public:
+
+ /** Constructor using settings to preserve aspect ratio of image. */
+ Border(Digikam::DImg *orgImage, TQObject *parent=0, int orgWidth=0, int orgHeight=0,
+ TQString borderPath=TQString(), int borderType=SolidBorder, float borderPercent=0.1,
+ Digikam::DColor solidColor = Digikam::DColor(),
+ Digikam::DColor niepceBorderColor = Digikam::DColor(),
+ Digikam::DColor niepceLineColor = Digikam::DColor(),
+ Digikam::DColor bevelUpperLeftColor = Digikam::DColor(),
+ Digikam::DColor bevelLowerRightColor = Digikam::DColor(),
+ Digikam::DColor decorativeFirstColor = Digikam::DColor(),
+ Digikam::DColor decorativeSecondColor = Digikam::DColor());
+
+ /** Constructor using settings to not-preserve aspect ratio of image. */
+ Border(Digikam::DImg *orgImage, TQObject *parent=0, int orgWidth=0, int orgHeight=0,
+ TQString borderPath=TQString(), int borderType=SolidBorder,
+ int borderWidth1=100, int borderWidth2=20, int borderWidth3=20, int borderWidth4=10,
+ Digikam::DColor solidColor = Digikam::DColor(),
+ Digikam::DColor niepceBorderColor = Digikam::DColor(),
+ Digikam::DColor niepceLineColor = Digikam::DColor(),
+ Digikam::DColor bevelUpperLeftColor = Digikam::DColor(),
+ Digikam::DColor bevelLowerRightColor = Digikam::DColor(),
+ Digikam::DColor decorativeFirstColor = Digikam::DColor(),
+ Digikam::DColor decorativeSecondColor = Digikam::DColor());
+
+ ~Border(){};
+
+private:
+
+ virtual void filterImage(void);
+
+
+ /** Methods to preserve aspect ratio of image. */
+ void solid(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth);
+ void niepce(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth,
+ const Digikam::DColor &bg, int lineWidth);
+ void bevel(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &topColor,
+ const Digikam::DColor &btmColor, int borderWidth);
+ void pattern(Digikam::DImg &src, Digikam::DImg &dest, int borderWidth, const Digikam::DColor &firstColor,
+ const Digikam::DColor &secondColor, int firstWidth, int secondWidth);
+
+ /** Methods to not-preserve aspect ratio of image. */
+ void solid2(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth);
+ void niepce2(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &fg, int borderWidth,
+ const Digikam::DColor &bg, int lineWidth);
+ void bevel2(Digikam::DImg &src, Digikam::DImg &dest, const Digikam::DColor &topColor,
+ const Digikam::DColor &btmColor, int borderWidth);
+ void pattern2(Digikam::DImg &src, Digikam::DImg &dest, int borderWidth, const Digikam::DColor &firstColor,
+ const Digikam::DColor &secondColor, int firstWidth, int secondWidth);
+
+private:
+
+ bool m_preserveAspectRatio;
+
+ int m_orgWidth;
+ int m_orgHeight;
+
+ int m_borderType;
+
+ int m_borderWidth1;
+ int m_borderWidth2;
+ int m_borderWidth3;
+ int m_borderWidth4;
+
+ int m_borderMainWidth;
+ int m_border2ndWidth;
+
+ float m_orgRatio;
+
+ TQString m_borderPath;
+
+ Digikam::DColor m_solidColor;
+ Digikam::DColor m_niepceBorderColor;
+ Digikam::DColor m_niepceLineColor;
+ Digikam::DColor m_bevelUpperLeftColor;
+ Digikam::DColor m_bevelLowerRightColor;
+ Digikam::DColor m_decorativeFirstColor;
+ Digikam::DColor m_decorativeSecondColor;
+};
+
+} // NameSpace DigikamBorderImagesPlugin
+
+#endif /* BORDER_H */
diff --git a/src/imageplugins/border/bordertool.cpp b/src/imageplugins/border/bordertool.cpp
new file mode 100644
index 00000000..160f5b0a
--- /dev/null
+++ b/src/imageplugins/border/bordertool.cpp
@@ -0,0 +1,668 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-20
+ * Description : a digiKam image plugin to add a border
+ * around an image.
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kcolorbutton.h>
+#include <tdeconfig.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kseparator.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "editortoolsettings.h"
+#include "border.h"
+#include "bordertool.h"
+#include "bordertool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamBorderImagesPlugin
+{
+
+BorderTool::BorderTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("border");
+ setToolName(i18n("Add Border"));
+ setToolIcon(SmallIcon("bordertool"));
+
+ m_previewWidget = new ImageWidget("bordertool Tool", 0, TQString(),
+ false, ImageGuideWidget::HVGuideMode, false);
+
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 11, 2);
+
+ TQLabel *label1 = new TQLabel(i18n("Type:"), m_gboxSettings->plainPage());
+
+ m_borderType = new RComboBox(m_gboxSettings->plainPage());
+ m_borderType->insertItem( i18n("Solid") );
+ // Niepce is Real name. This is the first guy in the world to have built a camera.
+ m_borderType->insertItem( "Niepce" );
+ m_borderType->insertItem( i18n("Beveled") );
+ m_borderType->insertItem( i18n("Decorative Pine") );
+ m_borderType->insertItem( i18n("Decorative Wood") );
+ m_borderType->insertItem( i18n("Decorative Paper") );
+ m_borderType->insertItem( i18n("Decorative Parquet") );
+ m_borderType->insertItem( i18n("Decorative Ice") );
+ m_borderType->insertItem( i18n("Decorative Leaf") );
+ m_borderType->insertItem( i18n("Decorative Marble") );
+ m_borderType->insertItem( i18n("Decorative Rain") );
+ m_borderType->insertItem( i18n("Decorative Craters") );
+ m_borderType->insertItem( i18n("Decorative Dried") );
+ m_borderType->insertItem( i18n("Decorative Pink") );
+ m_borderType->insertItem( i18n("Decorative Stone") );
+ m_borderType->insertItem( i18n("Decorative Chalk") );
+ m_borderType->insertItem( i18n("Decorative Granite") );
+ m_borderType->insertItem( i18n("Decorative Rock") );
+ m_borderType->insertItem( i18n("Decorative Wall") );
+ m_borderType->setDefaultItem(Border::SolidBorder);
+ TQWhatsThis::add( m_borderType, i18n("<p>Select the border type to add around the image."));
+
+ KSeparator *line1 = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ // -------------------------------------------------------------------
+
+ m_preserveAspectRatio = new TQCheckBox(m_gboxSettings->plainPage());
+ m_preserveAspectRatio->setText(i18n("Preserve Aspect Ratio"));
+ TQWhatsThis::add(m_preserveAspectRatio, i18n("Enable this option if you want to preserve the aspect "
+ "ratio of the image. If enabled, the border width will be "
+ "in percent of the image size, else the border width will "
+ "in pixels."));
+
+ m_labelBorderPercent = new TQLabel(i18n("Width (%):"), m_gboxSettings->plainPage());
+ m_borderPercent = new RIntNumInput(m_gboxSettings->plainPage());
+ m_borderPercent->setRange(1, 50, 1);
+ m_borderPercent->setDefaultValue(10);
+ TQWhatsThis::add(m_borderPercent, i18n("<p>Set here the border width in percent of the image size."));
+
+ m_labelBorderWidth = new TQLabel(i18n("Width (pixels):"), m_gboxSettings->plainPage());
+ m_borderWidth = new RIntNumInput(m_gboxSettings->plainPage());
+ m_borderWidth->setDefaultValue(100);
+ TQWhatsThis::add(m_borderWidth, i18n("<p>Set here the border width in pixels to add around the image."));
+
+ ImageIface iface(0, 0);
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+
+ if (w > h)
+ m_borderWidth->setRange(1, h/2, 1);
+ else
+ m_borderWidth->setRange(1, w/2, 1);
+
+ KSeparator *line2 = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ // -------------------------------------------------------------------
+
+ m_labelForeground = new TQLabel(m_gboxSettings->plainPage());
+ m_firstColorButton = new KColorButton( TQColor( 192, 192, 192 ), m_gboxSettings->plainPage() );
+ m_labelBackground = new TQLabel(m_gboxSettings->plainPage());
+ m_secondColorButton = new KColorButton( TQColor( 128, 128, 128 ), m_gboxSettings->plainPage() );
+
+ // -------------------------------------------------------------------
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 2);
+ grid->addMultiCellWidget(m_borderType, 1, 1, 0, 2);
+ grid->addMultiCellWidget(line1, 2, 2, 0, 2);
+ grid->addMultiCellWidget(m_preserveAspectRatio, 3, 3, 0, 2);
+ grid->addMultiCellWidget(m_labelBorderPercent, 4, 4, 0, 2);
+ grid->addMultiCellWidget(m_borderPercent, 5, 5, 0, 2);
+ grid->addMultiCellWidget(m_labelBorderWidth, 6, 6, 0, 2);
+ grid->addMultiCellWidget(m_borderWidth, 7, 7, 0, 2);
+ grid->addMultiCellWidget(line2, 8, 8, 0, 2);
+ grid->addMultiCellWidget(m_labelForeground, 9, 9, 0, 0);
+ grid->addMultiCellWidget(m_firstColorButton, 9, 9, 1, 2);
+ grid->addMultiCellWidget(m_labelBackground, 10, 10, 0, 0);
+ grid->addMultiCellWidget(m_secondColorButton, 10, 10, 1, 2);
+ grid->setRowStretch(11, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_preserveAspectRatio, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotPreserveAspectRatioToggled(bool)));
+
+ connect(m_borderType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotBorderTypeChanged(int)));
+
+ connect(m_borderPercent, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_borderWidth, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_firstColorButton, TQ_SIGNAL(changed(const TQColor &)),
+ this, TQ_SLOT(slotColorForegroundChanged(const TQColor &)));
+
+ connect(m_secondColorButton, TQ_SIGNAL(changed(const TQColor &)),
+ this, TQ_SLOT(slotColorBackgroundChanged(const TQColor &)));
+}
+
+BorderTool::~BorderTool()
+{
+}
+
+void BorderTool::readSettings()
+{
+ m_borderType->blockSignals(true);
+ m_borderPercent->blockSignals(true);
+ m_borderWidth->blockSignals(true);
+ m_firstColorButton->blockSignals(true);
+ m_secondColorButton->blockSignals(true);
+ m_preserveAspectRatio->blockSignals(true);
+
+ TDEConfig *config = kapp->config();
+ config->setGroup("border Tool");
+
+ m_borderType->setCurrentItem(config->readNumEntry("Border Type", m_borderType->defaultItem()));
+ m_borderPercent->setValue(config->readNumEntry("Border Percent", m_borderPercent->defaultValue()));
+ m_borderWidth->setValue(config->readNumEntry("Border Width", m_borderWidth->defaultValue()));
+ m_preserveAspectRatio->setChecked(config->readBoolEntry("Preserve Aspect Ratio", true));
+
+ TQColor black(0, 0, 0);
+ TQColor white(255, 255, 255);
+ TQColor gray1(192, 192, 192);
+ TQColor gray2(128, 128, 128);
+
+ m_solidColor = config->readColorEntry("Solid Color", &black);
+ m_niepceBorderColor = config->readColorEntry("Niepce Border Color", &white);
+ m_niepceLineColor = config->readColorEntry("Niepce Line Color", &black);
+ m_bevelUpperLeftColor = config->readColorEntry("Bevel Upper Left Color", &gray1);
+ m_bevelLowerRightColor = config->readColorEntry("Bevel Lower Right Color", &gray2);
+ m_decorativeFirstColor = config->readColorEntry("Decorative First Color", &black);
+ m_decorativeSecondColor = config->readColorEntry("Decorative Second Color", &black);
+
+ m_borderType->blockSignals(false);
+ m_borderPercent->blockSignals(false);
+ m_borderWidth->blockSignals(false);
+ m_firstColorButton->blockSignals(false);
+ m_secondColorButton->blockSignals(false);
+ m_preserveAspectRatio->blockSignals(false);
+
+ slotBorderTypeChanged(m_borderType->currentItem());
+}
+
+void BorderTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("border Tool");
+
+ config->writeEntry("Border Type", m_borderType->currentItem());
+ config->writeEntry("Border Percent", m_borderPercent->value());
+ config->writeEntry("Border Width", m_borderWidth->value());
+ config->writeEntry("Preserve Aspect Ratio", m_preserveAspectRatio->isChecked());
+
+ config->writeEntry("Solid Color", m_solidColor);
+ config->writeEntry("Niepce Border Color", m_niepceBorderColor);
+ config->writeEntry("Niepce Line Color", m_niepceLineColor);
+ config->writeEntry("Bevel Upper Left Color", m_bevelUpperLeftColor);
+ config->writeEntry("Bevel Lower Right Color", m_bevelLowerRightColor);
+ config->writeEntry("Decorative First Color", m_decorativeFirstColor);
+ config->writeEntry("Decorative Second Color", m_decorativeSecondColor);
+
+ m_previewWidget->writeSettings();
+
+ config->sync();
+}
+
+void BorderTool::slotResetSettings()
+{
+ m_borderType->blockSignals(true);
+ m_borderPercent->blockSignals(true);
+ m_borderWidth->blockSignals(true);
+ m_firstColorButton->blockSignals(true);
+ m_secondColorButton->blockSignals(true);
+ m_preserveAspectRatio->blockSignals(true);
+
+ m_borderType->slotReset();
+ m_borderPercent->slotReset();
+ m_borderWidth->slotReset();
+ m_preserveAspectRatio->setChecked(true);
+
+ m_solidColor = TQColor(0, 0, 0);
+ m_niepceBorderColor = TQColor(255, 255, 255);
+ m_niepceLineColor = TQColor(0, 0, 0);
+ m_bevelUpperLeftColor = TQColor(192, 192, 192);
+ m_bevelLowerRightColor = TQColor(128, 128, 128);
+ m_decorativeFirstColor = TQColor(0, 0, 0);
+ m_decorativeSecondColor = TQColor(0, 0, 0);
+
+ m_borderType->blockSignals(false);
+ m_borderPercent->blockSignals(false);
+ m_borderWidth->blockSignals(false);
+ m_firstColorButton->blockSignals(false);
+ m_secondColorButton->blockSignals(false);
+ m_preserveAspectRatio->blockSignals(false);
+
+ slotBorderTypeChanged(Border::SolidBorder);
+}
+
+void BorderTool::renderingFinished()
+{
+ m_preserveAspectRatio->setEnabled(true);
+ m_borderType->setEnabled(true);
+ m_borderPercent->setEnabled(true);
+ m_borderWidth->setEnabled(true);
+ m_firstColorButton->setEnabled(true);
+ m_secondColorButton->setEnabled(true);
+ toggleBorderSlider(m_preserveAspectRatio->isChecked());
+}
+
+void BorderTool::slotColorForegroundChanged(const TQColor &color)
+{
+ switch (m_borderType->currentItem())
+ {
+ case Border::SolidBorder:
+ m_solidColor = color;
+ break;
+
+ case Border::NiepceBorder:
+ m_niepceBorderColor = color;
+ break;
+
+ case Border::BeveledBorder:
+ m_bevelUpperLeftColor = color;
+ break;
+
+ case Border::PineBorder:
+ case Border::WoodBorder:
+ case Border::PaperBorder:
+ case Border::ParqueBorder:
+ case Border::IceBorder:
+ case Border::LeafBorder:
+ case Border::MarbleBorder:
+ case Border::RainBorder:
+ case Border::CratersBorder:
+ case Border::DriedBorder:
+ case Border::PinkBorder:
+ case Border::StoneBorder:
+ case Border::ChalkBorder:
+ case Border::GraniteBorder:
+ case Border::RockBorder:
+ case Border::WallBorder:
+ m_decorativeFirstColor = color;
+ break;
+ }
+
+ slotEffect();
+}
+
+void BorderTool::slotColorBackgroundChanged(const TQColor &color)
+{
+ switch (m_borderType->currentItem())
+ {
+ case Border::SolidBorder:
+ m_solidColor = color;
+ break;
+
+ case Border::NiepceBorder:
+ m_niepceLineColor = color;
+ break;
+
+ case Border::BeveledBorder:
+ m_bevelLowerRightColor = color;
+ break;
+
+ case Border::PineBorder:
+ case Border::WoodBorder:
+ case Border::PaperBorder:
+ case Border::ParqueBorder:
+ case Border::IceBorder:
+ case Border::LeafBorder:
+ case Border::MarbleBorder:
+ case Border::RainBorder:
+ case Border::CratersBorder:
+ case Border::DriedBorder:
+ case Border::PinkBorder:
+ case Border::StoneBorder:
+ case Border::ChalkBorder:
+ case Border::GraniteBorder:
+ case Border::RockBorder:
+ case Border::WallBorder:
+ m_decorativeSecondColor = color;
+ break;
+ }
+
+ slotEffect();
+}
+
+void BorderTool::slotBorderTypeChanged(int borderType)
+{
+ m_labelForeground->setText(i18n("First:"));
+ m_labelBackground->setText(i18n("Second:"));
+ TQWhatsThis::add( m_firstColorButton, i18n("<p>Set here the foreground color of the border."));
+ TQWhatsThis::add( m_secondColorButton, i18n("<p>Set here the Background color of the border."));
+ m_firstColorButton->setEnabled(true);
+ m_secondColorButton->setEnabled(true);
+ m_labelForeground->setEnabled(true);
+ m_labelBackground->setEnabled(true);
+ m_borderPercent->setEnabled(true);
+
+ switch (borderType)
+ {
+ case Border::SolidBorder:
+ m_firstColorButton->setColor( m_solidColor );
+ m_secondColorButton->setEnabled(false);
+ m_labelBackground->setEnabled(false);
+ break;
+
+ case Border::NiepceBorder:
+ TQWhatsThis::add( m_firstColorButton, i18n("<p>Set here the color of the main border."));
+ TQWhatsThis::add( m_secondColorButton, i18n("<p>Set here the color of the line."));
+ m_firstColorButton->setColor( m_niepceBorderColor );
+ m_secondColorButton->setColor( m_niepceLineColor );
+ break;
+
+ case Border::BeveledBorder:
+ TQWhatsThis::add( m_firstColorButton, i18n("<p>Set here the color of the upper left area."));
+ TQWhatsThis::add( m_secondColorButton, i18n("<p>Set here the color of the lower right area."));
+ m_firstColorButton->setColor( m_bevelUpperLeftColor );
+ m_secondColorButton->setColor( m_bevelLowerRightColor );
+ break;
+
+ case Border::PineBorder:
+ case Border::WoodBorder:
+ case Border::PaperBorder:
+ case Border::ParqueBorder:
+ case Border::IceBorder:
+ case Border::LeafBorder:
+ case Border::MarbleBorder:
+ case Border::RainBorder:
+ case Border::CratersBorder:
+ case Border::DriedBorder:
+ case Border::PinkBorder:
+ case Border::StoneBorder:
+ case Border::ChalkBorder:
+ case Border::GraniteBorder:
+ case Border::RockBorder:
+ case Border::WallBorder:
+ TQWhatsThis::add( m_firstColorButton, i18n("<p>Set here the color of the first line."));
+ TQWhatsThis::add( m_secondColorButton, i18n("<p>Set here the color of the second line."));
+ m_firstColorButton->setColor( m_decorativeFirstColor );
+ m_secondColorButton->setColor( m_decorativeSecondColor );
+ break;
+ }
+
+ slotEffect();
+}
+
+void BorderTool::prepareEffect()
+{
+ m_borderType->setEnabled(false);
+ m_borderPercent->setEnabled(false);
+ m_borderWidth->setEnabled(false);
+ m_firstColorButton->setEnabled(false);
+ m_secondColorButton->setEnabled(false);
+ m_preserveAspectRatio->setEnabled(false);
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ int orgWidth = iface->originalWidth();
+ int orgHeight = iface->originalHeight();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sixteenBit = iface->previewSixteenBit();
+ uchar *data = iface->getPreviewImage();
+ DImg previewImage(w, h, sixteenBit,
+ iface->previewHasAlpha(), data);
+ delete [] data;
+
+ int borderType = m_borderType->currentItem();
+ float ratio = (float)w/(float)orgWidth;
+ int borderWidth = (int)((float)m_borderWidth->value()*ratio);
+ TQString border = getBorderPath( m_borderType->currentItem() );
+
+ if (m_preserveAspectRatio->isChecked())
+ {
+ setFilter(dynamic_cast<DImgThreadedFilter*>(
+ new Border(&previewImage, this, orgWidth, orgHeight,
+ border, borderType, m_borderPercent->value()/100.0,
+ DColor(m_solidColor, sixteenBit),
+ DColor(m_niepceBorderColor, sixteenBit),
+ DColor(m_niepceLineColor, sixteenBit),
+ DColor(m_bevelUpperLeftColor, sixteenBit),
+ DColor(m_bevelLowerRightColor, sixteenBit),
+ DColor(m_decorativeFirstColor, sixteenBit),
+ DColor(m_decorativeSecondColor, sixteenBit))));
+ }
+ else
+ {
+ setFilter(dynamic_cast<DImgThreadedFilter*>(
+ new Border(&previewImage, this, orgWidth, orgHeight,
+ border, borderType, borderWidth,
+ (int)(20.0*ratio), (int)(20.0*ratio), 3,
+ DColor(m_solidColor, sixteenBit),
+ DColor(m_niepceBorderColor, sixteenBit),
+ DColor(m_niepceLineColor, sixteenBit),
+ DColor(m_bevelUpperLeftColor, sixteenBit),
+ DColor(m_bevelLowerRightColor, sixteenBit),
+ DColor(m_decorativeFirstColor, sixteenBit),
+ DColor(m_decorativeSecondColor, sixteenBit))));
+ }
+}
+
+void BorderTool::prepareFinal()
+{
+ m_borderType->setEnabled(false);
+ m_borderPercent->setEnabled(false);
+ m_borderWidth->setEnabled(false);
+ m_firstColorButton->setEnabled(false);
+ m_secondColorButton->setEnabled(false);
+
+ int borderType = m_borderType->currentItem();
+ int borderWidth = m_borderWidth->value();
+ float borderRatio = m_borderPercent->value()/100.0;
+ TQString border = getBorderPath( m_borderType->currentItem() );
+
+ ImageIface iface(0, 0);
+ int orgWidth = iface.originalWidth();
+ int orgHeight = iface.originalHeight();
+ bool sixteenBit = iface.previewSixteenBit();
+ uchar *data = iface.getOriginalImage();
+ DImg orgImage(orgWidth, orgHeight, sixteenBit,
+ iface.originalHasAlpha(), data);
+ delete [] data;
+
+ if (m_preserveAspectRatio->isChecked())
+ {
+ setFilter(dynamic_cast<DImgThreadedFilter*>(
+ new Border(&orgImage, this, orgWidth, orgHeight,
+ border, borderType, borderRatio,
+ DColor(m_solidColor, sixteenBit),
+ DColor(m_niepceBorderColor, sixteenBit),
+ DColor(m_niepceLineColor, sixteenBit),
+ DColor(m_bevelUpperLeftColor, sixteenBit),
+ DColor(m_bevelLowerRightColor, sixteenBit),
+ DColor(m_decorativeFirstColor, sixteenBit),
+ DColor(m_decorativeSecondColor, sixteenBit))));
+ }
+ else
+ {
+ setFilter(dynamic_cast<DImgThreadedFilter*>(
+ new Border(&orgImage, this, orgWidth, orgHeight,
+ border, borderType, borderWidth, 15, 15, 10,
+ DColor(m_solidColor, sixteenBit),
+ DColor(m_niepceBorderColor, sixteenBit),
+ DColor(m_niepceLineColor, sixteenBit),
+ DColor(m_bevelUpperLeftColor, sixteenBit),
+ DColor(m_bevelLowerRightColor, sixteenBit),
+ DColor(m_decorativeFirstColor, sixteenBit),
+ DColor(m_decorativeSecondColor, sixteenBit))));
+ }
+}
+
+void BorderTool::putPreviewData()
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+
+ DImg imTemp = filter()->getTargetImage().smoothScale(w, h, TQSize::ScaleMin);
+ DImg imDest( w, h, filter()->getTargetImage().sixteenBit(),
+ filter()->getTargetImage().hasAlpha() );
+
+ imDest.fill( DColor(m_previewWidget->paletteBackgroundColor().rgb(),
+ filter()->getTargetImage().sixteenBit()) );
+
+ imDest.bitBltImage(&imTemp, (w-imTemp.width())/2, (h-imTemp.height())/2);
+
+ iface->putPreviewImage(imDest.bits());
+ m_previewWidget->updatePreview();
+}
+
+void BorderTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+
+ DImg targetImage = filter()->getTargetImage();
+ iface.putOriginalImage(i18n("Add Border"),
+ targetImage.bits(),
+ targetImage.width(), targetImage.height());
+}
+
+TQString BorderTool::getBorderPath(int border)
+{
+ TQString pattern;
+
+ switch (border)
+ {
+ case Border::PineBorder:
+ pattern = "pine-pattern";
+ break;
+
+ case Border::WoodBorder:
+ pattern = "wood-pattern";
+ break;
+
+ case Border::PaperBorder:
+ pattern = "paper-pattern";
+ break;
+
+ case Border::ParqueBorder:
+ pattern = "parque-pattern";
+ break;
+
+ case Border::IceBorder:
+ pattern = "ice-pattern";
+ break;
+
+ case Border::LeafBorder:
+ pattern = "leaf-pattern";
+ break;
+
+ case Border::MarbleBorder:
+ pattern = "marble-pattern";
+ break;
+
+ case Border::RainBorder:
+ pattern = "rain-pattern";
+ break;
+
+ case Border::CratersBorder:
+ pattern = "craters-pattern";
+ break;
+
+ case Border::DriedBorder:
+ pattern = "dried-pattern";
+ break;
+
+ case Border::PinkBorder:
+ pattern = "pink-pattern";
+ break;
+
+ case Border::StoneBorder:
+ pattern = "stone-pattern";
+ break;
+
+ case Border::ChalkBorder:
+ pattern = "chalk-pattern";
+ break;
+
+ case Border::GraniteBorder:
+ pattern = "granit-pattern";
+ break;
+
+ case Border::RockBorder:
+ pattern = "rock-pattern";
+ break;
+
+ case Border::WallBorder:
+ pattern = "wall-pattern";
+ break;
+
+ default:
+ return TQString();
+ }
+
+ TDEGlobal::dirs()->addResourceType(pattern.ascii(), TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ return (TDEGlobal::dirs()->findResourceDir(pattern.ascii(), pattern + ".png") + pattern + ".png" );
+}
+
+void BorderTool::slotPreserveAspectRatioToggled(bool b)
+{
+ toggleBorderSlider(b);
+ slotTimer();
+}
+
+void BorderTool::toggleBorderSlider(bool b)
+{
+ m_borderPercent->setEnabled(b);
+ m_borderWidth->setEnabled(!b);
+ m_labelBorderPercent->setEnabled(b);
+ m_labelBorderWidth->setEnabled(!b);
+}
+
+} // NameSpace DigikamBorderImagesPlugin
diff --git a/src/imageplugins/border/bordertool.h b/src/imageplugins/border/bordertool.h
new file mode 100644
index 00000000..a8ec5ccf
--- /dev/null
+++ b/src/imageplugins/border/bordertool.h
@@ -0,0 +1,123 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-20
+ * Description : a digiKam image plugin to add a border
+ * around an image.
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef BORDERTOOL_H
+#define BORDERTOOL_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQLabel;
+class TQCheckBox;
+class TQColor;
+
+class KColorButton;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImageWidget;
+}
+
+namespace DigikamBorderImagesPlugin
+{
+
+class BorderTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ BorderTool(TQObject *parent);
+ ~BorderTool();
+
+private:
+
+ TQString getBorderPath(int border);
+
+private slots:
+
+ void slotPreserveAspectRatioToggled(bool);
+ void slotBorderTypeChanged(int borderType);
+ void slotColorForegroundChanged(const TQColor &color);
+ void slotColorBackgroundChanged(const TQColor &color);
+ void slotResetSettings();
+
+private:
+
+ void writeSettings();
+ void readSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+ void toggleBorderSlider(bool b);
+
+private:
+
+ TQLabel *m_labelBorderPercent;
+ TQLabel *m_labelBorderWidth;
+ TQLabel *m_labelForeground;
+ TQLabel *m_labelBackground;
+
+ TQCheckBox *m_preserveAspectRatio;
+
+ TQColor m_solidColor;
+ TQColor m_niepceBorderColor;
+ TQColor m_niepceLineColor;
+ TQColor m_bevelUpperLeftColor;
+ TQColor m_bevelLowerRightColor;
+ TQColor m_decorativeFirstColor;
+ TQColor m_decorativeSecondColor;
+
+ KDcrawIface::RComboBox *m_borderType;
+
+ KDcrawIface::RIntNumInput *m_borderPercent;
+ KDcrawIface::RIntNumInput *m_borderWidth;
+
+ KColorButton *m_firstColorButton;
+ KColorButton *m_secondColorButton;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamBorderImagesPlugin
+
+#endif /* BORDERTOOL_H */
diff --git a/src/imageplugins/border/digikamimageplugin_border.desktop b/src/imageplugins/border/digikamimageplugin_border.desktop
new file mode 100644
index 00000000..45f32a7e
--- /dev/null
+++ b/src/imageplugins/border/digikamimageplugin_border.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Name=ImagePlugin_Border
+Name[bg]=Приставка за снимки - �амки
+Name[da]=Billedplugin_Indramning
+Name[el]=ΠρόσθετοΕικόνας_Περίγραμμα
+Name[fi]=Reunus
+Name[hr]=Obrub
+Name[it]=PluginImmagini_Bordo
+Name[nl]=Afbeeldingsplugin_Rand
+Name[sr]=Оквир
+Name[sr@Latn]=Okvir
+Name[sv]=Insticksprogram för bildkanter
+Name[tr]=ResimEklentisi_Çerçeve
+Name[xx]=xxImagePlugin_Borderxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Add border to image plugin for digiKam
+Comment[bg]=Приставка на digiKam за добавяне на рамки на снимки
+Comment[ca]=Connector pel digiKam per afegir una vora a la imatge
+Comment[da]=Plugin til indramning af billeder i Digikam
+Comment[de]=digiKam-Modul zum Hinzufügen eines Rahmens zu einem Bild
+Comment[el]=Πρόσθετο προσθήκης περιγράμματος σε εικόνα για το digiKam
+Comment[es]=Plugin de digiKam para añadir bordes a la imagen
+Comment[et]=DigiKami pildile raami lisamise plugin
+Comment[fa]=افزودن لبه به وصلۀ تصویر برای digiKam
+Comment[fi]=Lisää kuvaan reunuksen
+Comment[gl]=Un plugin de digiKam para engadir un contorno á imaxe
+Comment[hr]=digiKam dodatak za dodavanje obruba
+Comment[is]=Íforrit fyrir digiKam sem gerir ramma á myndir
+Comment[it]=Plugin per l'aggiunta di bordi a un'immagire per digiKam
+Comment[ja]=digikam 画像装飾プラグイン
+Comment[nds]=digiKam-Moduul för't Tofögen vun Ränners rund en Bild
+Comment[nl]=Digikam-plugin voor het toevoegen van randen
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਹਾਸ਼ੀਆ ਜੋੜਨ ਲਈ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam dodająca ramkę do obrazu
+Comment[pt]=Um 'plugin' do digiKam para adicionar um contorno à imagem
+Comment[pt_BR]=Plugin de adicionar borda na imagem
+Comment[ru]=Модуль digiKam наложения рамки на изображение
+Comment[sk]=digiKam plugin pridávajúci okraj obrázku
+Comment[sr]=Прикључак за digiKam који додаје оквир на слику
+Comment[sr@Latn]=Priključak za digiKam koji dodaje okvir na sliku
+Comment[sv]=Digikam insticksprogram för tillägg av kanter
+Comment[tr]=digiKam için resme çerçeve eklenme eklentisi
+Comment[uk]=Втулок digiKam для додавання рамки навколо зображення
+Comment[vi]=Phần bổ sung thêm viền trên ảnh cho digiKam
+Comment[xx]=xxAdd border to image plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_border
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/border/digikamimageplugin_border_ui.rc b/src/imageplugins/border/digikamimageplugin_border_ui.rc
new file mode 100644
index 00000000..8cce0581
--- /dev/null
+++ b/src/imageplugins/border/digikamimageplugin_border_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="6" name="digikamimageplugin_border" >
+
+ <MenuBar>
+
+ <Menu name="Decorate" ><text>&amp;Decorate</text>
+ <Action name="imageplugin_border" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action name="imageplugin_border" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/border/imageeffect_border.cpp b/src/imageplugins/border/imageeffect_border.cpp
new file mode 100644
index 00000000..9f3dd6c3
--- /dev/null
+++ b/src/imageplugins/border/imageeffect_border.cpp
@@ -0,0 +1,667 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-20
+ * Description : a digiKam image plugin to add a border
+ * around an image.
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqcombobox.h>
+#include <tqcheckbox.h>
+
+// KDE includes.
+
+#include <kseparator.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdeconfig.h>
+#include <knuminput.h>
+#include <kcolorbutton.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "border.h"
+#include "imageeffect_border.h"
+#include "imageeffect_border.moc"
+
+namespace DigikamBorderImagesPlugin
+{
+
+ImageEffect_Border::ImageEffect_Border(TQWidget* parent)
+ : Digikam::ImageGuideDlg(parent, i18n("Add Border Around Photograph"),
+ "border", false, false, false,
+ Digikam::ImageGuideWidget::HVGuideMode)
+{
+ // No need Abort button action.
+ showButton(User1, false);
+
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Add Border"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to add a border around an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2005, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings, 10, 2, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Type:"), gboxSettings);
+
+ m_borderType = new TQComboBox( false, gboxSettings );
+ m_borderType->insertItem( i18n("Solid") );
+ // Niepce is Real name. This is the first guy in the world to have built a camera.
+ m_borderType->insertItem( "Niepce" );
+ m_borderType->insertItem( i18n("Beveled") );
+ m_borderType->insertItem( i18n("Decorative Pine") );
+ m_borderType->insertItem( i18n("Decorative Wood") );
+ m_borderType->insertItem( i18n("Decorative Paper") );
+ m_borderType->insertItem( i18n("Decorative Parquet") );
+ m_borderType->insertItem( i18n("Decorative Ice") );
+ m_borderType->insertItem( i18n("Decorative Leaf") );
+ m_borderType->insertItem( i18n("Decorative Marble") );
+ m_borderType->insertItem( i18n("Decorative Rain") );
+ m_borderType->insertItem( i18n("Decorative Craters") );
+ m_borderType->insertItem( i18n("Decorative Dried") );
+ m_borderType->insertItem( i18n("Decorative Pink") );
+ m_borderType->insertItem( i18n("Decorative Stone") );
+ m_borderType->insertItem( i18n("Decorative Chalk") );
+ m_borderType->insertItem( i18n("Decorative Granite") );
+ m_borderType->insertItem( i18n("Decorative Rock") );
+ m_borderType->insertItem( i18n("Decorative Wall") );
+ TQWhatsThis::add( m_borderType, i18n("<p>Select the border type to add around the image."));
+
+ KSeparator *line1 = new KSeparator(Horizontal, gboxSettings);
+
+ // -------------------------------------------------------------------
+
+ m_preserveAspectRatio = new TQCheckBox(gboxSettings);
+ m_preserveAspectRatio->setText(i18n("Preserve Aspect Ratio"));
+ TQWhatsThis::add(m_preserveAspectRatio, i18n("Enable this option if you want to preserve the aspect "
+ "ratio of the image. If enabled, the border width will be "
+ "in percent of the image size, else the border width will "
+ "in pixels."));
+
+ m_labelBorderPercent = new TQLabel(i18n("Width (%):"), gboxSettings);
+ m_borderPercent = new KIntNumInput(gboxSettings);
+ m_borderPercent->setRange(1, 50, 1, true);
+ TQWhatsThis::add(m_borderPercent, i18n("<p>Set here the border width in percent of the image size."));
+
+ m_labelBorderWidth = new TQLabel(i18n("Width (pixels):"), gboxSettings);
+ m_borderWidth = new KIntNumInput(gboxSettings);
+ TQWhatsThis::add(m_borderWidth, i18n("<p>Set here the border width in pixels to add around the image."));
+
+ Digikam::ImageIface iface(0, 0);
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+
+ if (w > h)
+ m_borderWidth->setRange(1, h/2, 1, true);
+ else
+ m_borderWidth->setRange(1, w/2, 1, true);
+
+ KSeparator *line2 = new KSeparator(Horizontal, gboxSettings);
+
+ // -------------------------------------------------------------------
+
+ m_labelForeground = new TQLabel(gboxSettings);
+ m_firstColorButton = new KColorButton( TQColor( 192, 192, 192 ), gboxSettings );
+ m_labelBackground = new TQLabel(gboxSettings);
+ m_secondColorButton = new KColorButton( TQColor( 128, 128, 128 ), gboxSettings );
+
+ // -------------------------------------------------------------------
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 2);
+ gridSettings->addMultiCellWidget(m_borderType, 1, 1, 0, 2);
+ gridSettings->addMultiCellWidget(line1, 2, 2, 0, 2);
+ gridSettings->addMultiCellWidget(m_preserveAspectRatio, 3, 3, 0, 2);
+ gridSettings->addMultiCellWidget(m_labelBorderPercent, 4, 4, 0, 2);
+ gridSettings->addMultiCellWidget(m_borderPercent, 5, 5, 0, 2);
+ gridSettings->addMultiCellWidget(m_labelBorderWidth, 6, 6, 0, 2);
+ gridSettings->addMultiCellWidget(m_borderWidth, 7, 7, 0, 2);
+ gridSettings->addMultiCellWidget(line2, 8, 8, 0, 2);
+ gridSettings->addMultiCellWidget(m_labelForeground, 9, 9, 0, 0);
+ gridSettings->addMultiCellWidget(m_firstColorButton, 9, 9, 1, 2);
+ gridSettings->addMultiCellWidget(m_labelBackground, 10, 10, 0, 0);
+ gridSettings->addMultiCellWidget(m_secondColorButton, 10, 10, 1, 2);
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_preserveAspectRatio, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotPreserveAspectRatioToggled(bool)));
+
+ connect(m_borderType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotBorderTypeChanged(int)));
+
+ connect(m_borderPercent, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_borderWidth, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_firstColorButton, TQ_SIGNAL(changed(const TQColor &)),
+ this, TQ_SLOT(slotColorForegroundChanged(const TQColor &)));
+
+ connect(m_secondColorButton, TQ_SIGNAL(changed(const TQColor &)),
+ this, TQ_SLOT(slotColorBackgroundChanged(const TQColor &)));
+}
+
+ImageEffect_Border::~ImageEffect_Border()
+{
+}
+
+void ImageEffect_Border::readUserSettings(void)
+{
+ m_borderType->blockSignals(true);
+ m_borderPercent->blockSignals(true);
+ m_borderWidth->blockSignals(true);
+ m_firstColorButton->blockSignals(true);
+ m_secondColorButton->blockSignals(true);
+ m_preserveAspectRatio->blockSignals(true);
+
+ TDEConfig *config = kapp->config();
+ config->setGroup("border Tool Dialog");
+
+ m_borderType->setCurrentItem(config->readNumEntry("Border Type", Border::SolidBorder));
+ m_borderPercent->setValue(config->readNumEntry("Border Percent", 10) );
+ m_borderWidth->setValue(config->readNumEntry("Border Width", 100) );
+ m_preserveAspectRatio->setChecked(config->readBoolEntry("Preserve Aspect Ratio", true) );
+
+ TQColor black(0, 0, 0);
+ TQColor white(255, 255, 255);
+ TQColor gray1(192, 192, 192);
+ TQColor gray2(128, 128, 128);
+
+ m_solidColor = config->readColorEntry("Solid Color", &black);
+ m_niepceBorderColor = config->readColorEntry("Niepce Border Color", &white);
+ m_niepceLineColor = config->readColorEntry("Niepce Line Color", &black);
+ m_bevelUpperLeftColor = config->readColorEntry("Bevel Upper Left Color", &gray1);
+ m_bevelLowerRightColor = config->readColorEntry("Bevel Lower Right Color", &gray2);
+ m_decorativeFirstColor = config->readColorEntry("Decorative First Color", &black);
+ m_decorativeSecondColor = config->readColorEntry("Decorative Second Color", &black);
+
+ m_borderType->blockSignals(false);
+ m_borderPercent->blockSignals(false);
+ m_borderWidth->blockSignals(false);
+ m_firstColorButton->blockSignals(false);
+ m_secondColorButton->blockSignals(false);
+ m_preserveAspectRatio->blockSignals(false);
+
+ slotBorderTypeChanged(m_borderType->currentItem());
+}
+
+void ImageEffect_Border::writeUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("border Tool Dialog");
+
+ config->writeEntry("Border Type", m_borderType->currentItem());
+ config->writeEntry("Border Percent", m_borderPercent->value());
+ config->writeEntry("Border Width", m_borderWidth->value());
+ config->writeEntry("Preserve Aspect Ratio", m_preserveAspectRatio->isChecked());
+
+ config->writeEntry("Solid Color", m_solidColor);
+ config->writeEntry("Niepce Border Color", m_niepceBorderColor);
+ config->writeEntry("Niepce Line Color", m_niepceLineColor);
+ config->writeEntry("Bevel Upper Left Color", m_bevelUpperLeftColor);
+ config->writeEntry("Bevel Lower Right Color", m_bevelLowerRightColor);
+ config->writeEntry("Decorative First Color", m_decorativeFirstColor);
+ config->writeEntry("Decorative Second Color", m_decorativeSecondColor);
+
+ config->sync();
+}
+
+void ImageEffect_Border::resetValues()
+{
+ m_borderType->blockSignals(true);
+ m_borderPercent->blockSignals(true);
+ m_borderWidth->blockSignals(true);
+ m_firstColorButton->blockSignals(true);
+ m_secondColorButton->blockSignals(true);
+ m_preserveAspectRatio->blockSignals(true);
+
+ m_borderType->setCurrentItem(Border::SolidBorder);
+ m_borderPercent->setValue(10);
+ m_borderWidth->setValue(100);
+ m_preserveAspectRatio->setChecked(true);
+
+ m_solidColor = TQColor(0, 0, 0);
+ m_niepceBorderColor = TQColor(255, 255, 255);
+ m_niepceLineColor = TQColor(0, 0, 0);
+ m_bevelUpperLeftColor = TQColor(192, 192, 192);
+ m_bevelLowerRightColor = TQColor(128, 128, 128);
+ m_decorativeFirstColor = TQColor(0, 0, 0);
+ m_decorativeSecondColor = TQColor(0, 0, 0);
+
+ m_borderType->blockSignals(false);
+ m_borderPercent->blockSignals(false);
+ m_borderWidth->blockSignals(false);
+ m_firstColorButton->blockSignals(false);
+ m_secondColorButton->blockSignals(false);
+ m_preserveAspectRatio->blockSignals(false);
+
+ slotBorderTypeChanged(Border::SolidBorder);
+}
+
+void ImageEffect_Border::renderingFinished()
+{
+ m_preserveAspectRatio->setEnabled(true);
+ m_borderType->setEnabled(true);
+ m_borderPercent->setEnabled(true);
+ m_borderWidth->setEnabled(true);
+ m_firstColorButton->setEnabled(true);
+ m_secondColorButton->setEnabled(true);
+ toggleBorderSlider(m_preserveAspectRatio->isChecked());
+}
+
+void ImageEffect_Border::slotColorForegroundChanged(const TQColor &color)
+{
+ switch (m_borderType->currentItem())
+ {
+ case Border::SolidBorder:
+ m_solidColor = color;
+ break;
+
+ case Border::NiepceBorder:
+ m_niepceBorderColor = color;
+ break;
+
+ case Border::BeveledBorder:
+ m_bevelUpperLeftColor = color;
+ break;
+
+ case Border::PineBorder:
+ case Border::WoodBorder:
+ case Border::PaperBorder:
+ case Border::ParqueBorder:
+ case Border::IceBorder:
+ case Border::LeafBorder:
+ case Border::MarbleBorder:
+ case Border::RainBorder:
+ case Border::CratersBorder:
+ case Border::DriedBorder:
+ case Border::PinkBorder:
+ case Border::StoneBorder:
+ case Border::ChalkBorder:
+ case Border::GraniteBorder:
+ case Border::RockBorder:
+ case Border::WallBorder:
+ m_decorativeFirstColor = color;
+ break;
+ }
+
+ slotEffect();
+}
+
+void ImageEffect_Border::slotColorBackgroundChanged(const TQColor &color)
+{
+ switch (m_borderType->currentItem())
+ {
+ case Border::SolidBorder:
+ m_solidColor = color;
+ break;
+
+ case Border::NiepceBorder:
+ m_niepceLineColor = color;
+ break;
+
+ case Border::BeveledBorder:
+ m_bevelLowerRightColor = color;
+ break;
+
+ case Border::PineBorder:
+ case Border::WoodBorder:
+ case Border::PaperBorder:
+ case Border::ParqueBorder:
+ case Border::IceBorder:
+ case Border::LeafBorder:
+ case Border::MarbleBorder:
+ case Border::RainBorder:
+ case Border::CratersBorder:
+ case Border::DriedBorder:
+ case Border::PinkBorder:
+ case Border::StoneBorder:
+ case Border::ChalkBorder:
+ case Border::GraniteBorder:
+ case Border::RockBorder:
+ case Border::WallBorder:
+ m_decorativeSecondColor = color;
+ break;
+ }
+
+ slotEffect();
+}
+
+void ImageEffect_Border::slotBorderTypeChanged(int borderType)
+{
+ m_labelForeground->setText(i18n("First:"));
+ m_labelBackground->setText(i18n("Second:"));
+ TQWhatsThis::add( m_firstColorButton, i18n("<p>Set here the foreground color of the border."));
+ TQWhatsThis::add( m_secondColorButton, i18n("<p>Set here the Background color of the border."));
+ m_firstColorButton->setEnabled(true);
+ m_secondColorButton->setEnabled(true);
+ m_labelForeground->setEnabled(true);
+ m_labelBackground->setEnabled(true);
+ m_borderPercent->setEnabled(true);
+
+ switch (borderType)
+ {
+ case Border::SolidBorder:
+ m_firstColorButton->setColor( m_solidColor );
+ m_secondColorButton->setEnabled(false);
+ m_labelBackground->setEnabled(false);
+ break;
+
+ case Border::NiepceBorder:
+ TQWhatsThis::add( m_firstColorButton, i18n("<p>Set here the color of the main border."));
+ TQWhatsThis::add( m_secondColorButton, i18n("<p>Set here the color of the line."));
+ m_firstColorButton->setColor( m_niepceBorderColor );
+ m_secondColorButton->setColor( m_niepceLineColor );
+ break;
+
+ case Border::BeveledBorder:
+ TQWhatsThis::add( m_firstColorButton, i18n("<p>Set here the color of the upper left area."));
+ TQWhatsThis::add( m_secondColorButton, i18n("<p>Set here the color of the lower right area."));
+ m_firstColorButton->setColor( m_bevelUpperLeftColor );
+ m_secondColorButton->setColor( m_bevelLowerRightColor );
+ break;
+
+ case Border::PineBorder:
+ case Border::WoodBorder:
+ case Border::PaperBorder:
+ case Border::ParqueBorder:
+ case Border::IceBorder:
+ case Border::LeafBorder:
+ case Border::MarbleBorder:
+ case Border::RainBorder:
+ case Border::CratersBorder:
+ case Border::DriedBorder:
+ case Border::PinkBorder:
+ case Border::StoneBorder:
+ case Border::ChalkBorder:
+ case Border::GraniteBorder:
+ case Border::RockBorder:
+ case Border::WallBorder:
+ TQWhatsThis::add( m_firstColorButton, i18n("<p>Set here the color of the first line."));
+ TQWhatsThis::add( m_secondColorButton, i18n("<p>Set here the color of the second line."));
+ m_firstColorButton->setColor( m_decorativeFirstColor );
+ m_secondColorButton->setColor( m_decorativeSecondColor );
+ break;
+ }
+
+ slotEffect();
+}
+
+void ImageEffect_Border::prepareEffect()
+{
+ m_borderType->setEnabled(false);
+ m_borderPercent->setEnabled(false);
+ m_borderWidth->setEnabled(false);
+ m_firstColorButton->setEnabled(false);
+ m_secondColorButton->setEnabled(false);
+ m_preserveAspectRatio->setEnabled(false);
+
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+ int orgWidth = iface->originalWidth();
+ int orgHeight = iface->originalHeight();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sixteenBit = iface->previewSixteenBit();
+ uchar *data = iface->getPreviewImage();
+ Digikam::DImg previewImage(w, h, sixteenBit,
+ iface->previewHasAlpha(), data);
+ delete [] data;
+
+ int borderType = m_borderType->currentItem();
+ float ratio = (float)w/(float)orgWidth;
+ int borderWidth = (int)((float)m_borderWidth->value()*ratio);
+ TQString border = getBorderPath( m_borderType->currentItem() );
+
+ if (m_preserveAspectRatio->isChecked())
+ {
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Border(&previewImage, this, orgWidth, orgHeight,
+ border, borderType, m_borderPercent->value()/100.0,
+ Digikam::DColor(m_solidColor, sixteenBit),
+ Digikam::DColor(m_niepceBorderColor, sixteenBit),
+ Digikam::DColor(m_niepceLineColor, sixteenBit),
+ Digikam::DColor(m_bevelUpperLeftColor, sixteenBit),
+ Digikam::DColor(m_bevelLowerRightColor, sixteenBit),
+ Digikam::DColor(m_decorativeFirstColor, sixteenBit),
+ Digikam::DColor(m_decorativeSecondColor, sixteenBit)) );
+ }
+ else
+ {
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Border(&previewImage, this, orgWidth, orgHeight,
+ border, borderType, borderWidth,
+ (int)(20.0*ratio), (int)(20.0*ratio), 3,
+ Digikam::DColor(m_solidColor, sixteenBit),
+ Digikam::DColor(m_niepceBorderColor, sixteenBit),
+ Digikam::DColor(m_niepceLineColor, sixteenBit),
+ Digikam::DColor(m_bevelUpperLeftColor, sixteenBit),
+ Digikam::DColor(m_bevelLowerRightColor, sixteenBit),
+ Digikam::DColor(m_decorativeFirstColor, sixteenBit),
+ Digikam::DColor(m_decorativeSecondColor, sixteenBit)) );
+ }
+}
+
+void ImageEffect_Border::prepareFinal()
+{
+ m_borderType->setEnabled(false);
+ m_borderPercent->setEnabled(false);
+ m_borderWidth->setEnabled(false);
+ m_firstColorButton->setEnabled(false);
+ m_secondColorButton->setEnabled(false);
+
+ int borderType = m_borderType->currentItem();
+ int borderWidth = m_borderWidth->value();
+ float borderRatio = m_borderPercent->value()/100.0;
+ TQString border = getBorderPath( m_borderType->currentItem() );
+
+ Digikam::ImageIface iface(0, 0);
+ int orgWidth = iface.originalWidth();
+ int orgHeight = iface.originalHeight();
+ bool sixteenBit = iface.previewSixteenBit();
+ uchar *data = iface.getOriginalImage();
+ Digikam::DImg orgImage(orgWidth, orgHeight, sixteenBit,
+ iface.originalHasAlpha(), data);
+ delete [] data;
+
+ if (m_preserveAspectRatio->isChecked())
+ {
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Border(&orgImage, this, orgWidth, orgHeight,
+ border, borderType, borderRatio,
+ Digikam::DColor(m_solidColor, sixteenBit),
+ Digikam::DColor(m_niepceBorderColor, sixteenBit),
+ Digikam::DColor(m_niepceLineColor, sixteenBit),
+ Digikam::DColor(m_bevelUpperLeftColor, sixteenBit),
+ Digikam::DColor(m_bevelLowerRightColor, sixteenBit),
+ Digikam::DColor(m_decorativeFirstColor, sixteenBit),
+ Digikam::DColor(m_decorativeSecondColor, sixteenBit)) );
+ }
+ else
+ {
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Border(&orgImage, this, orgWidth, orgHeight,
+ border, borderType, borderWidth, 15, 15, 10,
+ Digikam::DColor(m_solidColor, sixteenBit),
+ Digikam::DColor(m_niepceBorderColor, sixteenBit),
+ Digikam::DColor(m_niepceLineColor, sixteenBit),
+ Digikam::DColor(m_bevelUpperLeftColor, sixteenBit),
+ Digikam::DColor(m_bevelLowerRightColor, sixteenBit),
+ Digikam::DColor(m_decorativeFirstColor, sixteenBit),
+ Digikam::DColor(m_decorativeSecondColor, sixteenBit)) );
+ }
+}
+
+void ImageEffect_Border::putPreviewData(void)
+{
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+
+ Digikam::DImg imTemp = m_threadedFilter->getTargetImage().smoothScale(w, h, TQSize::ScaleMin);
+ Digikam::DImg imDest( w, h, m_threadedFilter->getTargetImage().sixteenBit(),
+ m_threadedFilter->getTargetImage().hasAlpha() );
+
+ imDest.fill( Digikam::DColor(paletteBackgroundColor().rgb(),
+ m_threadedFilter->getTargetImage().sixteenBit()) );
+
+ imDest.bitBltImage(&imTemp, (w-imTemp.width())/2, (h-imTemp.height())/2);
+
+ iface->putPreviewImage(imDest.bits());
+ m_imagePreviewWidget->updatePreview();
+}
+
+void ImageEffect_Border::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ Digikam::DImg targetImage = m_threadedFilter->getTargetImage();
+ iface.putOriginalImage(i18n("Add Border"),
+ targetImage.bits(),
+ targetImage.width(), targetImage.height());
+}
+
+TQString ImageEffect_Border::getBorderPath(int border)
+{
+ TQString pattern;
+
+ switch (border)
+ {
+ case Border::PineBorder:
+ pattern = "pine-pattern";
+ break;
+
+ case Border::WoodBorder:
+ pattern = "wood-pattern";
+ break;
+
+ case Border::PaperBorder:
+ pattern = "paper-pattern";
+ break;
+
+ case Border::ParqueBorder:
+ pattern = "parque-pattern";
+ break;
+
+ case Border::IceBorder:
+ pattern = "ice-pattern";
+ break;
+
+ case Border::LeafBorder:
+ pattern = "leaf-pattern";
+ break;
+
+ case Border::MarbleBorder:
+ pattern = "marble-pattern";
+ break;
+
+ case Border::RainBorder:
+ pattern = "rain-pattern";
+ break;
+
+ case Border::CratersBorder:
+ pattern = "craters-pattern";
+ break;
+
+ case Border::DriedBorder:
+ pattern = "dried-pattern";
+ break;
+
+ case Border::PinkBorder:
+ pattern = "pink-pattern";
+ break;
+
+ case Border::StoneBorder:
+ pattern = "stone-pattern";
+ break;
+
+ case Border::ChalkBorder:
+ pattern = "chalk-pattern";
+ break;
+
+ case Border::GraniteBorder:
+ pattern = "granit-pattern";
+ break;
+
+ case Border::RockBorder:
+ pattern = "rock-pattern";
+ break;
+
+ case Border::WallBorder:
+ pattern = "wall-pattern";
+ break;
+
+ default:
+ return TQString();
+ }
+
+ TDEGlobal::dirs()->addResourceType(pattern.ascii(), TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ return (TDEGlobal::dirs()->findResourceDir(pattern.ascii(), pattern + ".png") + pattern + ".png" );
+}
+
+void ImageEffect_Border::slotPreserveAspectRatioToggled(bool b)
+{
+ toggleBorderSlider(b);
+ slotTimer();
+}
+
+void ImageEffect_Border::toggleBorderSlider(bool b)
+{
+ m_borderPercent->setEnabled(b);
+ m_borderWidth->setEnabled(!b);
+ m_labelBorderPercent->setEnabled(b);
+ m_labelBorderWidth->setEnabled(!b);
+}
+
+} // NameSpace DigikamBorderImagesPlugin
+
diff --git a/src/imageplugins/border/imageeffect_border.h b/src/imageplugins/border/imageeffect_border.h
new file mode 100644
index 00000000..787a76a0
--- /dev/null
+++ b/src/imageplugins/border/imageeffect_border.h
@@ -0,0 +1,109 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-20
+ * Description : a digiKam image plugin to add a border
+ * around an image.
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_BORDER_H
+#define IMAGEEFFECT_BORDER_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "imageguidedlg.h"
+
+class TQComboBox;
+class TQLabel;
+class TQCheckBox;
+class TQColor;
+
+class KIntNumInput;
+class KColorButton;
+
+namespace DigikamBorderImagesPlugin
+{
+
+class ImageEffect_Border : public Digikam::ImageGuideDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Border(TQWidget *parent);
+ ~ImageEffect_Border();
+
+private:
+
+ TQString getBorderPath(int border);
+
+private slots:
+
+ void slotPreserveAspectRatioToggled(bool);
+ void slotBorderTypeChanged(int borderType);
+ void slotColorForegroundChanged(const TQColor &color);
+ void slotColorBackgroundChanged(const TQColor &color);
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+ void toggleBorderSlider(bool b);
+
+private:
+
+ TQLabel *m_labelBorderPercent;
+ TQLabel *m_labelBorderWidth;
+ TQLabel *m_labelForeground;
+ TQLabel *m_labelBackground;
+
+ TQComboBox *m_borderType;
+
+ TQCheckBox *m_preserveAspectRatio;
+
+ TQColor m_solidColor;
+ TQColor m_niepceBorderColor;
+ TQColor m_niepceLineColor;
+ TQColor m_bevelUpperLeftColor;
+ TQColor m_bevelLowerRightColor;
+ TQColor m_decorativeFirstColor;
+ TQColor m_decorativeSecondColor;
+
+ KIntNumInput *m_borderPercent;
+ KIntNumInput *m_borderWidth;
+
+ KColorButton *m_firstColorButton;
+ KColorButton *m_secondColorButton;
+};
+
+} // NameSpace DigikamBorderImagesPlugin
+
+#endif /* IMAGEEFFECT_BORDER_H */
diff --git a/src/imageplugins/border/imageplugin_border.cpp b/src/imageplugins/border/imageplugin_border.cpp
new file mode 100644
index 00000000..f0c5a236
--- /dev/null
+++ b/src/imageplugins/border/imageplugin_border.cpp
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-20
+ * Description : a digiKam image plugin to add a border
+ * around an image.
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "bordertool.h"
+#include "imageplugin_border.h"
+#include "imageplugin_border.moc"
+
+using namespace DigikamBorderImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_border,
+ KGenericFactory<ImagePlugin_Border>("digikamimageplugin_border"));
+
+ImagePlugin_Border::ImagePlugin_Border(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_Border")
+{
+ m_borderAction = new TDEAction(i18n("Add Border..."), "bordertool",
+ 0,
+ this, TQ_SLOT(slotBorder()),
+ actionCollection(), "imageplugin_border");
+
+ setXMLFile("digikamimageplugin_border_ui.rc");
+
+ DDebug() << "ImagePlugin_Border plugin loaded" << endl;
+}
+
+ImagePlugin_Border::~ImagePlugin_Border()
+{
+}
+
+void ImagePlugin_Border::setEnabledActions(bool enable)
+{
+ m_borderAction->setEnabled(enable);
+}
+
+void ImagePlugin_Border::slotBorder()
+{
+ BorderTool *tool = new BorderTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/border/imageplugin_border.h b/src/imageplugins/border/imageplugin_border.h
new file mode 100644
index 00000000..e5b3d959
--- /dev/null
+++ b/src/imageplugins/border/imageplugin_border.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-20
+ * Description : a digiKam image plugin to add a border
+ * around an image.
+ *
+ * Copyright 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_BORDER_H
+#define IMAGEPLUGIN_BORDER_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_Border : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_Border(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_Border();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotBorder();
+
+private:
+
+ TDEAction *m_borderAction;
+};
+
+#endif /* IMAGEPLUGIN_BORDER_H */
diff --git a/src/imageplugins/border/patterns/Makefile.am b/src/imageplugins/border/patterns/Makefile.am
new file mode 100644
index 00000000..31bb4b2d
--- /dev/null
+++ b/src/imageplugins/border/patterns/Makefile.am
@@ -0,0 +1,5 @@
+borderpicsdir = $(kde_datadir)/digikam/data
+borderpics_DATA = pine-pattern.png wood-pattern.png paper-pattern.png parque-pattern.png \
+ ice-pattern.png leaf-pattern.png marble-pattern.png rain-pattern.png \
+ craters-pattern.png dried-pattern.png pink-pattern.png stone-pattern.png \
+ chalk-pattern.png granit-pattern.png rock-pattern.png wall-pattern.png
diff --git a/src/imageplugins/border/patterns/chalk-pattern.png b/src/imageplugins/border/patterns/chalk-pattern.png
new file mode 100644
index 00000000..31c34f62
--- /dev/null
+++ b/src/imageplugins/border/patterns/chalk-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/craters-pattern.png b/src/imageplugins/border/patterns/craters-pattern.png
new file mode 100644
index 00000000..fe8fe792
--- /dev/null
+++ b/src/imageplugins/border/patterns/craters-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/dried-pattern.png b/src/imageplugins/border/patterns/dried-pattern.png
new file mode 100644
index 00000000..fca948ff
--- /dev/null
+++ b/src/imageplugins/border/patterns/dried-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/granit-pattern.png b/src/imageplugins/border/patterns/granit-pattern.png
new file mode 100644
index 00000000..eccbb354
--- /dev/null
+++ b/src/imageplugins/border/patterns/granit-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/ice-pattern.png b/src/imageplugins/border/patterns/ice-pattern.png
new file mode 100644
index 00000000..30a67265
--- /dev/null
+++ b/src/imageplugins/border/patterns/ice-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/leaf-pattern.png b/src/imageplugins/border/patterns/leaf-pattern.png
new file mode 100644
index 00000000..b602fceb
--- /dev/null
+++ b/src/imageplugins/border/patterns/leaf-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/marble-pattern.png b/src/imageplugins/border/patterns/marble-pattern.png
new file mode 100644
index 00000000..6346bf1f
--- /dev/null
+++ b/src/imageplugins/border/patterns/marble-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/paper-pattern.png b/src/imageplugins/border/patterns/paper-pattern.png
new file mode 100644
index 00000000..43da3b2f
--- /dev/null
+++ b/src/imageplugins/border/patterns/paper-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/parque-pattern.png b/src/imageplugins/border/patterns/parque-pattern.png
new file mode 100644
index 00000000..2aa5e96f
--- /dev/null
+++ b/src/imageplugins/border/patterns/parque-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/pine-pattern.png b/src/imageplugins/border/patterns/pine-pattern.png
new file mode 100644
index 00000000..4ae7a687
--- /dev/null
+++ b/src/imageplugins/border/patterns/pine-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/pink-pattern.png b/src/imageplugins/border/patterns/pink-pattern.png
new file mode 100644
index 00000000..d0649c85
--- /dev/null
+++ b/src/imageplugins/border/patterns/pink-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/rain-pattern.png b/src/imageplugins/border/patterns/rain-pattern.png
new file mode 100644
index 00000000..a282c442
--- /dev/null
+++ b/src/imageplugins/border/patterns/rain-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/rock-pattern.png b/src/imageplugins/border/patterns/rock-pattern.png
new file mode 100644
index 00000000..04dc8b0e
--- /dev/null
+++ b/src/imageplugins/border/patterns/rock-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/stone-pattern.png b/src/imageplugins/border/patterns/stone-pattern.png
new file mode 100644
index 00000000..98da7c2c
--- /dev/null
+++ b/src/imageplugins/border/patterns/stone-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/wall-pattern.png b/src/imageplugins/border/patterns/wall-pattern.png
new file mode 100644
index 00000000..3c101597
--- /dev/null
+++ b/src/imageplugins/border/patterns/wall-pattern.png
Binary files differ
diff --git a/src/imageplugins/border/patterns/wood-pattern.png b/src/imageplugins/border/patterns/wood-pattern.png
new file mode 100644
index 00000000..bfe4c724
--- /dev/null
+++ b/src/imageplugins/border/patterns/wood-pattern.png
Binary files differ
diff --git a/src/imageplugins/channelmixer/Makefile.am b/src/imageplugins/channelmixer/Makefile.am
new file mode 100644
index 00000000..61eaab34
--- /dev/null
+++ b/src/imageplugins/channelmixer/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_channelmixer_la_SOURCES = imageplugin_channelmixer.cpp \
+ channelmixertool.cpp
+
+digikamimageplugin_channelmixer_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_channelmixer_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_channelmixer.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_channelmixer.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_channelmixer_ui.rc
+
diff --git a/src/imageplugins/channelmixer/channelmixer.cpp b/src/imageplugins/channelmixer/channelmixer.cpp
new file mode 100644
index 00000000..849cc1e8
--- /dev/null
+++ b/src/imageplugins/channelmixer/channelmixer.cpp
@@ -0,0 +1,784 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-26
+ * Description : image channels mixer.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Load and save mixer gains methods inspired from
+ * Gimp 2.2.3 and copyrighted 2002 by Martin Guldahl
+ * <mguldahl at xmission dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
+#include <cerrno>
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqlabel.h>
+#include <tqpainter.h>
+#include <tqcombobox.h>
+#include <tqspinbox.h>
+#include <tqvbox.h>
+#include <tqwhatsthis.h>
+#include <tqpushbutton.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqtimer.h>
+#include <tqcheckbox.h>
+#include <tqfile.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <knuminput.h>
+#include <tdemessagebox.h>
+#include <tdeselect.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "version.h"
+#include "dimg.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagehistogram.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "dimgimagefilters.h"
+#include "channelmixer.h"
+#include "channelmixer.moc"
+
+namespace DigikamChannelMixerImagesPlugin
+{
+
+ChannelMixerDialog::ChannelMixerDialog(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Color Channel Mixer"),
+ "channelmixer", true, false)
+{
+ m_destinationPreviewData = 0L;
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Color Channel Mixer"),
+ digikam_version,
+ I18N_NOOP("An image color channel mixer plugin for digiKam."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new Digikam::ImageWidget("channelmixer Tool Dialog", plainPage(),
+ i18n("<p>You can see here the image's color channels' "
+ "gains adjustments preview. You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* grid = new TQGridLayout( gboxSettings, 9, 4, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ m_channelCB->setCurrentText( i18n("Red") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the color channel to mix here:<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ grid->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "mixer settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+
+ grid->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQLabel *redLabel = new TQLabel(i18n("Red:"), gboxSettings);
+ m_redGain = new KDoubleNumInput(gboxSettings);
+ m_redGain->setPrecision(0);
+ m_redGain->setRange(-200.0, 200.0, 1, true);
+ TQWhatsThis::add( m_redGain, i18n("<p>Select the red color gain in percent for the current channel here."));
+
+ TQLabel *blueLabel = new TQLabel(i18n("Blue:"), gboxSettings);
+ m_greenGain = new KDoubleNumInput(gboxSettings);
+ m_greenGain->setPrecision(0);
+ m_greenGain->setRange(-200.0, 200.0, 1, true);
+ TQWhatsThis::add( m_greenGain, i18n("<p>Select the green color gain in percent for the current channel here."));
+
+ TQLabel *greenLabel = new TQLabel(i18n("Green:"), gboxSettings);
+ m_blueGain = new KDoubleNumInput(gboxSettings);
+ m_blueGain->setPrecision(0);
+ m_blueGain->setRange(-200.0, 200.0, 1, true);
+ TQWhatsThis::add( m_blueGain, i18n("<p>Select the blue color gain in percent for the current channel here."));
+
+ m_resetButton = new TQPushButton(i18n("&Reset"), gboxSettings);
+ TQWhatsThis::add( m_resetButton, i18n("Reset color channels' gains settings from the currently selected channel."));
+
+ grid->addMultiCellWidget(redLabel, 3, 3, 0, 0);
+ grid->addMultiCellWidget(greenLabel, 4, 4, 0, 0);
+ grid->addMultiCellWidget(blueLabel, 5, 5, 0, 0);
+ grid->addMultiCellWidget(m_redGain, 3, 3, 1, 4);
+ grid->addMultiCellWidget(m_greenGain, 4, 4, 1, 4);
+ grid->addMultiCellWidget(m_blueGain, 5, 5, 1, 4);
+ grid->addMultiCellWidget(m_resetButton, 6, 6, 0, 1);
+
+ // -------------------------------------------------------------
+
+ m_monochrome = new TQCheckBox( i18n("Monochrome"), gboxSettings);
+ TQWhatsThis::add( m_monochrome, i18n("<p>Enable this option if you want the image rendered in monochrome mode. "
+ "In this mode, the histogram will display only luminosity values."));
+
+ m_preserveLuminosity = new TQCheckBox( i18n("Preserve luminosity"), gboxSettings);
+ TQWhatsThis::add( m_preserveLuminosity, i18n("<p>Enable this option is you want preserve the image luminosity."));
+
+ grid->addMultiCellWidget(m_monochrome, 7, 7, 0, 4);
+ grid->addMultiCellWidget(m_preserveLuminosity, 8, 8, 0, 4);
+ grid->setRowStretch(9, 10);
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+ // Channels and scale selection slots.
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+ // Gains settings slots.
+
+ connect(m_redGain, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotGainsChanged()));
+
+ connect(m_greenGain, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotGainsChanged()));
+
+ connect(m_blueGain, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotGainsChanged()));
+
+ connect(m_preserveLuminosity, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_monochrome, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotMonochromeActived(bool)));
+
+ // -------------------------------------------------------------
+ // Bouttons slots.
+
+ connect(m_resetButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotResetCurrentChannel()));
+}
+
+ChannelMixerDialog::~ChannelMixerDialog()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+}
+
+void ChannelMixerDialog::slotResetCurrentChannel()
+{
+ switch( m_channelCB->currentItem() )
+ {
+ case GreenChannelGains: // Green.
+ m_greenRedGain = 0.0;
+ m_greenGreenGain = 1.0;
+ m_greenBlueGain = 0.0;
+ break;
+
+ case BlueChannelGains: // Blue.
+ m_blueRedGain = 0.0;
+ m_blueGreenGain = 0.0;
+ m_blueBlueGain = 1.0;
+ break;
+
+ default: // Red or monochrome.
+ if ( m_monochrome->isChecked() )
+ {
+ m_blackRedGain = 1.0;
+ m_blackGreenGain = 0.0;
+ m_blackBlueGain = 0.0;
+ }
+ else
+ {
+ m_redRedGain = 1.0;
+ m_redGreenGain = 0.0;
+ m_redBlueGain = 0.0;
+ }
+ break;
+ }
+
+ adjustSliders();
+ slotEffect();
+ m_histogramWidget->reset();
+}
+
+void ChannelMixerDialog::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ChannelMixerDialog::slotGainsChanged()
+{
+ switch( m_channelCB->currentItem() )
+ {
+ case GreenChannelGains: // Green.
+ m_greenRedGain = m_redGain->value() / 100.0;
+ m_greenGreenGain = m_greenGain->value() / 100.0;
+ m_greenBlueGain = m_blueGain->value() / 100.0;
+ break;
+
+ case BlueChannelGains: // Blue.
+ m_blueRedGain = m_redGain->value() / 100.0;
+ m_blueGreenGain = m_greenGain->value() / 100.0;
+ m_blueBlueGain = m_blueGain->value() / 100.0;
+ break;
+
+ default: // Red or monochrome.
+ if ( m_monochrome->isChecked() )
+ {
+ m_blackRedGain = m_redGain->value() / 100.0;
+ m_blackGreenGain = m_greenGain->value() / 100.0;
+ m_blackBlueGain = m_blueGain->value() / 100.0;
+ }
+ else
+ {
+ m_redRedGain = m_redGain->value() / 100.0;
+ m_redGreenGain = m_greenGain->value() / 100.0;
+ m_redBlueGain = m_blueGain->value() / 100.0;
+ }
+ break;
+ }
+
+ slotTimer();
+}
+
+void ChannelMixerDialog::adjustSliders(void)
+{
+ m_redGain->blockSignals(true);
+ m_greenGain->blockSignals(true);
+ m_blueGain->blockSignals(true);
+
+ switch( m_channelCB->currentItem() )
+ {
+ case GreenChannelGains: // Green.
+ m_redGain->setValue(m_greenRedGain * 100.0);
+ m_greenGain->setValue(m_greenGreenGain * 100.0);
+ m_blueGain->setValue(m_greenBlueGain * 100.0);
+ break;
+
+ case BlueChannelGains: // Blue.
+ m_redGain->setValue(m_blueRedGain * 100.0);
+ m_greenGain->setValue(m_blueGreenGain * 100.0);
+ m_blueGain->setValue(m_blueBlueGain * 100.0);
+ break;
+
+ default: // Red or monochrome.
+ if ( m_monochrome->isChecked() )
+ {
+ m_redGain->setValue(m_blackRedGain * 100.0);
+ m_greenGain->setValue(m_blackGreenGain * 100.0);
+ m_blueGain->setValue(m_blackBlueGain * 100.0);
+ }
+ else
+ {
+ m_redGain->setValue(m_redRedGain * 100.0);
+ m_greenGain->setValue(m_redGreenGain * 100.0);
+ m_blueGain->setValue(m_redBlueGain * 100.0);
+ }
+ break;
+ }
+
+ m_redGain->blockSignals(false);
+ m_greenGain->blockSignals(false);
+ m_blueGain->blockSignals(false);
+}
+
+void ChannelMixerDialog::slotMonochromeActived(bool mono)
+{
+ m_channelCB->setEnabled(!mono);
+ m_channelCB->setCurrentItem(RedChannelGains); // Red for monochrome.
+ slotChannelChanged(RedChannelGains); // Monochrome => display luminosity histogram value.
+}
+
+void ChannelMixerDialog::slotEffect()
+{
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ // Create the new empty destination image data space.
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ m_destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)];
+ Digikam::DImgImageFilters filter;
+
+ if (m_monochrome->isChecked())
+ {
+ filter.channelMixerImage(data, w, h, sb, // Image data.
+ m_preserveLuminosity->isChecked(), // Preserve luminosity.
+ m_monochrome->isChecked(), // Monochrome.
+ m_blackRedGain, m_blackGreenGain, m_blackBlueGain, // Red channel gains.
+ 0.0, 1.0, 0.0, // Green channel gains (not used).
+ 0.0, 0.0, 1.0); // Blue channel gains (not used).
+ }
+ else
+ {
+ filter.channelMixerImage(data, w, h, sb, // Image data.
+ m_preserveLuminosity->isChecked(), // Preserve luminosity.
+ m_monochrome->isChecked(), // Monochrome.
+ m_redRedGain, m_redGreenGain, m_redBlueGain, // Red channel gains.
+ m_greenRedGain, m_greenGreenGain, m_greenBlueGain, // Green channel gains.
+ m_blueRedGain, m_blueGreenGain, m_blueBlueGain); // Blue channel gains.
+ }
+
+ iface->putPreviewImage(data);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+ memcpy (m_destinationPreviewData, data, w*h*(sb ? 8 : 4));
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ delete [] data;
+}
+
+void ChannelMixerDialog::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ Digikam::DImgImageFilters filter;
+
+ if (m_monochrome->isChecked())
+ {
+ filter.channelMixerImage(data, w, h, sb, // Image data.
+ m_preserveLuminosity->isChecked(), // Preserve luminosity.
+ m_monochrome->isChecked(), // Monochrome.
+ m_blackRedGain, m_blackGreenGain, m_blackBlueGain, // Red channel gains.
+ 0.0, 1.0, 0.0, // Green channel gains (not used).
+ 0.0, 0.0, 1.0); // Blue channel gains (not used).
+ }
+ else
+ {
+ filter.channelMixerImage(data, w, h, sb, // Image data.
+ m_preserveLuminosity->isChecked(), // Preserve luminosity.
+ m_monochrome->isChecked(), // Monochrome.
+ m_redRedGain, m_redGreenGain, m_redBlueGain, // Red channel gains.
+ m_greenRedGain, m_greenGreenGain, m_greenBlueGain, // Green channel gains.
+ m_blueRedGain, m_blueGreenGain, m_blueBlueGain); // Blue channel gains.
+ }
+
+ iface->putOriginalImage(i18n("Channel Mixer"), data);
+ delete [] data;
+ kapp->restoreOverrideCursor();
+ accept();
+}
+
+void ChannelMixerDialog::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case GreenChannelGains: // Green.
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannelGains: // Blue.
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+
+ default: // Red or monochrome.
+ if ( m_monochrome->isChecked() )
+ {
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ }
+ else
+ {
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ }
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+ adjustSliders();
+ slotEffect();
+}
+
+void ChannelMixerDialog::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ChannelMixerDialog::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("channelmixer Tool Dialog");
+
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+
+ m_monochrome->setChecked(config->readBoolEntry("Monochrome", false));
+ m_preserveLuminosity->setChecked(config->readNumEntry("PreserveLuminosity", false));
+
+ m_redRedGain = config->readDoubleNumEntry("RedRedGain", 1.0);
+ m_redGreenGain = config->readDoubleNumEntry("RedGreenGain", 0.0);
+ m_redBlueGain = config->readDoubleNumEntry("RedBlueGain", 0.0);
+
+ m_greenRedGain = config->readDoubleNumEntry("GreenRedGain", 0.0);
+ m_greenGreenGain = config->readDoubleNumEntry("GreenGreenGain", 1.0);
+ m_greenBlueGain = config->readDoubleNumEntry("GreenBlueGain", 0.0);
+
+ m_blueRedGain = config->readDoubleNumEntry("BlueRedGain", 0.0);
+ m_blueGreenGain = config->readDoubleNumEntry("BlueGreenGain", 0.0);
+ m_blueBlueGain = config->readDoubleNumEntry("BlueBlueGain", 1.0);
+
+ m_blackRedGain = config->readDoubleNumEntry("BlackRedGain", 1.0);
+ m_blackGreenGain = config->readDoubleNumEntry("BlackGreenGain", 0.0);
+ m_blackBlueGain = config->readDoubleNumEntry("BlackBlueGain", 0.0);
+
+ adjustSliders();
+ m_histogramWidget->reset();
+
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ChannelMixerDialog::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("channelmixer Tool Dialog");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+
+ config->writeEntry("Monochrome", m_monochrome->isChecked());
+ config->writeEntry("PreserveLuminosity", m_preserveLuminosity->isChecked());
+
+ config->writeEntry("RedRedGain", m_redRedGain);
+ config->writeEntry("RedGreenGain", m_redGreenGain);
+ config->writeEntry("RedBlueGain", m_redBlueGain);
+
+ config->writeEntry("GreenRedGain", m_greenRedGain);
+ config->writeEntry("GreenGreenGain", m_greenGreenGain);
+ config->writeEntry("GreenBlueGain", m_greenBlueGain);
+
+ config->writeEntry("BlueRedGain", m_blueRedGain);
+ config->writeEntry("BlueGreenGain", m_blueGreenGain);
+ config->writeEntry("BlueBlueGain", m_blueBlueGain);
+
+ config->writeEntry("BlackRedGain", m_blackRedGain);
+ config->writeEntry("BlackGreenGain", m_blackGreenGain);
+ config->writeEntry("BlackBlueGain", m_blackBlueGain);
+
+ config->sync();
+}
+
+void ChannelMixerDialog::resetValues()
+{
+ m_monochrome->blockSignals(true);
+ m_preserveLuminosity->blockSignals(true);
+
+ m_redRedGain = 1.0;
+ m_redGreenGain = 0.0;
+ m_redBlueGain = 0.0;
+
+ m_greenRedGain = 0.0;
+ m_greenGreenGain = 1.0;
+ m_greenBlueGain = 0.0;
+
+ m_blueRedGain = 0.0;
+ m_blueGreenGain = 0.0;
+ m_blueBlueGain = 1.0;
+
+ m_blackRedGain = 1.0;
+ m_blackGreenGain = 0.0;
+ m_blackBlueGain = 0.0;
+
+ adjustSliders();
+
+ m_monochrome->blockSignals(false);
+ m_preserveLuminosity->blockSignals(false);
+ m_channelCB->setEnabled(true);
+
+ m_histogramWidget->reset();
+
+ slotChannelChanged(RedChannelGains);
+}
+
+// Load all gains.
+void ChannelMixerDialog::slotUser3()
+{
+ KURL loadGainsFileUrl;
+ FILE *fp = 0L;
+ int currentOutputChannel;
+ bool monochrome;
+
+ loadGainsFileUrl = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Select Gimp Gains Mixer File to Load")) );
+ if( loadGainsFileUrl.isEmpty() )
+ return;
+
+ fp = fopen(TQFile::encodeName(loadGainsFileUrl.path()), "r");
+
+ if ( fp )
+ {
+ char buf1[1024];
+ char buf2[1024];
+ char buf3[1024];
+
+ buf1[0] = '\0';
+
+ fgets(buf1, 1023, fp);
+
+ fscanf (fp, "%*s %s", buf1);
+
+ // Get the current output channel in dialog.
+
+ if (strcmp (buf1, "RED") == 0)
+ currentOutputChannel = RedChannelGains;
+ else if (strcmp (buf1, "GREEN") == 0)
+ currentOutputChannel = GreenChannelGains;
+ else if (strcmp (buf1, "BLUE") == 0)
+ currentOutputChannel = BlueChannelGains;
+
+ fscanf (fp, "%*s %s", buf1); // preview flag, preserved for compatibility
+
+ fscanf (fp, "%*s %s", buf1);
+
+ if (strcmp (buf1, "true") == 0)
+ monochrome = true;
+ else
+ monochrome = false;
+
+ fscanf (fp, "%*s %s", buf1);
+
+ if (strcmp (buf1, "true") == 0)
+ m_preserveLuminosity->setChecked(true);
+ else
+ m_preserveLuminosity->setChecked(false);
+
+ fscanf (fp, "%*s %s %s %s", buf1, buf2, buf3);
+ m_redRedGain = atof(buf1);
+ m_redGreenGain = atof(buf2);
+ m_redBlueGain = atof(buf3);
+
+ fscanf (fp, "%*s %s %s %s", buf1, buf2, buf3);
+ m_greenRedGain = atof(buf1);
+ m_greenGreenGain = atof(buf2);
+ m_greenBlueGain = atof(buf3);
+
+ fscanf (fp, "%*s %s %s %s", buf1, buf2, buf3);
+ m_blueRedGain = atof(buf1);
+ m_blueGreenGain = atof(buf2);
+ m_blueBlueGain = atof(buf3);
+
+ fscanf (fp, "%*s %s %s %s", buf1, buf2, buf3);
+ m_blackRedGain = atof(buf1);
+ m_blackGreenGain = atof(buf2);
+ m_blackBlueGain = atof(buf3);
+
+ fclose(fp);
+
+ // Refresh settings.
+ m_monochrome->setChecked(monochrome);
+ m_channelCB->setCurrentItem(currentOutputChannel);
+ slotChannelChanged(currentOutputChannel);
+ }
+ else
+ {
+ KMessageBox::error(this, i18n("Cannot load settings from the Gains Mixer text file."));
+ return;
+ }
+}
+
+// Save all gains.
+void ChannelMixerDialog::slotUser2()
+{
+ KURL saveGainsFileUrl;
+ FILE *fp = 0L;
+
+ saveGainsFileUrl = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Gimp Gains Mixer File to Save")) );
+ if( saveGainsFileUrl.isEmpty() )
+ return;
+
+ fp = fopen(TQFile::encodeName(saveGainsFileUrl.path()), "w");
+
+ if ( fp )
+ {
+ const char *str = 0L;
+ char buf1[256];
+ char buf2[256];
+ char buf3[256];
+
+ switch ( m_channelCB->currentItem() )
+ {
+ case RedChannelGains:
+ str = "RED";
+ break;
+ case GreenChannelGains:
+ str = "GREEN";
+ break;
+ case BlueChannelGains:
+ str = "BLUE";
+ break;
+ default:
+ DWarning() << "Unknown Color channel gains" << endl;
+ break;
+ }
+
+ fprintf (fp, "# Channel Mixer Configuration File\n");
+
+ fprintf (fp, "CHANNEL: %s\n", str);
+ fprintf (fp, "PREVIEW: %s\n", "true"); // preserved for compatibility
+ fprintf (fp, "MONOCHROME: %s\n",
+ m_monochrome->isChecked() ? "true" : "false");
+ fprintf (fp, "PRESERVE_LUMINOSITY: %s\n",
+ m_preserveLuminosity->isChecked() ? "true" : "false");
+
+ sprintf (buf1, "%5.3f", m_redRedGain);
+ sprintf (buf2, "%5.3f", m_redGreenGain);
+ sprintf (buf3, "%5.3f", m_redBlueGain);
+ fprintf (fp, "RED: %s %s %s\n", buf1, buf2,buf3);
+
+ sprintf (buf1, "%5.3f", m_greenRedGain);
+ sprintf (buf2, "%5.3f", m_greenGreenGain);
+ sprintf (buf3, "%5.3f", m_greenBlueGain);
+ fprintf (fp, "GREEN: %s %s %s\n", buf1, buf2,buf3);
+
+ sprintf (buf1, "%5.3f", m_blueRedGain);
+ sprintf (buf2, "%5.3f", m_blueGreenGain);
+ sprintf (buf3, "%5.3f", m_blueBlueGain);
+ fprintf (fp, "BLUE: %s %s %s\n", buf1, buf2,buf3);
+
+ sprintf (buf1, "%5.3f", m_blackRedGain);
+ sprintf (buf2, "%5.3f", m_blackGreenGain);
+ sprintf (buf3, "%5.3f", m_blackBlueGain);
+ fprintf (fp, "BLACK: %s %s %s\n", buf1, buf2,buf3);
+
+ fclose (fp);
+ }
+ else
+ {
+ KMessageBox::error(this, i18n("Cannot save settings to the Gains Mixer text file."));
+ return;
+ }
+}
+
+} // NameSpace DigikamChannelMixerImagesPlugin
+
diff --git a/src/imageplugins/channelmixer/channelmixer.h b/src/imageplugins/channelmixer/channelmixer.h
new file mode 100644
index 00000000..9b4396d0
--- /dev/null
+++ b/src/imageplugins/channelmixer/channelmixer.h
@@ -0,0 +1,133 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-26
+ * Description : image channels mixer.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef CHANNELMIXER_H
+#define CHANNELMIXER_H
+
+// Digikam includes.
+
+#include "imagedlgbase.h"
+
+class TQCheckBox;
+class TQComboBox;
+class TQPushButton;
+class TQHButtonGroup;
+
+class KDoubleNumInput;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+}
+
+namespace DigikamChannelMixerImagesPlugin
+{
+
+class ChannelMixerDialog : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ChannelMixerDialog(TQWidget *parent);
+ ~ChannelMixerDialog();
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void finalRendering();
+ void adjustSliders();
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+ void slotResetCurrentChannel();
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotGainsChanged();
+ void slotMonochromeActived(bool mono);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+
+private:
+
+ enum ColorChannelGains
+ {
+ RedChannelGains=0,
+ GreenChannelGains,
+ BlueChannelGains
+ };
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+private:
+
+ uchar *m_destinationPreviewData;
+
+ double m_redRedGain;
+ double m_redGreenGain;
+ double m_redBlueGain;
+ double m_greenRedGain;
+ double m_greenGreenGain;
+ double m_greenBlueGain;
+ double m_blueRedGain;
+ double m_blueGreenGain;
+ double m_blueBlueGain;
+ double m_blackRedGain;
+ double m_blackGreenGain;
+ double m_blackBlueGain;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ KDoubleNumInput *m_redGain;
+ KDoubleNumInput *m_greenGain;
+ KDoubleNumInput *m_blueGain;
+
+ TQPushButton *m_resetButton;
+
+ TQCheckBox *m_preserveLuminosity;
+ TQCheckBox *m_monochrome;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ImageWidget *m_previewWidget;
+};
+
+} // NameSpace DigikamChannelMixerImagesPlugin
+
+#endif /* CHANNELMIXER_H */
diff --git a/src/imageplugins/channelmixer/channelmixertool.cpp b/src/imageplugins/channelmixer/channelmixertool.cpp
new file mode 100644
index 00000000..c8215178
--- /dev/null
+++ b/src/imageplugins/channelmixer/channelmixertool.cpp
@@ -0,0 +1,774 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-26
+ * Description : image channels mixer.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
+#include <cerrno>
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqfile.h>
+#include <tqframe.h>
+#include <tqgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqhgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpainter.h>
+#include <tqpushbutton.h>
+#include <tqspinbox.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kcursor.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdepopupmenu.h>
+#include <tdeselect.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "dimg.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagehistogram.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "dimgimagefilters.h"
+#include "editortoolsettings.h"
+#include "channelmixertool.h"
+#include "channelmixertool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamChannelMixerImagesPlugin
+{
+
+ChannelMixerTool::ChannelMixerTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ m_destinationPreviewData = 0;
+
+ setName("channelmixer");
+ setToolName(i18n("Channel Mixer"));
+ setToolIcon(SmallIcon("channelmixer"));
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImageWidget("channelmixer Tool", 0,
+ i18n("<p>You can see here the image's color channels' "
+ "gains adjustments preview. You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 9, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), m_gboxSettings->plainPage());
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, m_gboxSettings->plainPage() );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ m_channelCB->setCurrentText( i18n("Red") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the color channel to mix here:<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(m_gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "mixer settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget( ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+
+ // -------------------------------------------------------------
+
+ TQLabel *redLabel = new TQLabel(i18n("Red:"), m_gboxSettings->plainPage());
+ m_redGain = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_redGain->setPrecision(0);
+ m_redGain->setRange(-200.0, 200.0, 1);
+ m_redGain->setDefaultValue(0);
+ TQWhatsThis::add( m_redGain, i18n("<p>Select the red color gain in percent for the current channel here."));
+
+ TQLabel *blueLabel = new TQLabel(i18n("Blue:"), m_gboxSettings->plainPage());
+ m_greenGain = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_greenGain->setPrecision(0);
+ m_greenGain->setRange(-200.0, 200.0, 1);
+ m_greenGain->setDefaultValue(0);
+ TQWhatsThis::add( m_greenGain, i18n("<p>Select the green color gain in percent for the current channel here."));
+
+ TQLabel *greenLabel = new TQLabel(i18n("Green:"), m_gboxSettings->plainPage());
+ m_blueGain = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_blueGain->setPrecision(0);
+ m_blueGain->setRange(-200.0, 200.0, 1);
+ m_blueGain->setDefaultValue(0);
+ TQWhatsThis::add( m_blueGain, i18n("<p>Select the blue color gain in percent for the current channel here."));
+
+ m_resetButton = new TQPushButton(i18n("&Reset"), m_gboxSettings->plainPage());
+ TQWhatsThis::add( m_resetButton, i18n("Reset color channels' gains settings from the currently selected channel."));
+
+ // -------------------------------------------------------------
+
+ m_monochrome = new TQCheckBox( i18n("Monochrome"), m_gboxSettings->plainPage());
+ TQWhatsThis::add( m_monochrome, i18n("<p>Enable this option if you want the image rendered in monochrome mode. "
+ "In this mode, the histogram will display only luminosity values."));
+
+ m_preserveLuminosity = new TQCheckBox( i18n("Preserve luminosity"), m_gboxSettings->plainPage());
+ TQWhatsThis::add( m_preserveLuminosity, i18n("<p>Enable this option is you want preserve the image luminosity."));
+
+ grid->addMultiCellLayout(l1, 0, 0, 0, 4);
+ grid->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+ grid->addMultiCellWidget(redLabel, 3, 3, 0, 0);
+ grid->addMultiCellWidget(greenLabel, 4, 4, 0, 0);
+ grid->addMultiCellWidget(blueLabel, 5, 5, 0, 0);
+ grid->addMultiCellWidget(m_redGain, 3, 3, 1, 4);
+ grid->addMultiCellWidget(m_greenGain, 4, 4, 1, 4);
+ grid->addMultiCellWidget(m_blueGain, 5, 5, 1, 4);
+ grid->addMultiCellWidget(m_resetButton, 6, 6, 0, 1);
+ grid->addMultiCellWidget(m_monochrome, 7, 7, 0, 4);
+ grid->addMultiCellWidget(m_preserveLuminosity, 8, 8, 0, 4);
+ grid->setRowStretch(9, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+ // Channels and scale selection slots.
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotColorSelectedFromTarget(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+ // Gains settings slots.
+
+ connect(m_redGain, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotGainsChanged()));
+
+ connect(m_greenGain, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotGainsChanged()));
+
+ connect(m_blueGain, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotGainsChanged()));
+
+ connect(m_preserveLuminosity, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_monochrome, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotMonochromeActived(bool)));
+
+ // -------------------------------------------------------------
+ // Bouttons slots.
+
+ connect(m_resetButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotResetCurrentChannel()));
+}
+
+ChannelMixerTool::~ChannelMixerTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void ChannelMixerTool::slotResetCurrentChannel()
+{
+ switch( m_channelCB->currentItem() )
+ {
+ case GreenChannelGains: // Green.
+ m_greenRedGain = 0.0;
+ m_greenGreenGain = 1.0;
+ m_greenBlueGain = 0.0;
+ break;
+
+ case BlueChannelGains: // Blue.
+ m_blueRedGain = 0.0;
+ m_blueGreenGain = 0.0;
+ m_blueBlueGain = 1.0;
+ break;
+
+ default: // Red or monochrome.
+ if ( m_monochrome->isChecked() )
+ {
+ m_blackRedGain = 1.0;
+ m_blackGreenGain = 0.0;
+ m_blackBlueGain = 0.0;
+ }
+ else
+ {
+ m_redRedGain = 1.0;
+ m_redGreenGain = 0.0;
+ m_redBlueGain = 0.0;
+ }
+ break;
+ }
+
+ adjustSliders();
+ slotEffect();
+ m_histogramWidget->reset();
+}
+
+void ChannelMixerTool::slotColorSelectedFromTarget(const DColor& color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ChannelMixerTool::slotGainsChanged()
+{
+ switch( m_channelCB->currentItem() )
+ {
+ case GreenChannelGains: // Green.
+ m_greenRedGain = m_redGain->value() / 100.0;
+ m_greenGreenGain = m_greenGain->value() / 100.0;
+ m_greenBlueGain = m_blueGain->value() / 100.0;
+ break;
+
+ case BlueChannelGains: // Blue.
+ m_blueRedGain = m_redGain->value() / 100.0;
+ m_blueGreenGain = m_greenGain->value() / 100.0;
+ m_blueBlueGain = m_blueGain->value() / 100.0;
+ break;
+
+ default: // Red or monochrome.
+ if ( m_monochrome->isChecked() )
+ {
+ m_blackRedGain = m_redGain->value() / 100.0;
+ m_blackGreenGain = m_greenGain->value() / 100.0;
+ m_blackBlueGain = m_blueGain->value() / 100.0;
+ }
+ else
+ {
+ m_redRedGain = m_redGain->value() / 100.0;
+ m_redGreenGain = m_greenGain->value() / 100.0;
+ m_redBlueGain = m_blueGain->value() / 100.0;
+ }
+ break;
+ }
+
+ slotTimer();
+}
+
+void ChannelMixerTool::adjustSliders()
+{
+ m_redGain->blockSignals(true);
+ m_greenGain->blockSignals(true);
+ m_blueGain->blockSignals(true);
+
+ switch( m_channelCB->currentItem() )
+ {
+ case GreenChannelGains: // Green.
+ m_redGain->setValue(m_greenRedGain * 100.0);
+ m_greenGain->setValue(m_greenGreenGain * 100.0);
+ m_blueGain->setValue(m_greenBlueGain * 100.0);
+ break;
+
+ case BlueChannelGains: // Blue.
+ m_redGain->setValue(m_blueRedGain * 100.0);
+ m_greenGain->setValue(m_blueGreenGain * 100.0);
+ m_blueGain->setValue(m_blueBlueGain * 100.0);
+ break;
+
+ default: // Red or monochrome.
+ if ( m_monochrome->isChecked() )
+ {
+ m_redGain->setValue(m_blackRedGain * 100.0);
+ m_greenGain->setValue(m_blackGreenGain * 100.0);
+ m_blueGain->setValue(m_blackBlueGain * 100.0);
+ }
+ else
+ {
+ m_redGain->setValue(m_redRedGain * 100.0);
+ m_greenGain->setValue(m_redGreenGain * 100.0);
+ m_blueGain->setValue(m_redBlueGain * 100.0);
+ }
+ break;
+ }
+
+ m_redGain->blockSignals(false);
+ m_greenGain->blockSignals(false);
+ m_blueGain->blockSignals(false);
+}
+
+void ChannelMixerTool::slotMonochromeActived(bool mono)
+{
+ m_channelCB->setEnabled(!mono);
+ m_channelCB->setCurrentItem(RedChannelGains); // Red for monochrome.
+ slotChannelChanged(RedChannelGains); // Monochrome => display luminosity histogram value.
+}
+
+void ChannelMixerTool::slotEffect()
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ // Create the new empty destination image data space.
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ m_destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)];
+ DImgImageFilters filter;
+
+ if (m_monochrome->isChecked())
+ {
+ filter.channelMixerImage(data, w, h, sb, // Image data.
+ m_preserveLuminosity->isChecked(), // Preserve luminosity.
+ m_monochrome->isChecked(), // Monochrome.
+ m_blackRedGain, m_blackGreenGain, m_blackBlueGain, // Red channel gains.
+ 0.0, 1.0, 0.0, // Green channel gains (not used).
+ 0.0, 0.0, 1.0); // Blue channel gains (not used).
+ }
+ else
+ {
+ filter.channelMixerImage(data, w, h, sb, // Image data.
+ m_preserveLuminosity->isChecked(), // Preserve luminosity.
+ m_monochrome->isChecked(), // Monochrome.
+ m_redRedGain, m_redGreenGain, m_redBlueGain, // Red channel gains.
+ m_greenRedGain, m_greenGreenGain, m_greenBlueGain, // Green channel gains.
+ m_blueRedGain, m_blueGreenGain, m_blueBlueGain); // Blue channel gains.
+ }
+
+ iface->putPreviewImage(data);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+ memcpy (m_destinationPreviewData, data, w*h*(sb ? 8 : 4));
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ delete [] data;
+}
+
+void ChannelMixerTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ DImgImageFilters filter;
+
+ if (m_monochrome->isChecked())
+ {
+ filter.channelMixerImage(data, w, h, sb, // Image data.
+ m_preserveLuminosity->isChecked(), // Preserve luminosity.
+ m_monochrome->isChecked(), // Monochrome.
+ m_blackRedGain, m_blackGreenGain, m_blackBlueGain, // Red channel gains.
+ 0.0, 1.0, 0.0, // Green channel gains (not used).
+ 0.0, 0.0, 1.0); // Blue channel gains (not used).
+ }
+ else
+ {
+ filter.channelMixerImage(data, w, h, sb, // Image data.
+ m_preserveLuminosity->isChecked(), // Preserve luminosity.
+ m_monochrome->isChecked(), // Monochrome.
+ m_redRedGain, m_redGreenGain, m_redBlueGain, // Red channel gains.
+ m_greenRedGain, m_greenGreenGain, m_greenBlueGain, // Green channel gains.
+ m_blueRedGain, m_blueGreenGain, m_blueBlueGain); // Blue channel gains.
+ }
+
+ iface->putOriginalImage(i18n("Channel Mixer"), data);
+ delete [] data;
+ kapp->restoreOverrideCursor();
+}
+
+void ChannelMixerTool::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case GreenChannelGains: // Green.
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannelGains: // Blue.
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+
+ default: // Red or monochrome.
+ if ( m_monochrome->isChecked() )
+ {
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ }
+ else
+ {
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ }
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+ adjustSliders();
+ slotEffect();
+}
+
+void ChannelMixerTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ChannelMixerTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("channelmixer Tool");
+
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+
+ m_monochrome->setChecked(config->readBoolEntry("Monochrome", false));
+ m_preserveLuminosity->setChecked(config->readNumEntry("PreserveLuminosity", false));
+
+ m_redRedGain = config->readDoubleNumEntry("RedRedGain", 1.0);
+ m_redGreenGain = config->readDoubleNumEntry("RedGreenGain", 0.0);
+ m_redBlueGain = config->readDoubleNumEntry("RedBlueGain", 0.0);
+
+ m_greenRedGain = config->readDoubleNumEntry("GreenRedGain", 0.0);
+ m_greenGreenGain = config->readDoubleNumEntry("GreenGreenGain", 1.0);
+ m_greenBlueGain = config->readDoubleNumEntry("GreenBlueGain", 0.0);
+
+ m_blueRedGain = config->readDoubleNumEntry("BlueRedGain", 0.0);
+ m_blueGreenGain = config->readDoubleNumEntry("BlueGreenGain", 0.0);
+ m_blueBlueGain = config->readDoubleNumEntry("BlueBlueGain", 1.0);
+
+ m_blackRedGain = config->readDoubleNumEntry("BlackRedGain", 1.0);
+ m_blackGreenGain = config->readDoubleNumEntry("BlackGreenGain", 0.0);
+ m_blackBlueGain = config->readDoubleNumEntry("BlackBlueGain", 0.0);
+
+ adjustSliders();
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ChannelMixerTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("channelmixer Tool");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+
+ config->writeEntry("Monochrome", m_monochrome->isChecked());
+ config->writeEntry("PreserveLuminosity", m_preserveLuminosity->isChecked());
+
+ config->writeEntry("RedRedGain", m_redRedGain);
+ config->writeEntry("RedGreenGain", m_redGreenGain);
+ config->writeEntry("RedBlueGain", m_redBlueGain);
+
+ config->writeEntry("GreenRedGain", m_greenRedGain);
+ config->writeEntry("GreenGreenGain", m_greenGreenGain);
+ config->writeEntry("GreenBlueGain", m_greenBlueGain);
+
+ config->writeEntry("BlueRedGain", m_blueRedGain);
+ config->writeEntry("BlueGreenGain", m_blueGreenGain);
+ config->writeEntry("BlueBlueGain", m_blueBlueGain);
+
+ config->writeEntry("BlackRedGain", m_blackRedGain);
+ config->writeEntry("BlackGreenGain", m_blackGreenGain);
+ config->writeEntry("BlackBlueGain", m_blackBlueGain);
+
+ m_previewWidget->writeSettings();
+
+ config->sync();
+}
+
+void ChannelMixerTool::slotResetSettings()
+{
+ m_monochrome->blockSignals(true);
+ m_preserveLuminosity->blockSignals(true);
+
+ m_redRedGain = 1.0;
+ m_redGreenGain = 0.0;
+ m_redBlueGain = 0.0;
+
+ m_greenRedGain = 0.0;
+ m_greenGreenGain = 1.0;
+ m_greenBlueGain = 0.0;
+
+ m_blueRedGain = 0.0;
+ m_blueGreenGain = 0.0;
+ m_blueBlueGain = 1.0;
+
+ m_blackRedGain = 1.0;
+ m_blackGreenGain = 0.0;
+ m_blackBlueGain = 0.0;
+
+ adjustSliders();
+
+ m_monochrome->blockSignals(false);
+ m_preserveLuminosity->blockSignals(false);
+ m_channelCB->setEnabled(true);
+
+ m_histogramWidget->reset();
+
+ slotChannelChanged(RedChannelGains);
+}
+
+void ChannelMixerTool::slotLoadSettings()
+{
+ KURL loadGainsFileUrl;
+ FILE *fp = 0L;
+ int currentOutputChannel;
+ bool monochrome;
+
+ loadGainsFileUrl = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Select Gimp Gains Mixer File to Load")) );
+ if( loadGainsFileUrl.isEmpty() )
+ return;
+
+ fp = fopen(TQFile::encodeName(loadGainsFileUrl.path()), "r");
+
+ if ( fp )
+ {
+ char buf1[1024];
+ char buf2[1024];
+ char buf3[1024];
+
+ buf1[0] = '\0';
+
+ fgets(buf1, 1023, fp);
+
+ fscanf (fp, "%*s %s", buf1);
+
+ // Get the current output channel in dialog.
+
+ if (strcmp (buf1, "RED") == 0)
+ currentOutputChannel = RedChannelGains;
+ else if (strcmp (buf1, "GREEN") == 0)
+ currentOutputChannel = GreenChannelGains;
+ else if (strcmp (buf1, "BLUE") == 0)
+ currentOutputChannel = BlueChannelGains;
+
+ fscanf (fp, "%*s %s", buf1); // preview flag, preserved for compatibility
+
+ fscanf (fp, "%*s %s", buf1);
+
+ if (strcmp (buf1, "true") == 0)
+ monochrome = true;
+ else
+ monochrome = false;
+
+ fscanf (fp, "%*s %s", buf1);
+
+ if (strcmp (buf1, "true") == 0)
+ m_preserveLuminosity->setChecked(true);
+ else
+ m_preserveLuminosity->setChecked(false);
+
+ fscanf (fp, "%*s %s %s %s", buf1, buf2, buf3);
+ m_redRedGain = atof(buf1);
+ m_redGreenGain = atof(buf2);
+ m_redBlueGain = atof(buf3);
+
+ fscanf (fp, "%*s %s %s %s", buf1, buf2, buf3);
+ m_greenRedGain = atof(buf1);
+ m_greenGreenGain = atof(buf2);
+ m_greenBlueGain = atof(buf3);
+
+ fscanf (fp, "%*s %s %s %s", buf1, buf2, buf3);
+ m_blueRedGain = atof(buf1);
+ m_blueGreenGain = atof(buf2);
+ m_blueBlueGain = atof(buf3);
+
+ fscanf (fp, "%*s %s %s %s", buf1, buf2, buf3);
+ m_blackRedGain = atof(buf1);
+ m_blackGreenGain = atof(buf2);
+ m_blackBlueGain = atof(buf3);
+
+ fclose(fp);
+
+ // Refresh settings.
+ m_monochrome->setChecked(monochrome);
+ m_channelCB->setCurrentItem(currentOutputChannel);
+ slotChannelChanged(currentOutputChannel);
+ }
+ else
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot load settings from the Gains Mixer text file."));
+ return;
+ }
+}
+
+void ChannelMixerTool::slotSaveAsSettings()
+{
+ KURL saveGainsFileUrl;
+ FILE *fp = 0L;
+
+ saveGainsFileUrl = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Gimp Gains Mixer File to Save")) );
+ if( saveGainsFileUrl.isEmpty() )
+ return;
+
+ fp = fopen(TQFile::encodeName(saveGainsFileUrl.path()), "w");
+
+ if ( fp )
+ {
+ const char *str = 0L;
+ char buf1[256];
+ char buf2[256];
+ char buf3[256];
+
+ switch ( m_channelCB->currentItem() )
+ {
+ case RedChannelGains:
+ str = "RED";
+ break;
+ case GreenChannelGains:
+ str = "GREEN";
+ break;
+ case BlueChannelGains:
+ str = "BLUE";
+ break;
+ default:
+ DWarning() << "Unknown Color channel gains" << endl;
+ break;
+ }
+
+ fprintf (fp, "# Channel Mixer Configuration File\n");
+
+ fprintf (fp, "CHANNEL: %s\n", str);
+ fprintf (fp, "PREVIEW: %s\n", "true"); // preserved for compatibility
+ fprintf (fp, "MONOCHROME: %s\n",
+ m_monochrome->isChecked() ? "true" : "false");
+ fprintf (fp, "PRESERVE_LUMINOSITY: %s\n",
+ m_preserveLuminosity->isChecked() ? "true" : "false");
+
+ sprintf (buf1, "%5.3f", m_redRedGain);
+ sprintf (buf2, "%5.3f", m_redGreenGain);
+ sprintf (buf3, "%5.3f", m_redBlueGain);
+ fprintf (fp, "RED: %s %s %s\n", buf1, buf2,buf3);
+
+ sprintf (buf1, "%5.3f", m_greenRedGain);
+ sprintf (buf2, "%5.3f", m_greenGreenGain);
+ sprintf (buf3, "%5.3f", m_greenBlueGain);
+ fprintf (fp, "GREEN: %s %s %s\n", buf1, buf2,buf3);
+
+ sprintf (buf1, "%5.3f", m_blueRedGain);
+ sprintf (buf2, "%5.3f", m_blueGreenGain);
+ sprintf (buf3, "%5.3f", m_blueBlueGain);
+ fprintf (fp, "BLUE: %s %s %s\n", buf1, buf2,buf3);
+
+ sprintf (buf1, "%5.3f", m_blackRedGain);
+ sprintf (buf2, "%5.3f", m_blackGreenGain);
+ sprintf (buf3, "%5.3f", m_blackBlueGain);
+ fprintf (fp, "BLACK: %s %s %s\n", buf1, buf2,buf3);
+
+ fclose (fp);
+ }
+ else
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot save settings to the Gains Mixer text file."));
+ return;
+ }
+}
+
+} // NameSpace DigikamChannelMixerImagesPlugin
diff --git a/src/imageplugins/channelmixer/channelmixertool.h b/src/imageplugins/channelmixer/channelmixertool.h
new file mode 100644
index 00000000..c15a30cd
--- /dev/null
+++ b/src/imageplugins/channelmixer/channelmixertool.h
@@ -0,0 +1,138 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-26
+ * Description : image channels mixer.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef CHANNELMIXERTOOL_H
+#define CHANNELMIXERTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQCheckBox;
+class TQComboBox;
+class TQPushButton;
+class TQHButtonGroup;
+
+namespace KDcrawIface
+{
+class RDoubleNumInput;
+}
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+}
+
+namespace DigikamChannelMixerImagesPlugin
+{
+
+class ChannelMixerTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ ChannelMixerTool(TQObject *parent);
+ ~ChannelMixerTool();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+ void adjustSliders();
+
+private slots:
+
+ void slotLoadSettings();
+ void slotSaveAsSettings();
+ void slotResetCurrentChannel();
+ void slotEffect();
+ void slotResetSettings();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotGainsChanged();
+ void slotMonochromeActived(bool mono);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+
+private:
+
+ enum ColorChannelGains
+ {
+ RedChannelGains=0,
+ GreenChannelGains,
+ BlueChannelGains
+ };
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+private:
+
+ uchar *m_destinationPreviewData;
+
+ double m_redRedGain;
+ double m_redGreenGain;
+ double m_redBlueGain;
+ double m_greenRedGain;
+ double m_greenGreenGain;
+ double m_greenBlueGain;
+ double m_blueRedGain;
+ double m_blueGreenGain;
+ double m_blueBlueGain;
+ double m_blackRedGain;
+ double m_blackGreenGain;
+ double m_blackBlueGain;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ KDcrawIface::RDoubleNumInput *m_redGain;
+ KDcrawIface::RDoubleNumInput *m_greenGain;
+ KDcrawIface::RDoubleNumInput *m_blueGain;
+
+ TQPushButton *m_resetButton;
+
+ TQCheckBox *m_preserveLuminosity;
+ TQCheckBox *m_monochrome;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamChannelMixerImagesPlugin
+
+#endif /* CHANNELMIXERTOOL_H */
diff --git a/src/imageplugins/channelmixer/digikamimageplugin_channelmixer.desktop b/src/imageplugins/channelmixer/digikamimageplugin_channelmixer.desktop
new file mode 100644
index 00000000..a855fffe
--- /dev/null
+++ b/src/imageplugins/channelmixer/digikamimageplugin_channelmixer.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Name=ImagePlugin_ChannelMixer
+Name[bg]=Приставка за снимки - Смесител на канали
+Name[el]=ΠρόσθετοΕικόνας_ΑνάμειξηΚαναλιών
+Name[fi]=KanavatasapainonSäätö
+Name[hr]=Miješanje kanala
+Name[it]=PluginImmagini_MixerDeiCanali
+Name[nl]=Afbeeldingsplugin_Kanaalmixer
+Name[sr]=Миксета канала
+Name[sr@Latn]=Mikseta kanala
+Name[sv]=Insticksprogram för kanalblandning
+Name[tr]=ResimEklentisi_KanalKarıştırıcı
+Name[xx]=xxImagePlugin_ChannelMixerxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+
+Comment=Image color channels mixer plugin for digiKam
+Comment[bg]=Приставка на digiKam със смесител на цветови канали
+Comment[ca]=Connector pel digiKam per mesclar els canals de color de la imatge
+Comment[da]=Digikam plugin til at blande billedfarvekanaler
+Comment[de]=digiKam-Modul zum Mischen von Farbkanälen eines Bildes
+Comment[el]=Πρόσθετο μείκτη καναλιών χρώματος εικόνας για το digiKam
+Comment[en_GB]=Image colour channels mixer plugin for digiKam
+Comment[es]=Plugin para digiKam para la mezcla de los canales de color de imagen
+Comment[et]=DigiKami pildi värvikanalite mikseri plugin
+Comment[fa]=وصلۀ مخلوط‌کن مجراهای رنگ تصویر برای digiKam
+Comment[fi]=Värikanavien sekoitussuhteiden muokkain
+Comment[gl]=Un plugin de digiKam para misturar os canais de cores
+Comment[hr]=digiKam dodatak za miješanje kanala boja
+Comment[is]=Íforrit fyrir digiKam sem blandar litrásum mynda
+Comment[it]=Plugin di mixer dei canali dei colori per digiKam
+Comment[ja]=digiKam カラーチャンネルミキサープラグイン
+Comment[nds]=digiKam-Mischermoduul för de Bild-Klöörkanaals
+Comment[nl]=Digikam-plugin voor kanaalmixer
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਚਿੱਤਰ ਰੰਗ ਚੈਨਲ ਮਿਕਸਰ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam mieszająca kanały kolorów
+Comment[pt]=Um 'plugin' do digiKam para misturar os canais de cores
+Comment[pt_BR]=Plugin do mixer de canais de cor da imagem
+Comment[ru]=Модуль микширования цветовых каналов для digiKam
+Comment[sk]=digiKam plugin pre miešanie farebných kanálov obrázku
+Comment[sr]=Прикључак миксете канала боја за digiKam
+Comment[sr@Latn]=Priključak miksete kanala boja za digiKam
+Comment[sv]=Digikam insticksprogram för att blanda bildfärgkanaler
+Comment[tr]=digiKam için resim kanalları karıştıcı eklentisi
+Comment[uk]=Втулок змішування каналів кольорів для digiKam
+Comment[vi]=Phần bổ sung hoà kênh màu ảnh cho digiKam
+Comment[xx]=xxImage color channels mixer plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_channelmixer
+author=Caulier Gilles, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/channelmixer/digikamimageplugin_channelmixer_ui.rc b/src/imageplugins/channelmixer/digikamimageplugin_channelmixer_ui.rc
new file mode 100644
index 00000000..1a004c96
--- /dev/null
+++ b/src/imageplugins/channelmixer/digikamimageplugin_channelmixer_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_channelmixer" >
+
+ <MenuBar>
+
+ <Menu name="Color"><text>&amp;Color</text>
+ <Action name="imageplugin_channelmixer" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action name="imageplugin_channelmixer" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/channelmixer/imageplugin_channelmixer.cpp b/src/imageplugins/channelmixer/imageplugin_channelmixer.cpp
new file mode 100644
index 00000000..19fe21a9
--- /dev/null
+++ b/src/imageplugins/channelmixer/imageplugin_channelmixer.cpp
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-26
+ * Description : image channels mixer.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "channelmixertool.h"
+#include "imageplugin_channelmixer.h"
+#include "imageplugin_channelmixer.moc"
+
+using namespace DigikamChannelMixerImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_channelmixer,
+ KGenericFactory<ImagePlugin_ChannelMixer>("digikamimageplugin_channelmixer"))
+
+ImagePlugin_ChannelMixer::ImagePlugin_ChannelMixer(TQObject *parent, const char*,
+ const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_ChannelMixer")
+{
+ m_channelMixerAction = new TDEAction(i18n("Channel Mixer..."), "channelmixer",
+ CTRL+Key_H,
+ this, TQ_SLOT(slotChannelMixer()),
+ actionCollection(), "imageplugin_channelmixer");
+
+ setXMLFile("digikamimageplugin_channelmixer_ui.rc");
+
+ DDebug() << "ImagePlugin_ChannelMixer plugin loaded" << endl;
+}
+
+ImagePlugin_ChannelMixer::~ImagePlugin_ChannelMixer()
+{
+}
+
+void ImagePlugin_ChannelMixer::setEnabledActions(bool enable)
+{
+ m_channelMixerAction->setEnabled(enable);
+}
+
+void ImagePlugin_ChannelMixer::slotChannelMixer()
+{
+ ChannelMixerTool *cm = new ChannelMixerTool(this);
+ loadTool(cm);
+}
diff --git a/src/imageplugins/channelmixer/imageplugin_channelmixer.h b/src/imageplugins/channelmixer/imageplugin_channelmixer.h
new file mode 100644
index 00000000..444006ab
--- /dev/null
+++ b/src/imageplugins/channelmixer/imageplugin_channelmixer.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-26
+ * Description : image channels mixer.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_CHANNELMIXER_H
+#define IMAGEPLUGIN_CHANNELMIXER_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_ChannelMixer : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_ChannelMixer(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_ChannelMixer();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotChannelMixer();
+
+private:
+
+ TDEAction *m_channelMixerAction;
+};
+
+#endif /* IMAGEPLUGIN_CHANNELMIXER_H */
diff --git a/src/imageplugins/charcoal/Makefile.am b/src/imageplugins/charcoal/Makefile.am
new file mode 100644
index 00000000..3d851deb
--- /dev/null
+++ b/src/imageplugins/charcoal/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_charcoal_la_SOURCES = imageplugin_charcoal.cpp \
+ charcoaltool.cpp charcoal.cpp
+
+digikamimageplugin_charcoal_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_charcoal_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_charcoal.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_charcoal.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_charcoal_ui.rc
+
diff --git a/src/imageplugins/charcoal/charcoal.cpp b/src/imageplugins/charcoal/charcoal.cpp
new file mode 100644
index 00000000..a4c54a3c
--- /dev/null
+++ b/src/imageplugins/charcoal/charcoal.cpp
@@ -0,0 +1,249 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Charcoal threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original Charcoal algorithm copyright 2002
+ * by Daniel M. Duley <mosfet@kde.org> from KImageEffect API.
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#define SQ2PI 2.50662827463100024161235523934010416269302368164062
+#define Epsilon 1.0e-12
+
+// C++ includes.
+
+#include <cmath>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimggaussianblur.h"
+#include "dimgimagefilters.h"
+#include "charcoal.h"
+
+namespace DigikamCharcoalImagesPlugin
+{
+
+Charcoal::Charcoal(Digikam::DImg *orgImage, TQObject *parent, double pencil, double smooth)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "Charcoal")
+{
+ m_pencil = pencil;
+ m_smooth = smooth;
+
+ initFilter();
+}
+
+void Charcoal::filterImage(void)
+{
+ if (m_orgImage.isNull())
+ {
+ DWarning() << k_funcinfo << "No image data available!"
+ << endl;
+ return;
+ }
+
+ if (m_pencil <= 0.0)
+ {
+ m_destImage = m_orgImage;
+ return;
+ }
+
+ // -- Applying Edge effect -----------------------------------------------
+
+ long i=0;
+ int kernelWidth = getOptimalKernelWidth(m_pencil, m_smooth);
+
+ if((int)m_orgImage.width() < kernelWidth)
+ {
+ DWarning() << k_funcinfo << "Image is smaller than radius!"
+ << endl;
+ return;
+ }
+
+ double *kernel = new double[kernelWidth*kernelWidth];
+
+ if(!kernel)
+ {
+ DWarning() << k_funcinfo << "Unable to allocate memory!"
+ << endl;
+ return;
+ }
+
+ for(i = 0 ; i < (kernelWidth*kernelWidth) ; i++)
+ kernel[i]=(-1.0);
+
+ kernel[i/2]=kernelWidth*kernelWidth-1.0;
+ convolveImage(kernelWidth, kernel);
+ delete [] kernel;
+
+ // -- Applying Gaussian blur effect ---------------------------------------
+
+ Digikam::DImgGaussianBlur(this, m_destImage, m_destImage, 50, 60, (int)(m_smooth/10.0));
+
+ if (m_cancel)
+ return;
+
+ // -- Applying strech contrast color effect -------------------------------
+
+ Digikam::DImgImageFilters().stretchContrastImage(m_destImage.bits(), m_destImage.width(),
+ m_destImage.height(), m_destImage.sixteenBit());
+ postProgress( 70 );
+ if (m_cancel)
+ return;
+
+ // -- Inverting image color -----------------------------------------------
+
+ Digikam::DImgImageFilters().invertImage(m_destImage.bits(), m_destImage.width(),
+ m_destImage.height(), m_destImage.sixteenBit());
+ postProgress( 80 );
+ if (m_cancel)
+ return;
+
+ // -- Convert to neutral black & white ------------------------------------
+
+ Digikam::DImgImageFilters().channelMixerImage(
+ m_destImage.bits(), m_destImage.width(),
+ m_destImage.height(), m_destImage.sixteenBit(), // Image data.
+ true, // Preserve luminosity.
+ true, // Monochrome.
+ 0.3, 0.59 , 0.11, // Red channel gains.
+ 0.0, 1.0, 0.0, // Green channel gains (not used).
+ 0.0, 0.0, 1.0); // Blue channel gains (not used).
+ postProgress( 90 );
+ if (m_cancel)
+ return;
+}
+
+bool Charcoal::convolveImage(const unsigned int order, const double *kernel)
+{
+ uint x, y;
+ int mx, my, sx, sy, mcx, mcy, progress;
+ long kernelWidth, i;
+ double red, green, blue, alpha, normalize=0.0;
+ double *k=0;
+ Digikam::DColor color;
+
+ kernelWidth = order;
+
+ if((kernelWidth % 2) == 0)
+ {
+ DWarning() << k_funcinfo << "Kernel width must be an odd number!"
+ << endl;
+ return(false);
+ }
+
+ double *normal_kernel = new double[kernelWidth*kernelWidth];
+
+ if(!normal_kernel)
+ {
+ DWarning() << k_funcinfo << "Unable to allocate memory!"
+ << endl;
+ return(false);
+ }
+
+ for(i=0 ; i < (kernelWidth*kernelWidth) ; i++)
+ normalize += kernel[i];
+
+ if(fabs(normalize) <= Epsilon)
+ normalize=1.0;
+
+ normalize = 1.0/normalize;
+
+ for(i=0 ; i < (kernelWidth*kernelWidth) ; i++)
+ normal_kernel[i] = normalize*kernel[i];
+
+ double maxClamp = m_destImage.sixteenBit() ? 16777215.0 : 65535.0;
+
+ for(y=0 ; !m_cancel && (y < m_destImage.height()) ; y++)
+ {
+ sy = y-(kernelWidth/2);
+
+ for(x=0 ; !m_cancel && (x < m_destImage.width()) ; x++)
+ {
+ k = normal_kernel;
+ red = green = blue = alpha = 0;
+ sy = y-(kernelWidth/2);
+
+ for(mcy=0 ; !m_cancel && (mcy < kernelWidth) ; mcy++, sy++)
+ {
+ my = sy < 0 ? 0 : sy > (int)m_destImage.height()-1 ? m_destImage.height()-1 : sy;
+ sx = x+(-kernelWidth/2);
+
+ for(mcx=0 ; !m_cancel && (mcx < kernelWidth) ; mcx++, sx++)
+ {
+ mx = sx < 0 ? 0 : sx > (int)m_destImage.width()-1 ? m_destImage.width()-1 : sx;
+ color = m_orgImage.getPixelColor(mx, my);
+ red += (*k)*(color.red() * 257.0);
+ green += (*k)*(color.green() * 257.0);
+ blue += (*k)*(color.blue() * 257.0);
+ alpha += (*k)*(color.alpha() * 257.0);
+ k++;
+ }
+ }
+
+ red = red < 0.0 ? 0.0 : red > maxClamp ? maxClamp : red+0.5;
+ green = green < 0.0 ? 0.0 : green > maxClamp ? maxClamp : green+0.5;
+ blue = blue < 0.0 ? 0.0 : blue > maxClamp ? maxClamp : blue+0.5;
+ alpha = alpha < 0.0 ? 0.0 : alpha > maxClamp ? maxClamp : alpha+0.5;
+
+ m_destImage.setPixelColor(x, y, Digikam::DColor((int)(red / 257UL), (int)(green / 257UL),
+ (int)(blue / 257UL), (int)(alpha / 257UL),
+ m_destImage.sixteenBit()));
+ }
+
+ progress = (int)(((double)y * 50.0) / m_destImage.height());
+ if ( progress%5 == 0 )
+ postProgress( progress );
+ }
+
+ delete [] normal_kernel;
+ return(true);
+}
+
+int Charcoal::getOptimalKernelWidth(double radius, double sigma)
+{
+ double normalize, value;
+ long kernelWidth;
+ long u;
+
+ if(radius > 0.0)
+ return((int)(2.0*ceil(radius)+1.0));
+
+ for(kernelWidth=5; ;)
+ {
+ normalize=0.0;
+
+ for(u=(-kernelWidth/2) ; u <= (kernelWidth/2) ; u++)
+ normalize += exp(-((double) u*u)/(2.0*sigma*sigma))/(SQ2PI*sigma);
+
+ u = kernelWidth/2;
+ value = exp(-((double) u*u)/(2.0*sigma*sigma))/(SQ2PI*sigma)/normalize;
+
+ if((long)(65535*value) <= 0)
+ break;
+
+ kernelWidth+=2;
+ }
+
+ return((int)kernelWidth-2);
+}
+
+} // NameSpace DigikamCharcoalImagesPlugin
diff --git a/src/imageplugins/charcoal/charcoal.h b/src/imageplugins/charcoal/charcoal.h
new file mode 100644
index 00000000..2088ccc4
--- /dev/null
+++ b/src/imageplugins/charcoal/charcoal.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Charcoal threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef CHARCOAL_H
+#define CHARCOAL_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamCharcoalImagesPlugin
+{
+
+class Charcoal : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ Charcoal(Digikam::DImg *orgImage, TQObject *parent=0, double pencil=5.0, double smooth=10.0);
+ ~Charcoal(){};
+
+private:
+
+ void filterImage(void);
+ bool convolveImage(const unsigned int order, const double *kernel);
+ int getOptimalKernelWidth(double radius, double sigma);
+
+private:
+
+ double m_pencil;
+ double m_smooth;
+};
+
+} // NameSpace DigikamCharcoalImagesPlugin
+
+#endif /* CHARCOAL_H */
diff --git a/src/imageplugins/charcoal/charcoaltool.cpp b/src/imageplugins/charcoal/charcoaltool.cpp
new file mode 100644
index 00000000..75ee22df
--- /dev/null
+++ b/src/imageplugins/charcoal/charcoaltool.cpp
@@ -0,0 +1,202 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digikam image editor plugin to
+ * simulate charcoal drawing.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "charcoal.h"
+#include "charcoaltool.h"
+#include "charcoaltool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamCharcoalImagesPlugin
+{
+
+CharcoalTool::CharcoalTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("charcoal");
+ setToolName(i18n("Charcoal"));
+ setToolIcon(SmallIcon("charcoaltool"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 4, 1);
+ TQLabel *label1 = new TQLabel(i18n("Pencil size:"), m_gboxSettings->plainPage());
+
+ m_pencilInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_pencilInput->setRange(1, 100, 1);
+ m_pencilInput->setDefaultValue(5);
+ TQWhatsThis::add( m_pencilInput, i18n("<p>Set here the charcoal pencil size used to simulate the drawing."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Smooth:"), m_gboxSettings->plainPage());
+
+ m_smoothInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_smoothInput->setRange(1, 100, 1);
+ m_smoothInput->setDefaultValue(10);
+ TQWhatsThis::add( m_smoothInput, i18n("<p>This value controls the smoothing effect of the pencil "
+ "under the canvas."));
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 1);
+ grid->addMultiCellWidget(m_pencilInput, 1, 1, 0, 1);
+ grid->addMultiCellWidget(label2, 2, 2, 0, 1);
+ grid->addMultiCellWidget(m_smoothInput, 3, 3, 0, 1);
+ grid->setRowStretch(4, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "charcoal Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_pencilInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_smoothInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+CharcoalTool::~CharcoalTool()
+{
+}
+
+void CharcoalTool::renderingFinished()
+{
+ m_pencilInput->setEnabled(true);
+ m_smoothInput->setEnabled(true);
+}
+
+void CharcoalTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("charcoal Tool");
+ m_pencilInput->blockSignals(true);
+ m_smoothInput->blockSignals(true);
+
+ m_pencilInput->setValue(config->readNumEntry("PencilAjustment", m_pencilInput->defaultValue()));
+ m_smoothInput->setValue(config->readNumEntry("SmoothAjustment", m_smoothInput->defaultValue()));
+
+ m_pencilInput->blockSignals(false);
+ m_smoothInput->blockSignals(false);
+}
+
+void CharcoalTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("charcoal Tool");
+ config->writeEntry("PencilAjustment", m_pencilInput->value());
+ config->writeEntry("SmoothAjustment", m_smoothInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void CharcoalTool::slotResetSettings()
+{
+ m_pencilInput->blockSignals(true);
+ m_smoothInput->blockSignals(true);
+
+ m_pencilInput->slotReset();
+ m_smoothInput->slotReset();
+
+ m_pencilInput->blockSignals(false);
+ m_smoothInput->blockSignals(false);
+}
+
+void CharcoalTool::prepareEffect()
+{
+ m_pencilInput->setEnabled(false);
+ m_smoothInput->setEnabled(false);
+
+ double pencil = (double)m_pencilInput->value()/10.0;
+ double smooth = (double)m_smoothInput->value();
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Charcoal(&image, this, pencil, smooth)));
+}
+
+void CharcoalTool::prepareFinal()
+{
+ m_pencilInput->setEnabled(false);
+ m_smoothInput->setEnabled(false);
+
+ double pencil = (double)m_pencilInput->value()/10.0;
+ double smooth = (double)m_smoothInput->value();
+
+ ImageIface iface(0, 0);
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Charcoal(iface.getOriginalImg(), this, pencil, smooth)));
+}
+
+void CharcoalTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void CharcoalTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Charcoal"), filter()->getTargetImage().bits());
+}
+
+} // NameSpace DigikamCharcoalImagesPlugin
diff --git a/src/imageplugins/charcoal/charcoaltool.h b/src/imageplugins/charcoal/charcoaltool.h
new file mode 100644
index 00000000..5833dd06
--- /dev/null
+++ b/src/imageplugins/charcoal/charcoaltool.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digikam image editor plugin to
+ * simulate charcoal drawing.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef CHARCOALTOOL_H
+#define CHARCOALTOOL_H
+
+// Local includes.
+
+#include "editortool.h"
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamCharcoalImagesPlugin
+{
+
+class CharcoalTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ CharcoalTool(TQObject* parent);
+ ~CharcoalTool();
+
+private slots:
+
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KDcrawIface::RIntNumInput *m_pencilInput;
+ KDcrawIface::RIntNumInput *m_smoothInput;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamCharcoalImagesPlugin
+
+#endif /* CHARCOALTOOL_H */
diff --git a/src/imageplugins/charcoal/digikamimageplugin_charcoal.desktop b/src/imageplugins/charcoal/digikamimageplugin_charcoal.desktop
new file mode 100644
index 00000000..e8957bbf
--- /dev/null
+++ b/src/imageplugins/charcoal/digikamimageplugin_charcoal.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Name=ImagePlugin_Charcoal
+Name[bg]=Приставка за снимки - Въглен
+Name[da]=Billedplugin_Kultegning
+Name[el]=ΠρόσθετοΕικόνας_Κάρβουνο
+Name[fi]=Hiilipiirros
+Name[hr]=Crtež ugljenom
+Name[it]=PluginImmagini_Carboncino
+Name[nl]=Afbeeldingsplugin_Houtskool
+Name[sr]=Угљен
+Name[sr@Latn]=Ugljen
+Name[sv]=Insticksprogram för kolteckning
+Name[tr]=ResimEklentisi_Karakalem
+Name[xx]=xxImagePlugin_Charcoalxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Charcoal drawing image effect plugin for digiKam
+Comment[bg]=Приставка на digiKam за наподобяване на рисуване с въглен върху снимки
+Comment[ca]=Connector pel digiKam d'efecte d'imatge de dibuix al carbonet
+Comment[da]=Plugin til kultegningseffekt på billeder i Digikam
+Comment[de]=digiKam-Modul zum Erzeugen eines Kohlezeichnung-Effekts
+Comment[el]=Πρόσθετο εφέ σχεδίασης με κάρβουνο για το digiKam
+Comment[es]=Plugin para digiKam con efectos de dibujo a carboncillo
+Comment[et]=DigiKami söejoonistuse pildiefektiplugin
+Comment[fa]=وصلۀ جلوۀ تصویر ترسیم Charcoal برای digiKam
+Comment[fi]=Jäljittelee hiiliviivapiirrosta
+Comment[gl]=Un plugin de digiKam para o efeito de imaxe debuxada ao carbón
+Comment[hr]=digiKam dodatak za efekt crtanja ugljenom
+Comment[is]=Íforrit fyrir digiKam sem líkir eftir viðarkolateikningu
+Comment[it]=Plugin di effetto di disegno dell'immagine con carboncino per digiKam
+Comment[ja]=digiKam 木炭画効果プラグイン
+Comment[nds]=digiKam-Moduul för Kahlteken-Effekten
+Comment[nl]=Digikam-plugin voor houtskooltekeningen
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਚਾਰਕੋਲ ਡਰਾਇੰਗ ਚਿੱਤਰ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam imitująca szkice węglem
+Comment[pt]=Um 'plugin' do digiKam para o efeito de imagem de desenho a carvão
+Comment[pt_BR]=Plugin de efeito de carvão para o digiKam
+Comment[ru]=Модуль изображения картинки углем для digiKam
+Comment[sk]=digiKam plugin pre efekt kreslenia kriedou
+Comment[sr]=Прикључак ефекта цртежа угљеном за digiKam
+Comment[sr@Latn]=Priključak efekta crteža ugljenom za digiKam
+Comment[sv]=Digikam insticksprogram för kolteckningsbildeffekt
+Comment[tr]=digiKam için karakalem resim etkisi eklentisi
+Comment[uk]=Втулок створення ефекту малювання вугільним олівцем для digiKam
+Comment[vi]=Phần bổ sung hiệu ứng vẽ ảnh than gỗ cho digiKam
+Comment[xx]=xxCharcoal drawing image effect plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_charcoal
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/charcoal/digikamimageplugin_charcoal_ui.rc b/src/imageplugins/charcoal/digikamimageplugin_charcoal_ui.rc
new file mode 100644
index 00000000..92ab4752
--- /dev/null
+++ b/src/imageplugins/charcoal/digikamimageplugin_charcoal_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="6" name="digikamimageplugin_charcoal" >
+
+ <MenuBar>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_charcoal" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_charcoal" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/charcoal/imageeffect_charcoal.cpp b/src/imageplugins/charcoal/imageeffect_charcoal.cpp
new file mode 100644
index 00000000..67a0269d
--- /dev/null
+++ b/src/imageplugins/charcoal/imageeffect_charcoal.cpp
@@ -0,0 +1,193 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digikam image editor plugin to
+ * simulate charcoal drawing.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "charcoal.h"
+#include "imageeffect_charcoal.h"
+#include "imageeffect_charcoal.moc"
+
+namespace DigikamCharcoalImagesPlugin
+{
+
+ImageEffect_Charcoal::ImageEffect_Charcoal(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Charcoal Drawing"),
+ "charcoal", false, false, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Charcoal Drawing"),
+ digikam_version,
+ I18N_NOOP("A digiKam charcoal drawing image effect plugin."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 3, 1, 0, spacingHint());
+ TQLabel *label1 = new TQLabel(i18n("Pencil size:"), gboxSettings);
+
+ m_pencilInput = new KIntNumInput(gboxSettings);
+ m_pencilInput->setRange(1, 100, 1, true);
+ m_pencilInput->setValue(5);
+ TQWhatsThis::add( m_pencilInput, i18n("<p>Set here the charcoal pencil size used to simulate the drawing."));
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_pencilInput, 1, 1, 0, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Smooth:"), gboxSettings);
+
+ m_smoothInput = new KIntNumInput(gboxSettings);
+ m_smoothInput->setRange(1, 100, 1, true);
+ m_smoothInput->setValue(10);
+ TQWhatsThis::add( m_smoothInput, i18n("<p>This value controls the smoothing effect of the pencil "
+ "under the canvas."));
+
+ gridSettings->addMultiCellWidget(label2, 2, 2, 0, 1);
+ gridSettings->addMultiCellWidget(m_smoothInput, 3, 3, 0, 1);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_pencilInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_smoothInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_Charcoal::~ImageEffect_Charcoal()
+{
+}
+
+void ImageEffect_Charcoal::renderingFinished()
+{
+ m_pencilInput->setEnabled(true);
+ m_smoothInput->setEnabled(true);
+}
+
+void ImageEffect_Charcoal::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("charcoal Tool Dialog");
+ m_pencilInput->blockSignals(true);
+ m_smoothInput->blockSignals(true);
+ m_pencilInput->setValue(config->readNumEntry("PencilAjustment", 5));
+ m_smoothInput->setValue(config->readNumEntry("SmoothAjustment", 10));
+ m_pencilInput->blockSignals(false);
+ m_smoothInput->blockSignals(false);
+}
+
+void ImageEffect_Charcoal::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("charcoal Tool Dialog");
+ config->writeEntry("PencilAjustment", m_pencilInput->value());
+ config->writeEntry("SmoothAjustment", m_smoothInput->value());
+ config->sync();
+}
+
+void ImageEffect_Charcoal::resetValues()
+{
+ m_pencilInput->blockSignals(true);
+ m_smoothInput->blockSignals(true);
+ m_pencilInput->setValue(5);
+ m_smoothInput->setValue(10);
+ m_pencilInput->blockSignals(false);
+ m_smoothInput->blockSignals(false);
+}
+
+void ImageEffect_Charcoal::prepareEffect()
+{
+ m_pencilInput->setEnabled(false);
+ m_smoothInput->setEnabled(false);
+
+ double pencil = (double)m_pencilInput->value()/10.0;
+ double smooth = (double)m_smoothInput->value();
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new Charcoal(&image, this, pencil, smooth));
+}
+
+void ImageEffect_Charcoal::prepareFinal()
+{
+ m_pencilInput->setEnabled(false);
+ m_smoothInput->setEnabled(false);
+
+ double pencil = (double)m_pencilInput->value()/10.0;
+ double smooth = (double)m_smoothInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new Charcoal(iface.getOriginalImg(),
+ this, pencil, smooth));
+}
+
+void ImageEffect_Charcoal::putPreviewData(void)
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_Charcoal::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Charcoal"), m_threadedFilter->getTargetImage().bits());
+}
+
+} // NameSpace DigikamCharcoalImagesPlugin
+
diff --git a/src/imageplugins/charcoal/imageeffect_charcoal.h b/src/imageplugins/charcoal/imageeffect_charcoal.h
new file mode 100644
index 00000000..31916ecc
--- /dev/null
+++ b/src/imageplugins/charcoal/imageeffect_charcoal.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digikam image editor plugin to
+ * simulate charcoal drawing.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_CHARCOAL_H
+#define IMAGEEFFECT_CHARCOAL_H
+
+// Local includes.
+
+#include "ctrlpaneldlg.h"
+
+class KIntNumInput;
+
+namespace DigikamCharcoalImagesPlugin
+{
+
+class ImageEffect_Charcoal : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Charcoal(TQWidget* parent);
+ ~ImageEffect_Charcoal();
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KIntNumInput *m_pencilInput;
+ KIntNumInput *m_smoothInput;
+};
+
+} // NameSpace DigikamCharcoalImagesPlugin
+
+#endif /* IMAGEEFFECT_CHARCOAL_H */
diff --git a/src/imageplugins/charcoal/imageplugin_charcoal.cpp b/src/imageplugins/charcoal/imageplugin_charcoal.cpp
new file mode 100644
index 00000000..ae28e7ca
--- /dev/null
+++ b/src/imageplugins/charcoal/imageplugin_charcoal.cpp
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digikam image editor plugin to
+ * simulate charcoal drawing.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "charcoaltool.h"
+#include "imageplugin_charcoal.h"
+#include "imageplugin_charcoal.moc"
+
+using namespace DigikamCharcoalImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_charcoal,
+ KGenericFactory<ImagePlugin_Charcoal>("digikamimageplugin_charcoal"));
+
+ImagePlugin_Charcoal::ImagePlugin_Charcoal(TQObject *parent, const char*,
+ const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_Charcoal")
+{
+ m_charcoalAction = new TDEAction(i18n("Charcoal Drawing..."), "charcoaltool", 0,
+ this, TQ_SLOT(slotCharcoal()),
+ actionCollection(), "imageplugin_charcoal");
+
+ setXMLFile( "digikamimageplugin_charcoal_ui.rc" );
+
+ DDebug() << "ImagePlugin_Charcoal plugin loaded" << endl;
+}
+
+ImagePlugin_Charcoal::~ImagePlugin_Charcoal()
+{
+}
+
+void ImagePlugin_Charcoal::setEnabledActions(bool enable)
+{
+ m_charcoalAction->setEnabled(enable);
+}
+
+void ImagePlugin_Charcoal::slotCharcoal()
+{
+ CharcoalTool *tool = new CharcoalTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/charcoal/imageplugin_charcoal.h b/src/imageplugins/charcoal/imageplugin_charcoal.h
new file mode 100644
index 00000000..c642087a
--- /dev/null
+++ b/src/imageplugins/charcoal/imageplugin_charcoal.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digikam image editor plugin to
+ * simulate charcoal drawing.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_CHARCOAL_H
+#define IMAGEPLUGIN_CHARCOAL_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_Charcoal : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_Charcoal(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_Charcoal();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotCharcoal();
+
+private:
+
+ TDEAction *m_charcoalAction;
+};
+
+#endif /* IMAGEPLUGIN_CHARCOAL_H */
diff --git a/src/imageplugins/colorfx/Makefile.am b/src/imageplugins/colorfx/Makefile.am
new file mode 100644
index 00000000..a0d2e4fa
--- /dev/null
+++ b/src/imageplugins/colorfx/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_colorfx_la_SOURCES = imageplugin_colorfx.cpp \
+ colorfxtool.cpp
+
+digikamimageplugin_colorfx_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_colorfx_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_colorfx.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_colorfx.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_colorfx_ui.rc
+
diff --git a/src/imageplugins/colorfx/colorfxtool.cpp b/src/imageplugins/colorfx/colorfxtool.cpp
new file mode 100644
index 00000000..dd16e7cf
--- /dev/null
+++ b/src/imageplugins/colorfx/colorfxtool.cpp
@@ -0,0 +1,699 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : a digiKam image plugin for to apply a color
+ * effect to an image.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcombobox.h>
+#include <tqframe.h>
+#include <tqhbuttongroup.h>
+#include <tqhgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "colorgradientwidget.h"
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "imagecurves.h"
+#include "imagehistogram.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "colorfxtool.h"
+#include "colorfxtool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamColorFXImagesPlugin
+{
+
+ColorFXTool::ColorFXTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("coloreffects");
+ setToolName(i18n("Color Effects"));
+ setToolIcon(SmallIcon("colorfx"));
+
+ m_destinationPreviewData = 0;
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImageWidget("coloreffects Tool", 0,
+ i18n("<p>This is the color effects preview"));
+
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ EditorToolSettings *gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings->plainPage(), 9, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings->plainPage());
+ label1->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+ m_channelCB = new TQComboBox(false, gboxSettings->plainPage());
+ m_channelCB->insertItem(i18n("Luminosity"));
+ m_channelCB->insertItem(i18n("Red"));
+ m_channelCB->insertItem(i18n("Green"));
+ m_channelCB->insertItem(i18n("Blue"));
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin(0);
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(linHistoButton, i18n("<p>Linear"));
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap(TQPixmap(directory + "histogram-lin.png"));
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(logHistoButton, i18n("<p>Logarithmic"));
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap(TQPixmap(directory + "histogram-log.png"));
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget( ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ // -------------------------------------------------------------
+
+ m_effectTypeLabel = new TQLabel(i18n("Type:"), gboxSettings->plainPage());
+
+ m_effectType = new RComboBox(gboxSettings->plainPage());
+ m_effectType->insertItem(i18n("Solarize"));
+ m_effectType->insertItem(i18n("Vivid"));
+ m_effectType->insertItem(i18n("Neon"));
+ m_effectType->insertItem(i18n("Find Edges"));
+ m_effectType->setDefaultItem(Solarize);
+ TQWhatsThis::add( m_effectType, i18n("<p>Select the effect type to apply to the image here.<p>"
+ "<b>Solarize</b>: simulates solarization of photograph.<p>"
+ "<b>Vivid</b>: simulates the Velvia(tm) slide film colors.<p>"
+ "<b>Neon</b>: coloring the edges in a photograph to "
+ "reproduce a fluorescent light effect.<p>"
+ "<b>Find Edges</b>: detects the edges in a photograph "
+ "and their strength."
+ ));
+
+ m_levelLabel = new TQLabel(i18n("Level:"), gboxSettings->plainPage());
+ m_levelInput = new RIntNumInput(gboxSettings->plainPage());
+ m_levelInput->setRange(0, 100, 1);
+ m_levelInput->setDefaultValue(0);
+ TQWhatsThis::add( m_levelInput, i18n("<p>Set here the level of the effect."));
+
+ m_iterationLabel = new TQLabel(i18n("Iteration:"), gboxSettings->plainPage());
+ m_iterationInput = new RIntNumInput(gboxSettings->plainPage());
+ m_iterationInput->setRange(0, 100, 1);
+ m_iterationInput->setDefaultValue(0);
+ TQWhatsThis::add( m_iterationInput, i18n("<p>This value controls the number of iterations "
+ "to use with the Neon and Find Edges effects."));
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+ gridSettings->addMultiCellWidget(m_effectTypeLabel, 3, 3, 0, 4);
+ gridSettings->addMultiCellWidget(m_effectType, 4, 4, 0, 4);
+ gridSettings->addMultiCellWidget(m_levelLabel, 5, 5, 0, 4);
+ gridSettings->addMultiCellWidget(m_levelInput, 6, 6, 0, 4);
+ gridSettings->addMultiCellWidget(m_iterationLabel, 7, 7, 0, 4);
+ gridSettings->addMultiCellWidget(m_iterationInput, 8, 8, 0, 4);
+ gridSettings->setRowStretch(9, 10);
+
+ setToolSettings(gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const DColor & )));
+
+ connect(m_levelInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_iterationInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_effectType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffectTypeChanged(int)));
+}
+
+ColorFXTool::~ColorFXTool()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void ColorFXTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("coloreffect Tool");
+ m_effectType->setCurrentItem(config->readNumEntry("EffectType", m_effectType->defaultItem()));
+ m_levelInput->setValue(config->readNumEntry("LevelAjustment", m_levelInput->defaultValue()));
+ m_iterationInput->setValue(config->readNumEntry("IterationAjustment", m_iterationInput->defaultValue()));
+ slotEffectTypeChanged(m_effectType->currentItem()); //check for enable/disable of iteration
+
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ColorFXTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("coloreffect Tool");
+ config->writeEntry("EffectType", m_effectType->currentItem());
+ config->writeEntry("LevelAjustment", m_levelInput->value());
+ config->writeEntry("IterationAjustment", m_iterationInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void ColorFXTool::slotResetSettings()
+{
+ m_levelInput->blockSignals(true);
+ m_iterationInput->blockSignals(true);
+ m_effectType->blockSignals(true);
+
+ m_levelInput->slotReset();
+ m_iterationInput->slotReset();
+ m_effectType->slotReset();
+
+ m_levelInput->blockSignals(false);
+ m_iterationInput->blockSignals(false);
+ m_effectType->blockSignals(false);
+
+ slotEffect();
+}
+
+void ColorFXTool::slotChannelChanged(int channel)
+{
+ switch (channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("red"));
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("green"));
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("blue"));
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ColorFXTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ColorFXTool::slotColorSelectedFromTarget(const DColor &color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ColorFXTool::slotEffectTypeChanged(int type)
+{
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+
+ m_levelInput->blockSignals(true);
+ m_iterationInput->blockSignals(true);
+ m_levelInput->setRange(0, 100, 1);
+ m_levelInput->setValue(25);
+
+ switch (type)
+ {
+ case Solarize:
+ m_levelInput->setRange(0, 100, 1);
+ m_levelInput->setValue(0);
+ m_iterationInput->setEnabled(false);
+ m_iterationLabel->setEnabled(false);
+ break;
+
+ case Vivid:
+ m_levelInput->setRange(0, 50, 1);
+ m_levelInput->setValue(5);
+ m_iterationInput->setEnabled(false);
+ m_iterationLabel->setEnabled(false);
+ break;
+
+ case Neon:
+ case FindEdges:
+ m_levelInput->setRange(0, 5, 1);
+ m_levelInput->setValue(3);
+ m_iterationInput->setEnabled(true);
+ m_iterationLabel->setEnabled(true);
+ m_iterationInput->setRange(0, 5, 1);
+ m_iterationInput->setValue(2);
+ break;
+ }
+
+ m_levelInput->blockSignals(false);
+ m_iterationInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ColorFXTool::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ colorEffect(m_destinationPreviewData, w, h, sb);
+
+ iface->putPreviewImage(m_destinationPreviewData);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void ColorFXTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ if (data)
+ {
+ colorEffect(data, w, h, sb);
+ TQString name;
+
+ switch (m_effectType->currentItem())
+ {
+ case Solarize:
+ name = i18n("ColorFX");
+ break;
+
+ case Vivid:
+ name = i18n("Vivid");
+ break;
+
+ case Neon:
+ name = i18n("Neon");
+ break;
+
+ case FindEdges:
+ name = i18n("Find Edges");
+ break;
+ }
+
+ iface->putOriginalImage(name, data);
+ delete[] data;
+ }
+
+ kapp->restoreOverrideCursor();
+}
+
+void ColorFXTool::colorEffect(uchar *data, int w, int h, bool sb)
+{
+ switch (m_effectType->currentItem())
+ {
+ case Solarize:
+ solarize(m_levelInput->value(), data, w, h, sb);
+ break;
+
+ case Vivid:
+ vivid(m_levelInput->value(), data, w, h, sb);
+ break;
+
+ case Neon:
+ neon(data, w, h, sb, m_levelInput->value(), m_iterationInput->value());
+ break;
+
+ case FindEdges:
+ findEdges(data, w, h, sb, m_levelInput->value(), m_iterationInput->value());
+ break;
+ }
+}
+
+void ColorFXTool::solarize(int factor, uchar *data, int w, int h, bool sb)
+{
+ bool stretch = true;
+
+ if (!sb) // 8 bits image.
+ {
+ uint threshold = (uint)((100-factor)*(255+1)/100);
+ threshold = TQMAX(1, threshold);
+ uchar *ptr = data;
+ uchar a, r, g, b;
+
+ for (int x=0 ; x < w*h ; x++)
+ {
+ b = ptr[0];
+ g = ptr[1];
+ r = ptr[2];
+ a = ptr[3];
+
+ if (stretch)
+ {
+ r = (r > threshold) ? (255-r)*255/(255-threshold) : r*255/threshold;
+ g = (g > threshold) ? (255-g)*255/(255-threshold) : g*255/threshold;
+ b = (b > threshold) ? (255-b)*255/(255-threshold) : b*255/threshold;
+ }
+ else
+ {
+ if (r > threshold)
+ r = (255-r);
+ if (g > threshold)
+ g = (255-g);
+ if (b > threshold)
+ b = (255-b);
+ }
+
+ ptr[0] = b;
+ ptr[1] = g;
+ ptr[2] = r;
+ ptr[3] = a;
+
+ ptr += 4;
+ }
+ }
+ else // 16 bits image.
+ {
+ uint threshold = (uint)((100-factor)*(65535+1)/100);
+ threshold = TQMAX(1, threshold);
+ unsigned short *ptr = (unsigned short *)data;
+ unsigned short a, r, g, b;
+
+ for (int x=0 ; x < w*h ; x++)
+ {
+ b = ptr[0];
+ g = ptr[1];
+ r = ptr[2];
+ a = ptr[3];
+
+ if (stretch)
+ {
+ r = (r > threshold) ? (65535-r)*65535/(65535-threshold) : r*65535/threshold;
+ g = (g > threshold) ? (65535-g)*65535/(65535-threshold) : g*65535/threshold;
+ b = (b > threshold) ? (65535-b)*65535/(65535-threshold) : b*65535/threshold;
+ }
+ else
+ {
+ if (r > threshold)
+ r = (65535-r);
+ if (g > threshold)
+ g = (65535-g);
+ if (b > threshold)
+ b = (65535-b);
+ }
+
+ ptr[0] = b;
+ ptr[1] = g;
+ ptr[2] = r;
+ ptr[3] = a;
+
+ ptr += 4;
+ }
+ }
+}
+
+void ColorFXTool::vivid(int factor, uchar *data, int w, int h, bool sb)
+{
+ float amount = factor/100.0;
+
+ DImgImageFilters filter;
+
+ // Apply Channel Mixer adjustments.
+
+ filter.channelMixerImage(
+ data, w, h, sb, // Image data.
+ true, // Preserve Luminosity
+ false, // Disable Black & White mode.
+ 1.0 + amount + amount, (-1.0)*amount, (-1.0)*amount, // Red Gains.
+ (-1.0)*amount, 1.0 + amount + amount, (-1.0)*amount, // Green Gains.
+ (-1.0)*amount, (-1.0)*amount, 1.0 + amount + amount // Blue Gains.
+ );
+
+ // Allocate the destination image data.
+
+ uchar *dest = new uchar[w*h*(sb ? 8 : 4)];
+
+ // And now apply the curve correction.
+
+ ImageCurves Curves(sb);
+
+ if (!sb) // 8 bits image.
+ {
+ Curves.setCurvePoint(ImageHistogram::ValueChannel, 0, TQPoint(0, 0));
+ Curves.setCurvePoint(ImageHistogram::ValueChannel, 5, TQPoint(63, 60));
+ Curves.setCurvePoint(ImageHistogram::ValueChannel, 10, TQPoint(191, 194));
+ Curves.setCurvePoint(ImageHistogram::ValueChannel, 16, TQPoint(255, 255));
+ }
+ else // 16 bits image.
+ {
+ Curves.setCurvePoint(ImageHistogram::ValueChannel, 0, TQPoint(0, 0));
+ Curves.setCurvePoint(ImageHistogram::ValueChannel, 5, TQPoint(16128, 15360));
+ Curves.setCurvePoint(ImageHistogram::ValueChannel, 10, TQPoint(48896, 49664));
+ Curves.setCurvePoint(ImageHistogram::ValueChannel, 16, TQPoint(65535, 65535));
+ }
+
+ Curves.curvesCalculateCurve(ImageHistogram::AlphaChannel); // Calculate cure on all channels.
+ Curves.curvesLutSetup(ImageHistogram::AlphaChannel); // ... and apply it on all channels
+ Curves.curvesLutProcess(data, dest, w, h);
+
+ memcpy(data, dest, w*h*(sb ? 8 : 4));
+ delete [] dest;
+}
+
+/* Function to apply the Neon effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Intensity => Intensity value
+ * BW => Border Width
+ *
+ * Theory => Wow, this is a great effect, you've never seen a Neon effect
+ * like this on PSC. Is very similar to Growing Edges (photoshop)
+ * Some pictures will be very interesting
+ */
+void ColorFXTool::neon(uchar *data, int w, int h, bool sb, int Intensity, int BW)
+{
+ neonFindEdges(data, w, h, sb, true, Intensity, BW);
+}
+
+/* Function to apply the Find Edges effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Intensity => Intensity value
+ * BW => Border Width
+ *
+ * Theory => Wow, another Photoshop filter (FindEdges). Do you understand
+ * Neon effect ? This is the same engine, but is inversed with
+ * 255 - color.
+ */
+void ColorFXTool::findEdges(uchar *data, int w, int h, bool sb, int Intensity, int BW)
+{
+ neonFindEdges(data, w, h, sb, false, Intensity, BW);
+}
+
+// Implementation of neon and FindEdges. They share 99% of their code.
+void ColorFXTool::neonFindEdges(uchar *data, int w, int h, bool sb, bool neon, int Intensity, int BW)
+{
+ int Width = w;
+ int Height = h;
+ bool sixteenBit = sb;
+ int bytesDepth = sb ? 8 : 4;
+ uchar* pResBits = new uchar[Width*Height*bytesDepth];
+
+ Intensity = (Intensity < 0) ? 0 : (Intensity > 5) ? 5 : Intensity;
+ BW = (BW < 1) ? 1 : (BW > 5) ? 5 : BW;
+
+ uchar *ptr, *ptr1, *ptr2;
+
+ // these must be uint, we need full 2^32 range for 16 bit
+ uint color_1, color_2, colorPoint, colorOther1, colorOther2;
+
+ // initial copy
+ memcpy (pResBits, data, Width*Height*bytesDepth);
+
+ double intensityFactor = sqrt( 1 << Intensity );
+
+ for (int h = 0; h < Height; h++)
+ {
+ for (int w = 0; w < Width; w++)
+ {
+ ptr = pResBits + getOffset(Width, w, h, bytesDepth);
+ ptr1 = pResBits + getOffset(Width, w + Lim_Max (w, BW, Width), h, bytesDepth);
+ ptr2 = pResBits + getOffset(Width, w, h + Lim_Max (h, BW, Height), bytesDepth);
+
+ if (sixteenBit)
+ {
+ for (int k = 0; k <= 2; k++)
+ {
+ colorPoint = ((unsigned short *)ptr)[k];
+ colorOther1 = ((unsigned short *)ptr1)[k];
+ colorOther2 = ((unsigned short *)ptr2)[k];
+ color_1 = (colorPoint - colorOther1) * (colorPoint - colorOther1);
+ color_2 = (colorPoint - colorOther2) * (colorPoint - colorOther2);
+
+ // old algorithm was
+ // sqrt ((color_1 + color_2) << Intensity)
+ // As (a << I) = a * (1 << I) = a * (2^I), and we can split the square root
+
+ if (neon)
+ ((unsigned short *)ptr)[k] = CLAMP065535 ((int)( sqrt((double)color_1 + color_2) * intensityFactor ));
+ else
+ ((unsigned short *)ptr)[k] = 65535 - CLAMP065535 ((int)( sqrt((double)color_1 + color_2) * intensityFactor ));
+ }
+ }
+ else
+ {
+ for (int k = 0; k <= 2; k++)
+ {
+ colorPoint = ptr[k];
+ colorOther1 = ptr1[k];
+ colorOther2 = ptr2[k];
+ color_1 = (colorPoint - colorOther1) * (colorPoint - colorOther1);
+ color_2 = (colorPoint - colorOther2) * (colorPoint - colorOther2);
+
+ if (neon)
+ ptr[k] = CLAMP0255 ((int)( sqrt((double)color_1 + color_2) * intensityFactor ));
+ else
+ ptr[k] = 255 - CLAMP0255 ((int)( sqrt((double)color_1 + color_2) * intensityFactor ));
+ }
+ }
+ }
+ }
+
+ memcpy (data, pResBits, Width*Height*bytesDepth);
+ delete [] pResBits;
+}
+
+int ColorFXTool::getOffset(int Width, int X, int Y, int bytesDepth)
+{
+ return (Y * Width * bytesDepth) + (X * bytesDepth);
+}
+
+inline int ColorFXTool::Lim_Max(int Now, int Up, int Max)
+{
+ --Max;
+ while (Now > Max - Up) --Up;
+ return (Up);
+}
+
+} // NameSpace DigikamColorFXImagesPlugin
+
diff --git a/src/imageplugins/colorfx/colorfxtool.h b/src/imageplugins/colorfx/colorfxtool.h
new file mode 100644
index 00000000..6040f53e
--- /dev/null
+++ b/src/imageplugins/colorfx/colorfxtool.h
@@ -0,0 +1,136 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : a digiKam image plugin for to apply a color
+ * effect to an image.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef COLORFXTOOL_H
+#define COLORFXTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQHButtonGroup;
+class TQComboBox;
+class TQLabel;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class ImageWidget;
+class ColorGradientWidget;
+class HistogramWidget;
+class DColor;
+}
+
+namespace DigikamColorFXImagesPlugin
+{
+
+class ColorFXTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ ColorFXTool(TQObject *parent);
+ ~ColorFXTool();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+ void colorEffect(uchar *data, int w, int h, bool sb);
+ void solarize(int factor, uchar *data, int w, int h, bool sb);
+ void vivid(int factor, uchar *data, int w, int h, bool sb);
+ void neon(uchar *data, int w, int h, bool sb, int Intensity, int BW);
+ void findEdges(uchar *data, int w, int h, bool sb, int Intensity, int BW);
+ void neonFindEdges(uchar *data, int w, int h, bool sb, bool neon, int Intensity, int BW);
+
+ inline int getOffset(int Width, int X, int Y, int bytesDepth);
+ inline int Lim_Max(int Now, int Up, int Max);
+
+private slots:
+
+ void slotEffectTypeChanged(int type);
+ void slotEffect();
+ void slotResetSettings();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum ColorFXTypes
+ {
+ Solarize=0,
+ Vivid,
+ Neon,
+ FindEdges
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ TQLabel *m_effectTypeLabel;
+ TQLabel *m_levelLabel;
+ TQLabel *m_iterationLabel;
+
+ KDcrawIface::RIntNumInput *m_levelInput;
+ KDcrawIface::RIntNumInput *m_iterationInput;
+
+ KDcrawIface::RComboBox *m_effectType;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+};
+
+} // NameSpace DigikamColorFXImagesPlugin
+
+#endif /* COLORFXTOOL_H */
diff --git a/src/imageplugins/colorfx/digikamimageplugin_colorfx.desktop b/src/imageplugins/colorfx/digikamimageplugin_colorfx.desktop
new file mode 100644
index 00000000..7350f6d9
--- /dev/null
+++ b/src/imageplugins/colorfx/digikamimageplugin_colorfx.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Name=ImagePlugin_ColorFx
+Name[fi]=Väriefektit
+Name[it]=PluginImmagini_EffettiDiColore
+Name[nl]=Afbeeldingsplugin_Kleureffecten
+Name[sr]=Ефекти боје
+Name[sr@Latn]=Efekti boje
+Name[sv]=Insticksprogram med färgeffekter
+Name[tr]=ResimEklentisi_RenkFx
+Name[xx]=xxImagePlugin_ColorFxxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Color special effects plugin for digiKam
+Comment[ca]=Connector pel digiKam d'efectes especials de color
+Comment[da]=Digikam plugin med specialeffekter for farve
+Comment[de]=digiKam-Modul zum Erzeugen von speziellen Farbeffekten
+Comment[el]=Πρόσθετο ειδικών εφέ χρώματος για το digiKam
+Comment[es]=Plugin para digiKam con efectos especiales de color
+Comment[et]=DigiKami värvieriefektide plugin
+Comment[fi]=Erikoisia väritehosteita
+Comment[is]=Íforrit fyrir digiKam sem litmeðhöndlar sérstaklega myndir
+Comment[it]=Plugin degli effetti speciali dei colori per digiKam
+Comment[ja]=digiKam 色特殊効果プラグイン
+Comment[nds]=digiKam-Moduul för Klöör-Effekten
+Comment[nl]=Digikam-plugin voor kleureffecten
+Comment[pl]=Wtyczka specjalnych efektów koloru do programu digiKam
+Comment[pt]=Um 'plugin' do digiKam para efeitos especiais de cores
+Comment[pt_BR]=Plugin de efeitos especiais de Cor
+Comment[sk]=digiKam plugin pre špeciálne farebné efekty
+Comment[sr]=Прикључак посебних ефеката боје за digiKam
+Comment[sr@Latn]=Priključak posebnih efekata boje za digiKam
+Comment[sv]=Digikam insticksprogram med specialeffekter för färg
+Comment[tr]=digiKam için özel renk eklentisi
+Comment[uk]=Втулок спецефектів кольорів для digiKam
+Comment[vi]=Phần bổ sung hiệu ứng màu sắc cho digiKam
+Comment[xx]=xxColor special effects plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_colorfx
+author=Caulier Gilles, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/colorfx/digikamimageplugin_colorfx_ui.rc b/src/imageplugins/colorfx/digikamimageplugin_colorfx_ui.rc
new file mode 100644
index 00000000..443a00bd
--- /dev/null
+++ b/src/imageplugins/colorfx/digikamimageplugin_colorfx_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="7" name="digikamimageplugin_colorfx" >
+
+ <MenuBar>
+
+ <Menu name="Color" ><text>&amp;Color</text>
+ <Action name="imageplugin_colorfx" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_colorfx" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/colorfx/imageeffect_colorfx.cpp b/src/imageplugins/colorfx/imageeffect_colorfx.cpp
new file mode 100644
index 00000000..a4ab6fe7
--- /dev/null
+++ b/src/imageplugins/colorfx/imageeffect_colorfx.cpp
@@ -0,0 +1,690 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : a digiKam image plugin for to apply a color
+ * effect to an image.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqvgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqvbox.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <knuminput.h>
+#include <tdelocale.h>
+#include <kcursor.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagecurves.h"
+#include "imagehistogram.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "imageeffect_colorfx.h"
+#include "imageeffect_colorfx.moc"
+
+namespace DigikamColorFXImagesPlugin
+{
+
+ImageEffect_ColorFX::ImageEffect_ColorFX(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent,
+ i18n("Apply Color Special Effects to Photograph"),
+ "coloreffect", false, false)
+{
+ m_destinationPreviewData = 0;
+
+ // About data and help button.
+
+ TDEAboutData *about = new TDEAboutData("digikam",
+ I18N_NOOP("Color Effects"),
+ digikam_version,
+ I18N_NOOP("A digiKam plugin to apply special color effects to an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2005, Renchi Raju\n(c) 2006-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Renchi Raju", I18N_NOOP("Original Author"),
+ "renchi@pooh.tam.uiuc.edu");
+
+ about->addAuthor("Caulier Gilles", I18N_NOOP("Maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new Digikam::ImageWidget("coloreffect Tool Dialog", plainPage(),
+ i18n("<p>This is the color effect preview"));
+
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 9, 4, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ m_effectTypeLabel = new TQLabel(i18n("Type:"), gboxSettings);
+
+ m_effectType = new TQComboBox( false, gboxSettings );
+ m_effectType->insertItem( i18n("Solarize") );
+ m_effectType->insertItem( i18n("Vivid") );
+ m_effectType->insertItem( i18n("Neon") );
+ m_effectType->insertItem( i18n("Find Edges") );
+ TQWhatsThis::add( m_effectType, i18n("<p>Select the effect type to apply to the image here.<p>"
+ "<b>Solarize</b>: simulates solarization of photograph.<p>"
+ "<b>Vivid</b>: simulates the Velvia(tm) slide film colors.<p>"
+ "<b>Neon</b>: coloring the edges in a photograph to "
+ "reproduce a fluorescent light effect.<p>"
+ "<b>Find Edges</b>: detects the edges in a photograph "
+ "and their strength."
+ ));
+ gridSettings->addMultiCellWidget(m_effectTypeLabel, 3, 3, 0, 4);
+ gridSettings->addMultiCellWidget(m_effectType, 4, 4, 0, 4);
+
+ m_levelLabel = new TQLabel(i18n("Level:"), gboxSettings);
+ m_levelInput = new KIntNumInput(gboxSettings);
+ m_levelInput->setRange(0, 100, 1, true);
+ TQWhatsThis::add( m_levelInput, i18n("<p>Set here the level of the effect."));
+
+ gridSettings->addMultiCellWidget(m_levelLabel, 5, 5, 0, 4);
+ gridSettings->addMultiCellWidget(m_levelInput, 6, 6, 0, 4);
+
+ m_iterationLabel = new TQLabel(i18n("Iteration:"), gboxSettings);
+ m_iterationInput = new KIntNumInput(gboxSettings);
+ m_iterationInput->setRange(0, 100, 1, true);
+ TQWhatsThis::add( m_iterationInput, i18n("<p>This value controls the number of iterations "
+ "to use with the Neon and Find Edges effects."));
+
+ gridSettings->addMultiCellWidget(m_iterationLabel, 7, 7, 0, 4);
+ gridSettings->addMultiCellWidget(m_iterationInput, 8, 8, 0, 4);
+
+ gridSettings->setRowStretch(9, 10);
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_levelInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_iterationInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_effectType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffectTypeChanged(int)));
+}
+
+ImageEffect_ColorFX::~ImageEffect_ColorFX()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_previewWidget;
+}
+
+void ImageEffect_ColorFX::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("coloreffect Tool Dialog");
+ m_effectType->setCurrentItem(config->readNumEntry("EffectType", ColorFX));
+ m_levelInput->setValue(config->readNumEntry("LevelAjustment", 0));
+ m_iterationInput->setValue(config->readNumEntry("IterationAjustment", 3));
+ slotEffectTypeChanged(m_effectType->currentItem()); //check for enable/disable of iteration
+}
+
+void ImageEffect_ColorFX::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("coloreffect Tool Dialog");
+ config->writeEntry("EffectType", m_effectType->currentItem());
+ config->writeEntry("LevelAjustment", m_levelInput->value());
+ config->writeEntry("IterationAjustment", m_iterationInput->value());
+ config->sync();
+}
+
+void ImageEffect_ColorFX::resetValues()
+{
+ m_levelInput->setValue(0);
+}
+
+void ImageEffect_ColorFX::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_ColorFX::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_ColorFX::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ImageEffect_ColorFX::slotEffectTypeChanged(int type)
+{
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+
+ m_levelInput->blockSignals(true);
+ m_iterationInput->blockSignals(true);
+ m_levelInput->setRange(0, 100, 1, true);
+ m_levelInput->setValue(25);
+
+ switch (type)
+ {
+ case ColorFX:
+ m_levelInput->setRange(0, 100, 1, true);
+ m_levelInput->setValue(0);
+ m_iterationInput->setEnabled(false);
+ m_iterationLabel->setEnabled(false);
+ break;
+
+ case Vivid:
+ m_levelInput->setRange(0, 50, 1, true);
+ m_levelInput->setValue(5);
+ m_iterationInput->setEnabled(false);
+ m_iterationLabel->setEnabled(false);
+ break;
+
+ case Neon:
+ case FindEdges:
+ m_levelInput->setRange(0, 5, 1, true);
+ m_levelInput->setValue(3);
+ m_iterationInput->setEnabled(true);
+ m_iterationLabel->setEnabled(true);
+ m_iterationInput->setRange(0, 5, 1, true);
+ m_iterationInput->setValue(2);
+ break;
+ }
+
+ m_levelInput->blockSignals(false);
+ m_iterationInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ImageEffect_ColorFX::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ colorEffect(m_destinationPreviewData, w, h, sb);
+
+ iface->putPreviewImage(m_destinationPreviewData);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void ImageEffect_ColorFX::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ if (data)
+ {
+ colorEffect(data, w, h, sb);
+ TQString name;
+
+ switch (m_effectType->currentItem())
+ {
+ case ColorFX:
+ name = i18n("ColorFX");
+ break;
+
+ case Vivid:
+ name = i18n("Vivid");
+ break;
+
+ case Neon:
+ name = i18n("Neon");
+ break;
+
+ case FindEdges:
+ name = i18n("Find Edges");
+ break;
+ }
+
+ iface->putOriginalImage(name, data);
+ delete [] data;
+ }
+
+ kapp->restoreOverrideCursor();
+ accept();
+}
+
+void ImageEffect_ColorFX::colorEffect(uchar *data, int w, int h, bool sb)
+{
+ switch (m_effectType->currentItem())
+ {
+ case ColorFX:
+ solarize(m_levelInput->value(), data, w, h, sb);
+ break;
+
+ case Vivid:
+ vivid(m_levelInput->value(), data, w, h, sb);
+ break;
+
+ case Neon:
+ neon(data, w, h, sb, m_levelInput->value(), m_iterationInput->value());
+ break;
+
+ case FindEdges:
+ findEdges(data, w, h, sb, m_levelInput->value(), m_iterationInput->value());
+ break;
+ }
+}
+
+void ImageEffect_ColorFX::solarize(int factor, uchar *data, int w, int h, bool sb)
+{
+ bool stretch = true;
+
+ if (!sb) // 8 bits image.
+ {
+ uint threshold = (uint)((100-factor)*(255+1)/100);
+ threshold = TQMAX(1, threshold);
+ uchar *ptr = data;
+ uchar a, r, g, b;
+
+ for (int x=0 ; x < w*h ; x++)
+ {
+ b = ptr[0];
+ g = ptr[1];
+ r = ptr[2];
+ a = ptr[3];
+
+ if (stretch)
+ {
+ r = (r > threshold) ? (255-r)*255/(255-threshold) : r*255/threshold;
+ g = (g > threshold) ? (255-g)*255/(255-threshold) : g*255/threshold;
+ b = (b > threshold) ? (255-b)*255/(255-threshold) : b*255/threshold;
+ }
+ else
+ {
+ if (r > threshold)
+ r = (255-r);
+ if (g > threshold)
+ g = (255-g);
+ if (b > threshold)
+ b = (255-b);
+ }
+
+ ptr[0] = b;
+ ptr[1] = g;
+ ptr[2] = r;
+ ptr[3] = a;
+
+ ptr += 4;
+ }
+ }
+ else // 16 bits image.
+ {
+ uint threshold = (uint)((100-factor)*(65535+1)/100);
+ threshold = TQMAX(1, threshold);
+ unsigned short *ptr = (unsigned short *)data;
+ unsigned short a, r, g, b;
+
+ for (int x=0 ; x < w*h ; x++)
+ {
+ b = ptr[0];
+ g = ptr[1];
+ r = ptr[2];
+ a = ptr[3];
+
+ if (stretch)
+ {
+ r = (r > threshold) ? (65535-r)*65535/(65535-threshold) : r*65535/threshold;
+ g = (g > threshold) ? (65535-g)*65535/(65535-threshold) : g*65535/threshold;
+ b = (b > threshold) ? (65535-b)*65535/(65535-threshold) : b*65535/threshold;
+ }
+ else
+ {
+ if (r > threshold)
+ r = (65535-r);
+ if (g > threshold)
+ g = (65535-g);
+ if (b > threshold)
+ b = (65535-b);
+ }
+
+ ptr[0] = b;
+ ptr[1] = g;
+ ptr[2] = r;
+ ptr[3] = a;
+
+ ptr += 4;
+ }
+ }
+}
+
+void ImageEffect_ColorFX::vivid(int factor, uchar *data, int w, int h, bool sb)
+{
+ float amount = factor/100.0;
+
+ Digikam::DImgImageFilters filter;
+
+ // Apply Channel Mixer adjustments.
+
+ filter.channelMixerImage(
+ data, w, h, sb, // Image data.
+ true, // Preserve Luminosity
+ false, // Disable Black & White mode.
+ 1.0 + amount + amount, (-1.0)*amount, (-1.0)*amount, // Red Gains.
+ (-1.0)*amount, 1.0 + amount + amount, (-1.0)*amount, // Green Gains.
+ (-1.0)*amount, (-1.0)*amount, 1.0 + amount + amount // Blue Gains.
+ );
+
+ // Allocate the destination image data.
+
+ uchar *dest = new uchar[w*h*(sb ? 8 : 4)];
+
+ // And now apply the curve correction.
+
+ Digikam::ImageCurves Curves(sb);
+
+ if (!sb) // 8 bits image.
+ {
+ Curves.setCurvePoint(Digikam::ImageHistogram::ValueChannel, 0, TQPoint(0, 0));
+ Curves.setCurvePoint(Digikam::ImageHistogram::ValueChannel, 5, TQPoint(63, 60));
+ Curves.setCurvePoint(Digikam::ImageHistogram::ValueChannel, 10, TQPoint(191, 194));
+ Curves.setCurvePoint(Digikam::ImageHistogram::ValueChannel, 16, TQPoint(255, 255));
+ }
+ else // 16 bits image.
+ {
+ Curves.setCurvePoint(Digikam::ImageHistogram::ValueChannel, 0, TQPoint(0, 0));
+ Curves.setCurvePoint(Digikam::ImageHistogram::ValueChannel, 5, TQPoint(16128, 15360));
+ Curves.setCurvePoint(Digikam::ImageHistogram::ValueChannel, 10, TQPoint(48896, 49664));
+ Curves.setCurvePoint(Digikam::ImageHistogram::ValueChannel, 16, TQPoint(65535, 65535));
+ }
+
+ Curves.curvesCalculateCurve(Digikam::ImageHistogram::AlphaChannel); // Calculate cure on all channels.
+ Curves.curvesLutSetup(Digikam::ImageHistogram::AlphaChannel); // ... and apply it on all channels
+ Curves.curvesLutProcess(data, dest, w, h);
+
+ memcpy(data, dest, w*h*(sb ? 8 : 4));
+ delete [] dest;
+}
+
+/* Function to apply the Neon effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Intensity => Intensity value
+ * BW => Border Width
+ *
+ * Theory => Wow, this is a great effect, you've never seen a Neon effect
+ * like this on PSC. Is very similar to Growing Edges (photoshop)
+ * Some pictures will be very interesting
+ */
+void ImageEffect_ColorFX::neon(uchar *data, int w, int h, bool sb, int Intensity, int BW)
+{
+ neonFindEdges(data, w, h, sb, true, Intensity, BW);
+}
+
+/* Function to apply the Find Edges effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Intensity => Intensity value
+ * BW => Border Width
+ *
+ * Theory => Wow, another Photoshop filter (FindEdges). Do you understand
+ * Neon effect ? This is the same engine, but is inversed with
+ * 255 - color.
+ */
+void ImageEffect_ColorFX::findEdges(uchar *data, int w, int h, bool sb, int Intensity, int BW)
+{
+ neonFindEdges(data, w, h, sb, false, Intensity, BW);
+}
+
+// Implementation of neon and FindEdges. They share 99% of their code.
+void ImageEffect_ColorFX::neonFindEdges(uchar *data, int w, int h, bool sb, bool neon, int Intensity, int BW)
+{
+ int Width = w;
+ int Height = h;
+ bool sixteenBit = sb;
+ int bytesDepth = sb ? 8 : 4;
+ uchar* pResBits = new uchar[Width*Height*bytesDepth];
+
+ Intensity = (Intensity < 0) ? 0 : (Intensity > 5) ? 5 : Intensity;
+ BW = (BW < 1) ? 1 : (BW > 5) ? 5 : BW;
+
+ uchar *ptr, *ptr1, *ptr2;
+
+ // these must be uint, we need full 2^32 range for 16 bit
+ uint color_1, color_2, colorPoint, colorOther1, colorOther2;
+
+ // initial copy
+ memcpy (pResBits, data, Width*Height*bytesDepth);
+
+ double intensityFactor = sqrt( 1 << Intensity );
+
+ for (int h = 0; h < Height; h++)
+ {
+ for (int w = 0; w < Width; w++)
+ {
+ ptr = pResBits + getOffset(Width, w, h, bytesDepth);
+ ptr1 = pResBits + getOffset(Width, w + Lim_Max (w, BW, Width), h, bytesDepth);
+ ptr2 = pResBits + getOffset(Width, w, h + Lim_Max (h, BW, Height), bytesDepth);
+
+ if (sixteenBit)
+ {
+ for (int k = 0; k <= 2; k++)
+ {
+ colorPoint = ((unsigned short *)ptr)[k];
+ colorOther1 = ((unsigned short *)ptr1)[k];
+ colorOther2 = ((unsigned short *)ptr2)[k];
+ color_1 = (colorPoint - colorOther1) * (colorPoint - colorOther1);
+ color_2 = (colorPoint - colorOther2) * (colorPoint - colorOther2);
+
+ // old algorithm was
+ // sqrt ((color_1 + color_2) << Intensity)
+ // As (a << I) = a * (1 << I) = a * (2^I), and we can split the square root
+
+ if (neon)
+ ((unsigned short *)ptr)[k] = CLAMP065535 ((int)( sqrt(color_1 + color_2) * intensityFactor ));
+ else
+ ((unsigned short *)ptr)[k] = 65535 - CLAMP065535 ((int)( sqrt(color_1 + color_2) * intensityFactor ));
+ }
+ }
+ else
+ {
+ for (int k = 0; k <= 2; k++)
+ {
+ colorPoint = ptr[k];
+ colorOther1 = ptr1[k];
+ colorOther2 = ptr2[k];
+ color_1 = (colorPoint - colorOther1) * (colorPoint - colorOther1);
+ color_2 = (colorPoint - colorOther2) * (colorPoint - colorOther2);
+
+ if (neon)
+ ptr[k] = CLAMP0255 ((int)( sqrt(color_1 + color_2) * intensityFactor ));
+ else
+ ptr[k] = 255 - CLAMP0255 ((int)( sqrt(color_1 + color_2) * intensityFactor ));
+ }
+ }
+ }
+ }
+
+ memcpy (data, pResBits, Width*Height*bytesDepth);
+ delete [] pResBits;
+}
+
+int ImageEffect_ColorFX::getOffset(int Width, int X, int Y, int bytesDepth)
+{
+ return (Y * Width * bytesDepth) + (X * bytesDepth);
+}
+
+inline int ImageEffect_ColorFX::Lim_Max(int Now, int Up, int Max)
+{
+ --Max;
+ while (Now > Max - Up) --Up;
+ return (Up);
+}
+
+} // NameSpace DigikamColorFXImagesPlugin
+
diff --git a/src/imageplugins/colorfx/imageeffect_colorfx.h b/src/imageplugins/colorfx/imageeffect_colorfx.h
new file mode 100644
index 00000000..d6d7d105
--- /dev/null
+++ b/src/imageplugins/colorfx/imageeffect_colorfx.h
@@ -0,0 +1,131 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : a digiKam image plugin for to apply a color
+ * effect to an image.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_COLORFX_H
+#define IMAGEEFFECT_COLORFX_H
+
+// Digikam includes.
+
+#include "imagedlgbase.h"
+
+class TQHButtonGroup;
+class TQComboBox;
+class TQLabel;
+
+class KIntNumInput;
+
+namespace Digikam
+{
+class ImageWidget;
+class ColorGradientWidget;
+class HistogramWidget;
+class DColor;
+}
+
+namespace DigikamColorFXImagesPlugin
+{
+
+class ImageEffect_ColorFX : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_ColorFX(TQWidget *parent);
+ ~ImageEffect_ColorFX();
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void finalRendering();
+ void colorEffect(uchar *data, int w, int h, bool sb);
+ void solarize(int factor, uchar *data, int w, int h, bool sb);
+ void vivid(int factor, uchar *data, int w, int h, bool sb);
+ void neon(uchar *data, int w, int h, bool sb, int Intensity, int BW);
+ void findEdges(uchar *data, int w, int h, bool sb, int Intensity, int BW);
+ void neonFindEdges(uchar *data, int w, int h, bool sb, bool neon, int Intensity, int BW);
+
+ inline int getOffset(int Width, int X, int Y, int bytesDepth);
+ inline int Lim_Max(int Now, int Up, int Max);
+
+private slots:
+
+ void slotEffectTypeChanged(int type);
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum ColorFXTypes
+ {
+ ColorFX=0,
+ Vivid,
+ Neon,
+ FindEdges
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+ TQComboBox *m_effectType;
+
+ TQHButtonGroup *m_scaleBG;
+
+ TQLabel *m_effectTypeLabel;
+ TQLabel *m_levelLabel;
+ TQLabel *m_iterationLabel;
+
+ KIntNumInput *m_levelInput;
+ KIntNumInput *m_iterationInput;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+};
+
+} // NameSpace DigikamColorFXImagesPlugin
+
+#endif /* IMAGEEFFECT_COLORFX_H */
diff --git a/src/imageplugins/colorfx/imageplugin_colorfx.cpp b/src/imageplugins/colorfx/imageplugin_colorfx.cpp
new file mode 100644
index 00000000..f4725028
--- /dev/null
+++ b/src/imageplugins/colorfx/imageplugin_colorfx.cpp
@@ -0,0 +1,73 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : a digiKam image plugin for to apply a color
+ * effect to an image.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "colorfxtool.h"
+#include "imageplugin_colorfx.h"
+#include "imageplugin_colorfx.moc"
+
+using namespace DigikamColorFXImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_colorfx,
+ KGenericFactory<ImagePlugin_ColorFX>("digikamimageplugin_colorfx"));
+
+ImagePlugin_ColorFX::ImagePlugin_ColorFX(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_ColorFX")
+{
+ m_solarizeAction = new TDEAction(i18n("Color Effects..."), "colorfx", 0,
+ this, TQ_SLOT(slotColorFX()),
+ actionCollection(), "imageplugin_colorfx");
+
+ setXMLFile( "digikamimageplugin_colorfx_ui.rc" );
+
+ DDebug() << "ImagePlugin_ColorFX plugin loaded" << endl;
+}
+
+ImagePlugin_ColorFX::~ImagePlugin_ColorFX()
+{
+}
+
+void ImagePlugin_ColorFX::setEnabledActions(bool enable)
+{
+ m_solarizeAction->setEnabled(enable);
+}
+
+void ImagePlugin_ColorFX::slotColorFX()
+{
+ ColorFXTool *colorfx = new ColorFXTool(this);
+ loadTool(colorfx);
+}
+
diff --git a/src/imageplugins/colorfx/imageplugin_colorfx.h b/src/imageplugins/colorfx/imageplugin_colorfx.h
new file mode 100644
index 00000000..d7aaa83f
--- /dev/null
+++ b/src/imageplugins/colorfx/imageplugin_colorfx.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-02-14
+ * Description : a digiKam image plugin for to apply a color
+ * effect to an image.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_COLORFX_H
+#define IMAGEPLUGIN_COLORFX_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_ColorFX : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_ColorFX(TQObject *parent, const char* name, const TQStringList &args);
+ ~ImagePlugin_ColorFX();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotColorFX();
+
+private:
+
+ TDEAction *m_solarizeAction;
+};
+
+#endif /* IMAGEPLUGIN_COLORFX_H */
diff --git a/src/imageplugins/coreplugin/Makefile.am b/src/imageplugins/coreplugin/Makefile.am
new file mode 100644
index 00000000..b36d6f36
--- /dev/null
+++ b/src/imageplugins/coreplugin/Makefile.am
@@ -0,0 +1,52 @@
+SUBDIRS = sharpnesseditor hsl ratiocrop
+COMPILE_FIRST = sharpnesseditor hsl ratiocrop
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/imageplugins/coreplugin/sharpnesseditor \
+ -I$(top_srcdir)/src/imageplugins/coreplugin/hsl \
+ -I$(top_srcdir)/src/imageplugins/coreplugin/ratiocrop \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_core_la_SOURCES = imageplugin_core.cpp bwsepiatool.cpp \
+ autocorrectiontool.cpp \
+ rgbtool.cpp \
+ redeyetool.cpp blurtool.cpp \
+ iccprooftool.cpp bcgtool.cpp
+
+noinst_HEADERS = autocorrectiontool.h blurtool.h \
+ rgbtool.h bcgtool.h \
+ bwsepiatool.h iccprooftool.h redeyetool.h
+
+digikamimageplugin_core_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/imageplugins/coreplugin/sharpnesseditor/libsharpnesseditor.la \
+ $(top_builddir)/src/imageplugins/coreplugin/hsl/libhsl.la \
+ $(top_builddir)/src/imageplugins/coreplugin/ratiocrop/libratiocrop.la \
+ $(top_builddir)/src/digikam/libdigikam.la \
+ $(top_builddir)/src/utilities/imageeditor/editor/libdimgeditor.la \
+ $(top_builddir)/src/libs/curves/libcurves.la \
+ $(top_builddir)/src/libs/widgets/common/libcommonwidgets.la \
+ $(top_builddir)/src/libs/widgets/imageplugins/libimagepluginswidgets.la
+
+digikamimageplugin_core_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio -lkexiv2 -ltdeutils
+
+kde_services_DATA = digikamimageplugin_core.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_core.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_core_ui.rc
diff --git a/src/imageplugins/coreplugin/autocorrectiontool.cpp b/src/imageplugins/coreplugin/autocorrectiontool.cpp
new file mode 100644
index 00000000..32f00b44
--- /dev/null
+++ b/src/imageplugins/coreplugin/autocorrectiontool.cpp
@@ -0,0 +1,438 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-31
+ * Description : Auto-Color correction tool.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqframe.h>
+#include <tqgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqhgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqlistbox.h>
+#include <tqpushbutton.h>
+#include <tqradiobutton.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// Digikam includes.
+
+#include "colorgradientwidget.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "listboxpreviewitem.h"
+#include "whitebalance.h"
+
+// Local includes.
+
+#include "autocorrectiontool.h"
+#include "autocorrectiontool.moc"
+
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+AutoCorrectionTool::AutoCorrectionTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("autocorrection");
+ setToolName(i18n("Auto-Correction"));
+ setToolIcon(SmallIcon("autocorrection"));
+ setToolHelp("autocolorcorrectiontool.anchor");
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImageWidget("autocorrection Tool", 0,
+ i18n("<p>Here you can see the auto-color correction tool "
+ "preview. You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ ImageIface iface(0, 0);
+ m_thumbnailImage = iface.getOriginalImg()->smoothScale(128, 128, TQSize::ScaleMin);
+ m_destinationPreviewData = 0;
+
+ EditorToolSettings *gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings->plainPage(), 2, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings->plainPage());
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings->plainPage() );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(linHistoButton, i18n("<p>Linear"));
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(logHistoButton, i18n("<p>Logarithmic"));
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap(TQPixmap(directory + "histogram-log.png"));
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal, 10, histoBox);
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ // -------------------------------------------------------------
+
+ m_correctionTools = new TQListBox(gboxSettings->plainPage());
+ m_correctionTools->setColumnMode(1);
+ m_correctionTools->setVariableWidth(false);
+ m_correctionTools->setVariableHeight(false);
+ ListBoxWhatsThis* whatsThis = new ListBoxWhatsThis(m_correctionTools);
+
+ TQPixmap pix = getThumbnailForEffect(AutoLevelsCorrection);
+ ListBoxPreviewItem *item = new ListBoxPreviewItem(pix, i18n("Auto Levels"));
+ whatsThis->add( item, i18n("<b>Auto Levels</b>:"
+ "<p>This option maximizes the tonal range in the Red, "
+ "Green, and Blue channels. It searches the image shadow and highlight "
+ "limit values and adjusts the Red, Green, and Blue channels "
+ "to a full histogram range.</p>"));
+ m_correctionTools->insertItem(item, AutoLevelsCorrection);
+
+ pix = getThumbnailForEffect(NormalizeCorrection);
+ item = new ListBoxPreviewItem(pix, i18n("Normalize"));
+ whatsThis->add( item, i18n("<b>Normalize</b>:"
+ "<p>This option scales brightness values across the active "
+ "image so that the darkest point becomes black, and the "
+ "brightest point becomes as bright as possible without "
+ "altering its hue. This is often a \"magic fix\" for "
+ "images that are dim or washed out.</p>"));
+ m_correctionTools->insertItem(item, NormalizeCorrection);
+
+ pix = getThumbnailForEffect(EqualizeCorrection);
+ item = new ListBoxPreviewItem(pix, i18n("Equalize"));
+ whatsThis->add( item, i18n("<b>Equalize</b>:"
+ "<p>This option adjusts the brightness of colors across the "
+ "active image so that the histogram for the value channel "
+ "is as nearly as possible flat, that is, so that each possible "
+ "brightness value appears at about the same number of pixels "
+ "as each other value. Sometimes Equalize works wonderfully at "
+ "enhancing the contrasts in an image. Other times it gives "
+ "garbage. It is a very powerful operation, which can either work "
+ "miracles on an image or destroy it.</p>"));
+ m_correctionTools->insertItem(item, EqualizeCorrection);
+
+ pix = getThumbnailForEffect(StretchContrastCorrection);
+ item = new ListBoxPreviewItem(pix, i18n("Stretch Contrast"));
+ whatsThis->add( item, i18n("<b>Stretch Contrast</b>:"
+ "<p>This option enhances the contrast and brightness "
+ "of the RGB values of an image by stretching the lowest "
+ "and highest values to their fullest range, adjusting "
+ "everything in between.</p>"));
+ m_correctionTools->insertItem(item, StretchContrastCorrection);
+
+ pix = getThumbnailForEffect(AutoExposureCorrection);
+ item = new ListBoxPreviewItem(pix, i18n("Auto Exposure"));
+ whatsThis->add( item, i18n("<b>Auto Exposure</b>:"
+ "<p>This option enhances the contrast and brightness "
+ "of the RGB values of an image to calculate optimal "
+ "exposition and black level using image histogram "
+ "properties.</p>"));
+ m_correctionTools->insertItem(item, AutoExposureCorrection);
+
+ // -------------------------------------------------------------
+
+ m_correctionTools->setFocus();
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+ gridSettings->addMultiCellWidget(histoBox, 1, 1, 0, 4);
+ gridSettings->addMultiCellWidget(m_correctionTools, 2, 2, 0, 4);
+ gridSettings->setRowStretch(2, 10);
+ gridSettings->setSpacing(gboxSettings->spacingHint());
+ gridSettings->setMargin(gboxSettings->spacingHint());
+
+ setToolSettings(gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget(const DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotColorSelectedFromTarget(const DColor&)));
+
+ connect(m_correctionTools, TQ_SIGNAL(highlighted(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+}
+
+AutoCorrectionTool::~AutoCorrectionTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void AutoCorrectionTool::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void AutoCorrectionTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void AutoCorrectionTool::slotColorSelectedFromTarget(const DColor& color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void AutoCorrectionTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("autocorrection Tool");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+ m_correctionTools->setCurrentItem(config->readNumEntry("Auto Correction Filter", AutoLevelsCorrection));
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void AutoCorrectionTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("autocorrection Tool");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("Auto Correction Filter", m_correctionTools->currentItem());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void AutoCorrectionTool::slotResetSettings()
+{
+ m_correctionTools->blockSignals(true);
+ m_correctionTools->setCurrentItem(AutoLevelsCorrection);
+ m_correctionTools->blockSignals(false);
+
+ slotEffect();
+}
+
+void AutoCorrectionTool::slotEffect()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ autoCorrection(m_destinationPreviewData, w, h, sb, m_correctionTools->currentItem());
+
+ iface->putPreviewImage(m_destinationPreviewData);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+TQPixmap AutoCorrectionTool::getThumbnailForEffect(AutoCorrectionType type)
+{
+ DImg thumb = m_thumbnailImage.copy();
+ autoCorrection(thumb.bits(), thumb.width(), thumb.height(), thumb.sixteenBit(), type);
+ return (thumb.convertToPixmap());
+}
+
+
+void AutoCorrectionTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ if (data)
+ {
+ int type = m_correctionTools->currentItem();
+ autoCorrection(data, w, h, sb, type);
+ TQString name;
+
+ switch (type)
+ {
+ case AutoLevelsCorrection:
+ name = i18n("Auto Levels");
+ break;
+
+ case NormalizeCorrection:
+ name = i18n("Normalize");
+ break;
+
+ case EqualizeCorrection:
+ name = i18n("Equalize");
+ break;
+
+ case StretchContrastCorrection:
+ name = i18n("Stretch Contrast");
+ break;
+
+ case AutoExposureCorrection:
+ name = i18n("Auto Exposure");
+ break;
+ }
+
+ iface->putOriginalImage(name, data);
+ delete [] data;
+ }
+
+ kapp->restoreOverrideCursor();
+}
+
+void AutoCorrectionTool::autoCorrection(uchar *data, int w, int h, bool sb, int type)
+{
+ DImgImageFilters filter;
+
+ switch (type)
+ {
+ case AutoLevelsCorrection:
+ filter.autoLevelsCorrectionImage(data, w, h, sb);
+ break;
+
+ case NormalizeCorrection:
+ filter.normalizeImage(data, w, h, sb);
+ break;
+
+ case EqualizeCorrection:
+ filter.equalizeImage(data, w, h, sb);
+ break;
+
+ case StretchContrastCorrection:
+ filter.stretchContrastImage(data, w, h, sb);
+ break;
+
+ case AutoExposureCorrection:
+ WhiteBalance wbFilter(sb);
+ double blackLevel;
+ double exposureLevel;
+ wbFilter.autoExposureAdjustement(data, w, h, sb, blackLevel, exposureLevel);
+ wbFilter.whiteBalance(data, w, h, sb, blackLevel, exposureLevel);
+ break;
+ }
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/autocorrectiontool.h b/src/imageplugins/coreplugin/autocorrectiontool.h
new file mode 100644
index 00000000..73a388f2
--- /dev/null
+++ b/src/imageplugins/coreplugin/autocorrectiontool.h
@@ -0,0 +1,128 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-31
+ * Description : Auto-Color correction tool.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef AUTOCORRECTIONTOOL_H
+#define AUTOCORRECTIONTOOL_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQHButtonGroup;
+class TQComboBox;
+class TQListBox;
+class TQButtonGroup;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+class DImg;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class AutoCorrectionTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ AutoCorrectionTool(TQObject *parent);
+ ~AutoCorrectionTool();
+
+protected:
+
+ void finalRendering();
+
+private slots:
+
+ void slotEffect();
+ void slotResetSettings();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+
+private:
+
+ enum AutoCorrectionType
+ {
+ AutoLevelsCorrection=0,
+ NormalizeCorrection,
+ EqualizeCorrection,
+ StretchContrastCorrection,
+ AutoExposureCorrection
+ };
+
+private:
+
+ void readSettings();
+ void writeSettings();
+
+ void autoCorrection(uchar *data, int w, int h, bool sb, int type);
+ TQPixmap getThumbnailForEffect(AutoCorrectionType type);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ TQListBox *m_correctionTools;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::DImg m_thumbnailImage;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* AUTOCORRECTIONTOOL_H */
diff --git a/src/imageplugins/coreplugin/bcgtool.cpp b/src/imageplugins/coreplugin/bcgtool.cpp
new file mode 100644
index 00000000..17ecf838
--- /dev/null
+++ b/src/imageplugins/coreplugin/bcgtool.cpp
@@ -0,0 +1,366 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-05
+ * Description : digiKam image editor to adjust Brightness,
+ Contrast, and Gamma of picture.
+ *
+ * Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqframe.h>
+#include <tqgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqhgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Digikam includes.
+
+#include "bcgmodifier.h"
+#include "colorgradientwidget.h"
+#include "dimg.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+
+// Local includes.
+
+#include "bcgtool.h"
+#include "bcgtool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+BCGTool::BCGTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("bcgadjust");
+ setToolName(i18n("Brightness / Contrast / Gamma"));
+ setToolIcon(SmallIcon("contrast"));
+ setToolHelp("bcgadjusttool.anchor");
+
+ m_destinationPreviewData = 0;
+
+ m_previewWidget = new ImageWidget("bcgadjust Tool", 0,
+ i18n("<p>Here you can see the image "
+ "brightness-contrast-gamma adjustments preview. "
+ "You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* gridSettings = new TQGridLayout(m_gboxSettings->plainPage(), 9, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), m_gboxSettings->plainPage());
+ label1->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+ m_channelCB = new TQComboBox(false, m_gboxSettings->plainPage());
+ m_channelCB->insertItem(i18n("Luminosity"));
+ m_channelCB->insertItem(i18n("Red"));
+ m_channelCB->insertItem(i18n("Green"));
+ m_channelCB->insertItem(i18n("Blue"));
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin(0);
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(linHistoButton, i18n("<p>Linear"));
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap(TQPixmap(directory + "histogram-lin.png"));
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(logHistoButton, i18n("<p>Logarithmic"));
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap(TQPixmap(directory + "histogram-log.png"));
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(m_gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal, 10, histoBox);
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Brightness:"), m_gboxSettings->plainPage());
+ m_bInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_bInput->setRange(-100, 100, 1);
+ m_bInput->setDefaultValue(0);
+ TQWhatsThis::add( m_bInput, i18n("<p>Set here the brightness adjustment of the image."));
+
+ TQLabel *label3 = new TQLabel(i18n("Contrast:"), m_gboxSettings->plainPage());
+ m_cInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_cInput->setRange(-100, 100, 1);
+ m_cInput->setDefaultValue(0);
+ TQWhatsThis::add( m_cInput, i18n("<p>Set here the contrast adjustment of the image."));
+
+ TQLabel *label4 = new TQLabel(i18n("Gamma:"), m_gboxSettings->plainPage());
+ m_gInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_gInput->setPrecision(2);
+ m_gInput->setRange(0.1, 3.0, 0.01);
+ m_gInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_gInput, i18n("<p>Set here the gamma adjustment of the image."));
+
+ // -------------------------------------------------------------
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+ gridSettings->addMultiCellWidget(label2, 3, 3, 0, 4);
+ gridSettings->addMultiCellWidget(m_bInput, 4, 4, 0, 4);
+ gridSettings->addMultiCellWidget(label3, 5, 5, 0, 4);
+ gridSettings->addMultiCellWidget(m_cInput, 6, 6, 0, 4);
+ gridSettings->addMultiCellWidget(label4, 7, 7, 0, 4);
+ gridSettings->addMultiCellWidget(m_gInput, 8, 8, 0, 4);
+ gridSettings->setRowStretch(9, 10);
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_bInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_cInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings->enableButton(EditorToolSettings::Ok, false);
+}
+
+BCGTool::~BCGTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void BCGTool::slotChannelChanged(int channel)
+{
+ switch (channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("red"));
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("green"));
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("blue"));
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void BCGTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void BCGTool::slotColorSelectedFromTarget(const DColor &color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void BCGTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("bcgadjust Tool");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+ m_bInput->setValue(config->readNumEntry("BrightnessAjustment", m_bInput->defaultValue()));
+ m_cInput->setValue(config->readNumEntry("ContrastAjustment", m_cInput->defaultValue()));
+ m_gInput->setValue(config->readDoubleNumEntry("GammaAjustment", m_gInput->defaultValue()));
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void BCGTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("bcgadjust Tool");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("BrightnessAjustment", m_bInput->value());
+ config->writeEntry("ContrastAjustment", m_cInput->value());
+ config->writeEntry("GammaAjustment", m_gInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void BCGTool::slotResetSettings()
+{
+ m_bInput->blockSignals(true);
+ m_cInput->blockSignals(true);
+ m_gInput->blockSignals(true);
+
+ m_bInput->slotReset();
+ m_cInput->slotReset();
+ m_gInput->slotReset();
+
+ m_bInput->blockSignals(false);
+ m_cInput->blockSignals(false);
+ m_gInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void BCGTool::slotEffect()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+
+ double b = (double) m_bInput->value() / 250.0;
+ double c = (double) (m_cInput->value() / 100.0) + 1.00;
+ double g = m_gInput->value();
+
+ m_gboxSettings->enableButton(EditorToolSettings::Ok,
+ ( b != 0.0 || c != 1.0 || g != 1.0 ));
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool a = iface->previewHasAlpha();
+ bool sb = iface->previewSixteenBit();
+
+ DImg preview(w, h, sb, a, m_destinationPreviewData);
+ BCGModifier cmod;
+ cmod.setGamma(g);
+ cmod.setBrightness(b);
+ cmod.setContrast(c);
+ cmod.applyBCG(preview);
+ iface->putPreviewImage(preview.bits());
+
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, preview.bits(), preview.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void BCGTool::finalRendering()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+ ImageIface* iface = m_previewWidget->imageIface();
+
+ double b = (double) m_bInput->value() / 250.0;
+ double c = (double) (m_cInput->value() / 100.0) + 1.00;
+ double g = m_gInput->value();
+
+ iface->setOriginalBCG(b, c, g);
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/bcgtool.h b/src/imageplugins/coreplugin/bcgtool.h
new file mode 100644
index 00000000..4a1e9d21
--- /dev/null
+++ b/src/imageplugins/coreplugin/bcgtool.h
@@ -0,0 +1,115 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-05
+ * Description : digiKam image editor to adjust Brightness,
+ Contrast, and Gamma of picture.
+ *
+ * Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef BCGTOOL_H
+#define BCGTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQCheckBox;
+class TQComboBox;
+class TQHButtonGroup;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RDoubleNumInput;
+}
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class BCGTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ BCGTool(TQObject *parent);
+ ~BCGTool();
+
+private slots:
+
+ void slotEffect();
+ void slotResetSettings();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget( const Digikam::DColor &color );
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ KDcrawIface::RIntNumInput *m_bInput;
+ KDcrawIface::RIntNumInput *m_cInput;
+ KDcrawIface::RDoubleNumInput *m_gInput;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* BCGTOOL_H */
diff --git a/src/imageplugins/coreplugin/blurtool.cpp b/src/imageplugins/coreplugin/blurtool.cpp
new file mode 100644
index 00000000..85e1dc19
--- /dev/null
+++ b/src/imageplugins/coreplugin/blurtool.cpp
@@ -0,0 +1,169 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-09
+ * Description : a tool to blur an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+
+// Digikam includes.
+
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "dimggaussianblur.h"
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "blurtool.h"
+#include "blurtool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+BlurTool::BlurTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("gaussianblur");
+ setToolName(i18n("Blur"));
+ setToolIcon(SmallIcon("blurimage"));
+ setToolHelp("blursharpentool.anchor");
+
+ // ---------------------------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 2, 1);
+ TQLabel *label = new TQLabel(i18n("Smoothness:"), m_gboxSettings->plainPage());
+
+ m_radiusInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_radiusInput->setRange(0, 100, 1);
+ m_radiusInput->setDefaultValue(0);
+ TQWhatsThis::add(m_radiusInput, i18n("<p>A smoothness of 0 has no effect, "
+ "1 and above determine the Gaussian blur matrix radius "
+ "that determines how much to blur the image."));
+
+ grid->addMultiCellWidget(label, 0, 0, 0, 1);
+ grid->addMultiCellWidget(m_radiusInput, 1, 1, 0, 1);
+ grid->setRowStretch(2, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "gaussianblur Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+}
+
+BlurTool::~BlurTool()
+{
+}
+
+void BlurTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("gaussianblur Tool");
+ m_radiusInput->setValue(config->readNumEntry("RadiusAjustment", m_radiusInput->defaultValue()));
+}
+
+void BlurTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("gaussianblur Tool");
+ config->writeEntry("RadiusAjustment", m_radiusInput->value());
+ config->sync();
+}
+
+void BlurTool::slotResetSettings()
+{
+ m_radiusInput->blockSignals(true);
+ m_radiusInput->slotReset();
+ m_radiusInput->blockSignals(false);
+}
+
+void BlurTool::prepareEffect()
+{
+ m_radiusInput->setEnabled(false);
+
+ DImg img = m_previewWidget->getOriginalRegionImage();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new DImgGaussianBlur(&img, this, m_radiusInput->value())));
+}
+
+void BlurTool::prepareFinal()
+{
+ m_radiusInput->setEnabled(false);
+
+ ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sixteenBit = iface.originalSixteenBit();
+ bool hasAlpha = iface.originalHasAlpha();
+ DImg orgImage = DImg(w, h, sixteenBit, hasAlpha ,data);
+ delete [] data;
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new DImgGaussianBlur(&orgImage, this, m_radiusInput->value())));
+}
+
+void BlurTool::putPreviewData()
+{
+ DImg imDest = filter()->getTargetImage();
+ m_previewWidget->setPreviewImage(imDest);
+}
+
+void BlurTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ DImg imDest = filter()->getTargetImage();
+ iface.putOriginalImage(i18n("Gaussian Blur"), imDest.bits());
+}
+
+void BlurTool::renderingFinished()
+{
+ m_radiusInput->setEnabled(true);
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/blurtool.h b/src/imageplugins/coreplugin/blurtool.h
new file mode 100644
index 00000000..545f4aa2
--- /dev/null
+++ b/src/imageplugins/coreplugin/blurtool.h
@@ -0,0 +1,81 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-09
+ * Description : a tool to blur an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_BLUR_H
+#define IMAGEEFFECT_BLUR_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class BlurTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ BlurTool(TQObject *parent);
+ ~BlurTool();
+
+private slots:
+
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KDcrawIface::RIntNumInput *m_radiusInput;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_BLUR_H */
diff --git a/src/imageplugins/coreplugin/bwsepiatool.cpp b/src/imageplugins/coreplugin/bwsepiatool.cpp
new file mode 100644
index 00000000..06c30462
--- /dev/null
+++ b/src/imageplugins/coreplugin/bwsepiatool.cpp
@@ -0,0 +1,1177 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-06
+ * Description : Black and White conversion tool.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqfile.h>
+#include <tqframe.h>
+#include <tqgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqhgroupbox.h>
+#include <tqintdict.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqlistbox.h>
+#include <tqpushbutton.h>
+#include <tqtextstream.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kstandarddirs.h>
+#include <ktabwidget.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Digikam includes.
+
+#include "bcgmodifier.h"
+#include "colorgradientwidget.h"
+#include "curveswidget.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "imagecurves.h"
+#include "imagehistogram.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "listboxpreviewitem.h"
+
+// Local includes.
+
+#include "bwsepiatool.h"
+#include "bwsepiatool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+class PreviewPixmapFactory : public TQObject
+{
+public:
+
+ PreviewPixmapFactory(BWSepiaTool* bwSepia);
+
+ void invalidate() { m_previewPixmapMap.clear(); }
+
+ const TQPixmap* pixmap(int id);
+
+private:
+
+ TQPixmap makePixmap(int id);
+
+ TQIntDict<TQPixmap> m_previewPixmapMap;
+ BWSepiaTool *m_bwSepia;
+};
+
+PreviewPixmapFactory::PreviewPixmapFactory(BWSepiaTool* bwSepia)
+ : TQObject(bwSepia), m_bwSepia(bwSepia)
+{
+ m_previewPixmapMap.setAutoDelete(true);
+}
+
+const TQPixmap* PreviewPixmapFactory::pixmap(int id)
+{
+ if (m_previewPixmapMap.find(id) == 0)
+ {
+ TQPixmap pix = makePixmap(id);
+ m_previewPixmapMap.insert(id, new TQPixmap(pix));
+ }
+
+ TQPixmap* res = m_previewPixmapMap[id];
+
+ return res;
+}
+
+TQPixmap PreviewPixmapFactory::makePixmap(int id)
+{
+ return m_bwSepia->getThumbnailForEffect(id);
+}
+
+// -----------------------------------------------------------------------------------
+
+class ListBoxBWPreviewItem : public ListBoxPreviewItem
+{
+
+public:
+
+ ListBoxBWPreviewItem(TQListBox *listbox, const TQString &text,
+ PreviewPixmapFactory* factory, int id)
+ : ListBoxPreviewItem(listbox, TQPixmap(), text)
+ {
+ m_previewPixmapFactory = factory;
+ m_id = id;
+ };
+
+ virtual const TQPixmap* pixmap() const;
+
+private:
+
+ int m_id;
+ PreviewPixmapFactory* m_previewPixmapFactory;
+};
+
+const TQPixmap* ListBoxBWPreviewItem::pixmap() const
+{
+ return m_previewPixmapFactory->pixmap(m_id);
+}
+
+// -----------------------------------------------------------------------------------
+
+BWSepiaTool::BWSepiaTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("convertbw");
+ setToolName(i18n("Black && White"));
+ setToolIcon(SmallIcon("bwtonal"));
+ setToolHelp("blackandwhitetool.anchor");
+
+ m_destinationPreviewData = 0;
+
+ ImageIface iface(0, 0);
+ m_originalImage = iface.getOriginalImg();
+ m_thumbnailImage = m_originalImage->smoothScale(128, 128, TQSize::ScaleMin);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImageWidget("convertbw Tool", 0,
+ i18n("<p>Here you can see the black and white conversion tool preview. "
+ "You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ EditorToolSettings *gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings->plainPage(), 4, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings->plainPage());
+ label1->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+ m_channelCB = new TQComboBox(false, gboxSettings->plainPage());
+ m_channelCB->insertItem(i18n("Luminosity"));
+ m_channelCB->insertItem(i18n("Red"));
+ m_channelCB->insertItem(i18n("Green"));
+ m_channelCB->insertItem(i18n("Blue"));
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin(0);
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(linHistoButton, i18n("<p>Linear"));
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap(TQPixmap(directory + "histogram-lin.png"));
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(logHistoButton, i18n("<p>Logarithmic"));
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap(TQPixmap(directory + "histogram-log.png"));
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal, 10, histoBox);
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ m_tab = new KTabWidget(gboxSettings->plainPage());
+
+ m_bwFilm = new TQListBox(m_tab);
+ m_bwFilm->setColumnMode(1);
+ m_bwFilm->setVariableWidth(false);
+ m_bwFilm->setVariableHeight(false);
+ ListBoxWhatsThis* whatsThis2 = new ListBoxWhatsThis(m_bwFilm);
+ m_previewPixmapFactory = new PreviewPixmapFactory(this);
+
+ int type = BWGeneric;
+
+ ListBoxBWPreviewItem *item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Generic"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Generic</b>:"
+ "<p>Simulate a generic black and white film</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Agfa 200X"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Agfa 200X</b>:"
+ "<p>Simulate the Agfa 200X black and white film at 200 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Agfa Pan 25"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Agfa Pan 25</b>:"
+ "<p>Simulate the Agfa Pan black and white film at 25 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Agfa Pan 100"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Agfa Pan 100</b>:"
+ "<p>Simulate the Agfa Pan black and white film at 100 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Agfa Pan 400"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Agfa Pan 400</b>:"
+ "<p>Simulate the Agfa Pan black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford Delta 100"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford Delta 100</b>:"
+ "<p>Simulate the Ilford Delta black and white film at 100 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford Delta 400"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford Delta 400</b>:"
+ "<p>Simulate the Ilford Delta black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford Delta 400 Pro 3200"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford Delta 400 Pro 3200</b>:"
+ "<p>Simulate the Ilford Delta 400 Pro black and white film at 3200 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford FP4 Plus"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford FP4 Plus</b>:"
+ "<p>Simulate the Ilford FP4 Plus black and white film at 125 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford HP5 Plus"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford HP5 Plus</b>:"
+ "<p>Simulate the Ilford HP5 Plus black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford PanF Plus"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford PanF Plus</b>:"
+ "<p>Simulate the Ilford PanF Plus black and white film at 50 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford XP2 Super"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford XP2 Super</b>:"
+ "<p>Simulate the Ilford XP2 Super black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Kodak Tmax 100"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Kodak Tmax 100</b>:"
+ "<p>Simulate the Kodak Tmax black and white film at 100 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Kodak Tmax 400"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Kodak Tmax 400</b>:"
+ "<p>Simulate the Kodak Tmax black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Kodak TriX"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Kodak TriX</b>:"
+ "<p>Simulate the Kodak TriX black and white film at 400 ISO</p>"));
+
+ // -------------------------------------------------------------
+
+ TQVBox *vbox = new TQVBox(m_tab);
+
+ m_bwFilters = new TQListBox(vbox);
+ m_bwFilters->setColumnMode(1);
+ m_bwFilters->setVariableWidth(false);
+ m_bwFilters->setVariableHeight(false);
+ ListBoxWhatsThis* whatsThis = new ListBoxWhatsThis(m_bwFilters);
+
+ type = BWNoFilter;
+
+ item = new ListBoxBWPreviewItem(m_bwFilters,
+ i18n("No Lens Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>No Lens Filter</b>:"
+ "<p>Do not apply a lens filter when rendering the image.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilters, i18n("Green Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>Black & White with Green Filter</b>:"
+ "<p>Simulate black and white film exposure using a green filter. "
+ "This is usefule for all scenic shoots, especially portraits "
+ "photographed against the sky.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilters, i18n("Orange Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>Black & White with Orange Filter</b>:"
+ "<p>Simulate black and white film exposure using an orange filter. "
+ "This will enhance landscapes, marine scenes and aerial "
+ "photography.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilters, i18n("Red Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>Black & White with Red Filter</b>:"
+ "<p>Simulate black and white film exposure using a red filter. "
+ "This creates dramatic sky effects, and simulates moonlight scenes "
+ "in the daytime.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilters, i18n("Yellow Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>Black & White with Yellow Filter</b>:"
+ "<p>Simulate black and white film exposure using a yellow filter. "
+ "This has the most natural tonal correction, and improves contrast. Ideal for "
+ "landscapes.</p>"));
+
+ m_strengthInput = new RIntNumInput(vbox);
+ m_strengthInput->input()->setLabel(i18n("Strength:"), AlignLeft | AlignVCenter);
+ m_strengthInput->setRange(1, 5, 1);
+ m_strengthInput->setDefaultValue(1);
+ TQWhatsThis::add(m_strengthInput, i18n("<p>Here, set the strength adjustment of the lens filter."));
+
+ // -------------------------------------------------------------
+
+ m_bwTone = new TQListBox(m_tab);
+ m_bwTone->setColumnMode(1);
+ m_bwTone->setVariableWidth(false);
+ m_bwTone->setVariableHeight(false);
+ ListBoxWhatsThis* whatsThis3 = new ListBoxWhatsThis(m_bwTone);
+
+ type = BWNoTone;
+
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("No Tone Filter"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>No Tone Filter</b>:"
+ "<p>Do not apply a tone filter to the image.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Sepia Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Sepia Tone</b>:"
+ "<p>Gives a warm highlight and mid-tone while adding a bit of coolness to "
+ "the shadows - very similar to the process of bleaching a print and "
+ "re-developing in a sepia toner.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Brown Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Brown Tone</b>:"
+ "<p>This filter is more neutral than the Sepia Tone "
+ "filter.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Cold Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Cold Tone</b>:"
+ "<p>Start subtle and replicates printing on a cold tone black and white "
+ "paper such as a bromide enlarging "
+ "paper.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Selenium Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Selenium Tone</b>:"
+ "<p>This effect replicates traditional selenium chemical toning done "
+ "in the darkroom.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Platinum Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Platinum Tone</b>:"
+ "<p>This effect replicates traditional platinum chemical toning done "
+ "in the darkroom.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Green Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with greenish tint</b>:"
+ "<p>This effect is also known as Verdante.</p>"));
+
+ // -------------------------------------------------------------
+
+ TQWidget *curveBox = new TQWidget( m_tab );
+ TQGridLayout *gridTab2 = new TQGridLayout(curveBox, 5, 2, 0);
+
+ ColorGradientWidget* vGradient = new ColorGradientWidget(
+ ColorGradientWidget::Vertical,
+ 10, curveBox);
+ vGradient->setColors(TQColor("white"), TQColor("black"));
+
+ TQLabel *spacev = new TQLabel(curveBox);
+ spacev->setFixedWidth(1);
+
+ m_curvesWidget = new CurvesWidget(256, 256, m_originalImage->bits(), m_originalImage->width(),
+ m_originalImage->height(), m_originalImage->sixteenBit(),
+ curveBox);
+ TQWhatsThis::add( m_curvesWidget, i18n("<p>This is the curve adjustment of the image luminosity"));
+
+ TQLabel *spaceh = new TQLabel(curveBox);
+ spaceh->setFixedHeight(1);
+
+ ColorGradientWidget *hGradient = new ColorGradientWidget(
+ ColorGradientWidget::Horizontal,
+ 10, curveBox);
+ hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ m_cInput = new RIntNumInput(curveBox);
+ m_cInput->input()->setLabel(i18n("Contrast:"), AlignLeft | AlignVCenter);
+ m_cInput->setRange(-100, 100, 1);
+ m_cInput->setDefaultValue(0);
+ TQWhatsThis::add( m_cInput, i18n("<p>Set here the contrast adjustment of the image."));
+
+ gridTab2->addMultiCellWidget(vGradient, 0, 0, 0, 0);
+ gridTab2->addMultiCellWidget(spacev, 0, 0, 1, 1);
+ gridTab2->addMultiCellWidget(m_curvesWidget, 0, 0, 2, 2);
+ gridTab2->addMultiCellWidget(spaceh, 1, 1, 2, 2);
+ gridTab2->addMultiCellWidget(hGradient, 2, 2, 2, 2);
+ gridTab2->addMultiCellWidget(m_cInput, 4, 4, 0, 2);
+// gridTab2->setRowSpacing(3);
+ gridTab2->setRowStretch(5, 10);
+
+ // -------------------------------------------------------------
+
+ m_tab->insertTab(m_bwFilm, i18n("Film"), FilmTab);
+ m_tab->insertTab(vbox, i18n("Lens Filters"), BWFiltersTab);
+ m_tab->insertTab(m_bwTone, i18n("Tone"), ToneTab);
+ m_tab->insertTab(curveBox, i18n("Lightness"), LuminosityTab);
+
+ gridSettings->addMultiCellWidget(m_tab, 3, 3, 0, 4);
+ gridSettings->setRowStretch(3, 10);
+ setToolSettings(gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotSpotColorChanged(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_bwFilters, TQ_SIGNAL(highlighted(int)),
+ this, TQ_SLOT(slotFilterSelected(int)));
+
+ connect(m_strengthInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_bwFilm, TQ_SIGNAL(highlighted(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_bwTone, TQ_SIGNAL(highlighted(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_curvesWidget, TQ_SIGNAL(signalCurvesChanged()),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_cInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+}
+
+BWSepiaTool::~BWSepiaTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void BWSepiaTool::slotFilterSelected(int filter)
+{
+ if (filter == BWNoFilter)
+ m_strengthInput->setEnabled(false);
+ else
+ m_strengthInput->setEnabled(true);
+
+ slotEffect();
+}
+
+TQPixmap BWSepiaTool::getThumbnailForEffect(int type)
+{
+ DImg thumb = m_thumbnailImage.copy();
+ int w = thumb.width();
+ int h = thumb.height();
+ bool sb = thumb.sixteenBit();
+ bool a = thumb.hasAlpha();
+
+ if (type < BWGeneric)
+ {
+ // In Filter view, we will render a preview of the B&W filter with the generic B&W film.
+ blackAndWhiteConversion(thumb.bits(), w, h, sb, type);
+ blackAndWhiteConversion(thumb.bits(), w, h, sb, BWGeneric);
+ }
+ else
+ {
+ // In Film and Tone view, we will render the preview without to use the B&W Filter
+ blackAndWhiteConversion(thumb.bits(), w, h, sb, type);
+ }
+
+ if (m_curvesWidget->curves()) // in case we're called before the creator is done
+ {
+ uchar *targetData = new uchar[w*h*(sb ? 8 : 4)];
+ m_curvesWidget->curves()->curvesLutSetup(ImageHistogram::AlphaChannel);
+ m_curvesWidget->curves()->curvesLutProcess(thumb.bits(), targetData, w, h);
+
+ DImg preview(w, h, sb, a, targetData);
+ BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(preview);
+
+ thumb.putImageData(preview.bits());
+
+ delete [] targetData;
+ }
+ return (thumb.convertToPixmap());
+}
+
+void BWSepiaTool::slotChannelChanged(int channel)
+{
+ switch (channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("red"));
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("green"));
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("blue"));
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void BWSepiaTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+ m_curvesWidget->m_scaleType = scale;
+ m_curvesWidget->repaint(false);
+}
+
+void BWSepiaTool::slotSpotColorChanged(const DColor &color)
+{
+ m_curvesWidget->setCurveGuide(color);
+}
+
+void BWSepiaTool::slotColorSelectedFromTarget(const DColor &color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void BWSepiaTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("convertbw Tool");
+
+ m_tab->setCurrentPage(config->readNumEntry("Settings Tab", BWFiltersTab));
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+ m_bwFilters->setCurrentItem(config->readNumEntry("BW Filter", 0));
+ m_bwFilm->setCurrentItem(config->readNumEntry("BW Film", 0));
+ m_bwTone->setCurrentItem(config->readNumEntry("BW Tone", 0));
+ m_cInput->setValue(config->readNumEntry("ContrastAjustment", m_cInput->defaultValue()));
+ m_strengthInput->setValue(config->readNumEntry("StrengthAjustment", m_strengthInput->defaultValue()));
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curvesWidget->curves()->curvesChannelReset(i);
+
+ m_curvesWidget->curves()->setCurveType(m_curvesWidget->m_channelType, ImageCurves::CURVE_SMOOTH);
+ m_curvesWidget->reset();
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p = config->readPointEntry(TQString("CurveAjustmentPoint%1").arg(j), &disable);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::ValueChannel, j, p);
+ }
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curvesWidget->curves()->curvesCalculateCurve(i);
+
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+ slotFilterSelected(m_bwFilters->currentItem());
+}
+
+void BWSepiaTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("convertbw Tool");
+ config->writeEntry("Settings Tab", m_tab->currentPageIndex());
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("BW Filter", m_bwFilters->currentItem());
+ config->writeEntry("BW Film", m_bwFilm->currentItem());
+ config->writeEntry("BW Tone", m_bwTone->currentItem());
+ config->writeEntry("ContrastAjustment", m_cInput->value());
+ config->writeEntry("StrengthAjustment", m_strengthInput->value());
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint p = m_curvesWidget->curves()->getCurvePoint(ImageHistogram::ValueChannel, j);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()/255);
+ p.setY(p.y()/255);
+ }
+
+ config->writeEntry(TQString("CurveAjustmentPoint%1").arg(j), p);
+ }
+
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void BWSepiaTool::slotResetSettings()
+{
+ m_bwFilm->blockSignals(true);
+ m_bwFilters->blockSignals(true);
+ m_bwTone->blockSignals(true);
+ m_cInput->blockSignals(true);
+ m_strengthInput->blockSignals(true);
+
+ m_bwFilm->setCurrentItem(0);
+ m_bwFilm->setSelected(0, true);
+
+ m_bwFilters->setCurrentItem(0);
+ m_bwFilters->setSelected(0, true);
+
+ m_bwTone->setCurrentItem(0);
+ m_bwTone->setSelected(0, true);
+
+ m_cInput->slotReset();
+ m_strengthInput->slotReset();
+
+ for (int channel = 0; channel < 5; channel++)
+ m_curvesWidget->curves()->curvesChannelReset(channel);
+
+ m_curvesWidget->reset();
+
+ m_bwFilm->blockSignals(false);
+ m_bwFilters->blockSignals(false);
+ m_bwTone->blockSignals(false);
+ m_cInput->blockSignals(false);
+ m_strengthInput->blockSignals(false);
+
+ m_histogramWidget->reset();
+ m_previewPixmapFactory->invalidate();
+ m_bwFilters->triggerUpdate(false);
+ m_bwTone->triggerUpdate(false);
+
+ slotEffect();
+}
+
+void BWSepiaTool::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ m_histogramWidget->stopHistogramComputation();
+
+ delete [] m_destinationPreviewData;
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool a = iface->previewHasAlpha();
+ bool sb = iface->previewSixteenBit();
+
+ // Apply black and white filter.
+
+ blackAndWhiteConversion(m_destinationPreviewData, w, h, sb, m_bwFilters->currentItem());
+
+ // Apply black and white film type.
+
+ blackAndWhiteConversion(m_destinationPreviewData, w, h, sb, m_bwFilm->currentItem() + BWGeneric);
+
+ // Apply color tone filter.
+
+ blackAndWhiteConversion(m_destinationPreviewData, w, h, sb, m_bwTone->currentItem() + BWNoTone);
+
+ // Calculate and apply the curve on image.
+
+ uchar *targetData = new uchar[w*h*(sb ? 8 : 4)];
+ m_curvesWidget->curves()->curvesLutSetup(ImageHistogram::AlphaChannel);
+ m_curvesWidget->curves()->curvesLutProcess(m_destinationPreviewData, targetData, w, h);
+
+ // Adjust contrast.
+
+ DImg preview(w, h, sb, a, targetData);
+ BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(preview);
+ iface->putPreviewImage(preview.bits());
+
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, preview.bits(), preview.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ delete [] targetData;
+
+ kapp->restoreOverrideCursor();
+}
+
+void BWSepiaTool::finalRendering()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool a = iface->originalHasAlpha();
+ bool sb = iface->originalSixteenBit();
+
+ if (data)
+ {
+ // Apply black and white filter.
+
+ blackAndWhiteConversion(data, w, h, sb, m_bwFilters->currentItem());
+
+ // Apply black and white film type.
+
+ blackAndWhiteConversion(data, w, h, sb, m_bwFilm->currentItem() + BWGeneric);
+
+ // Apply color tone filter.
+
+ blackAndWhiteConversion(data, w, h, sb, m_bwTone->currentItem() + BWNoTone);
+
+ // Calculate and apply the curve on image.
+
+ uchar *targetData = new uchar[w*h*(sb ? 8 : 4)];
+ m_curvesWidget->curves()->curvesLutSetup(ImageHistogram::AlphaChannel);
+ m_curvesWidget->curves()->curvesLutProcess(data, targetData, w, h);
+
+ // Adjust contrast.
+
+ DImg img(w, h, sb, a, targetData);
+ BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(img);
+
+ iface->putOriginalImage(i18n("Convert to Black && White"), img.bits());
+
+ delete [] data;
+ delete [] targetData;
+ }
+
+ kapp->restoreOverrideCursor();
+}
+
+void BWSepiaTool::blackAndWhiteConversion(uchar *data, int w, int h, bool sb, int type)
+{
+ // Value to multiply RGB 8 bits component of mask used by changeTonality() method.
+ int mul = sb ? 255 : 1;
+ DImgImageFilters filter;
+ double strength = 1.0 + ((double)m_strengthInput->value() - 1.0) * (1.0 / 3.0);
+
+ switch (type)
+ {
+ case BWNoFilter:
+ m_redAttn = 0.0;
+ m_greenAttn = 0.0;
+ m_blueAttn = 0.0;
+ break;
+
+ case BWGreenFilter:
+ m_redAttn = -0.20 * strength;
+ m_greenAttn = +0.11 * strength;
+ m_blueAttn = +0.09 * strength;
+ break;
+
+ case BWOrangeFilter:
+ m_redAttn = +0.48 * strength;
+ m_greenAttn = -0.37 * strength;
+ m_blueAttn = -0.11 * strength;
+ break;
+
+ case BWRedFilter:
+ m_redAttn = +0.60 * strength;
+ m_greenAttn = -0.49 * strength;
+ m_blueAttn = -0.11 * strength;
+ break;
+
+ case BWYellowFilter:
+ m_redAttn = +0.30 * strength;
+ m_greenAttn = -0.31 * strength;
+ m_blueAttn = +0.01 * strength;
+ break;
+
+ // --------------------------------------------------------------------------------
+
+ case BWGeneric:
+ case BWNoTone:
+ m_redMult = 0.24;
+ m_greenMult = 0.68;
+ m_blueMult = 0.08;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWAgfa200X:
+ m_redMult = 0.18;
+ m_greenMult = 0.41;
+ m_blueMult = 0.41;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWAgfapan25:
+ m_redMult = 0.25;
+ m_greenMult = 0.39;
+ m_blueMult = 0.36;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWAgfapan100:
+ m_redMult = 0.21;
+ m_greenMult = 0.40;
+ m_blueMult = 0.39;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWAgfapan400:
+ m_redMult = 0.20;
+ m_greenMult = 0.41;
+ m_blueMult = 0.39;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordDelta100:
+ m_redMult = 0.21;
+ m_greenMult = 0.42;
+ m_blueMult = 0.37;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordDelta400:
+ m_redMult = 0.22;
+ m_greenMult = 0.42;
+ m_blueMult = 0.36;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordDelta400Pro3200:
+ m_redMult = 0.31;
+ m_greenMult = 0.36;
+ m_blueMult = 0.33;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordFP4:
+ m_redMult = 0.28;
+ m_greenMult = 0.41;
+ m_blueMult = 0.31;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordHP5:
+ m_redMult = 0.23;
+ m_greenMult = 0.37;
+ m_blueMult = 0.40;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordPanF:
+ m_redMult = 0.33;
+ m_greenMult = 0.36;
+ m_blueMult = 0.31;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordXP2Super:
+ m_redMult = 0.21;
+ m_greenMult = 0.42;
+ m_blueMult = 0.37;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWKodakTmax100:
+ m_redMult = 0.24;
+ m_greenMult = 0.37;
+ m_blueMult = 0.39;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWKodakTmax400:
+ m_redMult = 0.27;
+ m_greenMult = 0.36;
+ m_blueMult = 0.37;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWKodakTriX:
+ m_redMult = 0.25;
+ m_greenMult = 0.35;
+ m_blueMult = 0.40;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ // --------------------------------------------------------------------------------
+
+ case BWSepiaTone:
+ filter.changeTonality(data, w, h, sb, 162*mul, 132*mul, 101*mul);
+ break;
+
+ case BWBrownTone:
+ filter.changeTonality(data, w, h, sb, 129*mul, 115*mul, 104*mul);
+ break;
+
+ case BWColdTone:
+ filter.changeTonality(data, w, h, sb, 102*mul, 109*mul, 128*mul);
+ break;
+
+ case BWSeleniumTone:
+ filter.changeTonality(data, w, h, sb, 122*mul, 115*mul, 122*mul);
+ break;
+
+ case BWPlatinumTone:
+ filter.changeTonality(data, w, h, sb, 115*mul, 110*mul, 106*mul);
+ break;
+
+ case BWGreenTone:
+ filter.changeTonality(data, w, h, sb, 108*mul, 116*mul, 100*mul);
+ break;
+
+ }
+}
+
+//-- Load all settings from file --------------------------------------
+
+void BWSepiaTool::slotLoadSettings()
+{
+ KURL loadFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Black & White Settings File to Load")) );
+ if( loadFile.isEmpty() )
+ return;
+
+ TQFile file(loadFile.path());
+
+ if (file.open(IO_ReadOnly))
+ {
+ TQTextStream stream(&file);
+
+ if (stream.readLine() != "# Black & White Configuration File")
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" is not a Black & White settings text file.")
+ .arg(loadFile.fileName()));
+ file.close();
+ return;
+ }
+
+ m_bwFilters->blockSignals(true);
+ m_bwTone->blockSignals(true);
+ m_cInput->blockSignals(true);
+
+ m_bwFilters->setCurrentItem(stream.readLine().toInt());
+ m_bwTone->setCurrentItem(stream.readLine().toInt());
+ m_cInput->setValue(stream.readLine().toInt());
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curvesWidget->curves()->curvesChannelReset(i);
+
+ m_curvesWidget->curves()->setCurveType(m_curvesWidget->m_channelType, ImageCurves::CURVE_SMOOTH);
+ m_curvesWidget->reset();
+
+ for (int j = 0; j < 17; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p;
+ p.setX(stream.readLine().toInt());
+ p.setY(stream.readLine().toInt());
+
+ if (m_originalImage->sixteenBit() && p != disable)
+ {
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::ValueChannel, j, p);
+ }
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curvesWidget->curves()->curvesCalculateCurve(i);
+
+ m_bwFilters->blockSignals(false);
+ m_bwTone->blockSignals(false);
+ m_cInput->blockSignals(false);
+
+ m_histogramWidget->reset();
+ m_previewPixmapFactory->invalidate();
+ m_bwFilters->triggerUpdate(false);
+ m_bwTone->triggerUpdate(false);
+
+ slotEffect();
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot load settings from the Black & White text file."));
+
+ file.close();
+}
+
+//-- Save all settings to file ---------------------------------------
+
+void BWSepiaTool::slotSaveAsSettings()
+{
+ KURL saveFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Black & White Settings File to Save")));
+ if( saveFile.isEmpty() )
+ return;
+
+ TQFile file(saveFile.path());
+
+ if (file.open(IO_WriteOnly))
+ {
+ TQTextStream stream(&file);
+ stream << "# Black & White Configuration File\n";
+ stream << m_bwFilters->currentItem() << "\n";
+ stream << m_bwTone->currentItem() << "\n";
+ stream << m_cInput->value() << "\n";
+
+ for (int j = 0; j < 17; j++)
+ {
+ TQPoint p = m_curvesWidget->curves()->getCurvePoint(ImageHistogram::ValueChannel, j);
+ if (m_originalImage->sixteenBit())
+ {
+ p.setX(p.x() / 255);
+ p.setY(p.y() / 255);
+ }
+ stream << p.x() << "\n";
+ stream << p.y() << "\n";
+ }
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot save settings to the Black & White text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/bwsepiatool.h b/src/imageplugins/coreplugin/bwsepiatool.h
new file mode 100644
index 00000000..7145f567
--- /dev/null
+++ b/src/imageplugins/coreplugin/bwsepiatool.h
@@ -0,0 +1,193 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-06
+ * Description : Black and White conversion tool.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+
+#ifndef BWSEPIATOOL_H
+#define BWSEPIATOOL_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQHButtonGroup;
+class TQComboBox;
+class TQButtonGroup;
+class TQListBox;
+
+class KTabWidget;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+class DImg;
+class CurvesWidget;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class PreviewPixmapFactory;
+
+class BWSepiaTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ BWSepiaTool(TQObject *parent);
+ ~BWSepiaTool();
+
+ friend class PreviewPixmapFactory;
+
+protected:
+
+ TQPixmap getThumbnailForEffect(int type);
+ void finalRendering();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void blackAndWhiteConversion(uchar *data, int w, int h, bool sb, int type);
+
+private slots:
+
+ void slotResetSettings();
+ void slotSaveAsSettings();
+ void slotLoadSettings();
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotSpotColorChanged(const Digikam::DColor &color);
+ void slotColorSelectedFromTarget( const Digikam::DColor &color );
+ void slotFilterSelected(int filter);
+
+private:
+
+ enum BlackWhiteConversionType
+ {
+ BWNoFilter=0, // B&W filter to the front of lens.
+ BWGreenFilter,
+ BWOrangeFilter,
+ BWRedFilter,
+ BWYellowFilter,
+
+ BWGeneric, // B&W film simulation.
+ BWAgfa200X,
+ BWAgfapan25,
+ BWAgfapan100,
+ BWAgfapan400,
+ BWIlfordDelta100,
+ BWIlfordDelta400,
+ BWIlfordDelta400Pro3200,
+ BWIlfordFP4,
+ BWIlfordHP5,
+ BWIlfordPanF,
+ BWIlfordXP2Super,
+ BWKodakTmax100,
+ BWKodakTmax400,
+ BWKodakTriX,
+
+ BWNoTone, // Chemical color tone filter.
+ BWSepiaTone,
+ BWBrownTone,
+ BWColdTone,
+ BWSeleniumTone,
+ BWPlatinumTone,
+ BWGreenTone
+ };
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum SettingsTab
+ {
+ FilmTab=0,
+ BWFiltersTab,
+ ToneTab,
+ LuminosityTab
+ };
+
+ // Color filter attenuation in percents.
+ double m_redAttn, m_greenAttn, m_blueAttn;
+
+ // Channel mixer color multiplier.
+ double m_redMult, m_greenMult, m_blueMult;
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ TQListBox *m_bwFilters;
+ TQListBox *m_bwFilm;
+ TQListBox *m_bwTone;
+
+ KDcrawIface::RIntNumInput *m_cInput;
+ KDcrawIface::RIntNumInput *m_strengthInput;
+
+ KTabWidget *m_tab;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::CurvesWidget *m_curvesWidget;
+
+ Digikam::DImg *m_originalImage;
+ Digikam::DImg m_thumbnailImage;
+
+ PreviewPixmapFactory *m_previewPixmapFactory;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* BWSEPIATOOL_H */
diff --git a/src/imageplugins/coreplugin/digikamimageplugin_core.desktop b/src/imageplugins/coreplugin/digikamimageplugin_core.desktop
new file mode 100644
index 00000000..8f8b3d10
--- /dev/null
+++ b/src/imageplugins/coreplugin/digikamimageplugin_core.desktop
@@ -0,0 +1,47 @@
+[Desktop Entry]
+Name=ImagePlugin_Core
+Name[el]=ΠρόσθετοΕικόνας_Πυρήνας
+Name[fi]=Liitännäisten ydin
+Name[hr]=Jezgra
+Name[it]=PluginImmagini_Nocciolo
+Name[nl]=Afbeeldingsplugin_Kern
+Name[sr]=Језгро прикључака
+Name[sr@Latn]=Jezgro priključaka
+Name[sv]=Insticksprogram med bildkärna
+Name[tr]=ResimEklentisi_Çekirdek
+Name[xx]=xxImagePlugin_Corexx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=digiKam Core Image Plugin
+Comment[bg]=Основна приставка за снимки на digiKam
+Comment[ca]=Connector d'imatges bàsic del digiKam
+Comment[da]=Grundlæggende Digikam billed-plugin
+Comment[de]=digiKam-Kernmodul
+Comment[el]=Πρόσθετο εικόνων πυρήνα digiKam
+Comment[es]=Plugin fundamental de digiKam de imágenes
+Comment[et]=DigiKami peamine pildiplugin
+Comment[fa]=وصلۀ تصویر هستۀ digiKam
+Comment[fi]=digiKamin liitännäisten ydin
+Comment[gl]=Plugin de Imaxe Básico de digiKam
+Comment[hr]=digiKam dodatak za slike
+Comment[it]=Plugin delle immagini centrale di digiKam
+Comment[ja]=digiKam コア画像プラグイン
+Comment[nds]=Karn-Bildmoduul vun digiKam
+Comment[nl]=Digikam kernafbeeldingsplugin
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਕੋਰ ਚਿੱਤਰ ਪਲੱਗਇਨ
+Comment[pl]=Podstawowa wtyczka obrazu digiKama
+Comment[pt]='Plugin' de Imagem Básico do digiKam
+Comment[pt_BR]=Plugin digiKam para Centralização da imagem
+Comment[ru]=Модуль digiKam основная работа с изображением
+Comment[sk]=Základný obrázkový plugin digiKamu
+Comment[sr]=Језгро digiKam-ових сликовних прикључака
+Comment[sr@Latn]=Jezgro digiKam-ovih slikovnih priključaka
+Comment[sv]=Insticksprogram med bildkärna för Digikam
+Comment[tr]=digiKam Çekirdek Resim Eklentisi
+Comment[uk]=Втулок основи зображення для digiKam
+Comment[vi]=Phần bổ sung ảnh lõi digiKam
+Comment[xx]=xxdigiKam Core Image Pluginxx
+
+X-TDE-Library=digikamimageplugin_core
+author=Caulier Gilles, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/coreplugin/digikamimageplugin_core_ui.rc b/src/imageplugins/coreplugin/digikamimageplugin_core_ui.rc
new file mode 100644
index 00000000..cb1148bd
--- /dev/null
+++ b/src/imageplugins/coreplugin/digikamimageplugin_core_ui.rc
@@ -0,0 +1,56 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="7" name="digikamimageplugin_core" >
+
+ <MenuBar>
+
+ <Menu name="Color"><text>&amp;Color</text>
+ <Action name="implugcore_autocorrection" />
+ <Action name="imageplugin_whitebalance" />
+ <Action name="implugcore_bcg" />
+ <Action name="implugcore_hsl" />
+ <Action name="imageplugin_colorfx" />
+ <Action name="implugcore_rgb" />
+ <Separator />
+ <Action name="imageplugin_adjustcurves" />
+ <Action name="imageplugin_adjustlevels" />
+ <Action name="implugcore_invert" />
+ <Action name="implugcore_blackwhite" />
+ <Menu name="Depth"><text>&amp;Depth</text>
+ <Action name="implugcore_convertto8bits" />
+ <Action name="implugcore_convertto16bits" />
+ </Menu>
+ <Separator />
+ <Action name="implugcore_colormanagement" />
+ <Separator />
+ </Menu>
+ <Menu name="Enhance"><text>Enh&amp;ance</text>
+ <Action name="implugcore_sharpen" />
+ <Action name="implugcore_blur" />
+ <Separator />
+ <Action name="implugcore_redeye" />
+ </Menu>
+
+ <Menu name="Transform" ><text>Tra&amp;nsform</text>
+ <Action name="implugcore_ratiocrop" />
+ </Menu>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_infrared" />
+ <Action name="imageplugin_filmgrain" />
+ <Action name="imageplugin_oilpaint" />
+ <Action name="imageplugin_charcoal" />
+ <Action name="imageplugin_emboss" />
+ <Action name="imageplugin_distortionfx" />
+ <Action name="imageplugin_blurfx" />
+ <Action name="imageplugin_raindrop" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties/>
+
+</kpartgui>
diff --git a/src/imageplugins/coreplugin/hsl/Makefile.am b/src/imageplugins/coreplugin/hsl/Makefile.am
new file mode 100644
index 00000000..4465d44c
--- /dev/null
+++ b/src/imageplugins/coreplugin/hsl/Makefile.am
@@ -0,0 +1,26 @@
+noinst_LTLIBRARIES = libhsl.la
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+libhsl_la_SOURCES = hsltool.cpp hspreviewwidget.cpp
+
+libhsl_la_LDFLAGS = $(all_libraries)
+
+noinst_HEADERS = hsltool.h hspreviewwidget.h
+
diff --git a/src/imageplugins/coreplugin/hsl/hsltool.cpp b/src/imageplugins/coreplugin/hsl/hsltool.cpp
new file mode 100644
index 00000000..5fa3d746
--- /dev/null
+++ b/src/imageplugins/coreplugin/hsl/hsltool.cpp
@@ -0,0 +1,453 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-16
+ * Description : digiKam image editor to adjust Hue, Saturation,
+ * and Lightness of picture.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqframe.h>
+#include <tqgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqhgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <kcolordialog.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Digikam includes.
+
+#include "colorgradientwidget.h"
+#include "dimg.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "hslmodifier.h"
+#include "hspreviewwidget.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+
+// Local includes.
+
+#include "hsltool.h"
+#include "hsltool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+HSLTool::HSLTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("adjusthsl");
+ setToolName(i18n("Hue / Saturation / Lightness"));
+ setToolIcon(SmallIcon("adjusthsl"));
+ setToolHelp("hsladjusttool.anchor");
+
+ m_destinationPreviewData = 0;
+
+ ImageIface iface(0, 0);
+ m_originalImage = iface.getOriginalImg();
+
+ m_previewWidget = new ImageWidget("hsladjust Tool", 0,
+ i18n("<p>Here you can see the image "
+ "Hue/Saturation/Lightness adjustments preview. "
+ "You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* gridSettings = new TQGridLayout(m_gboxSettings->plainPage(), 11, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), m_gboxSettings->plainPage());
+ label1->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+ m_channelCB = new TQComboBox(false, m_gboxSettings->plainPage());
+ m_channelCB->insertItem(i18n("Luminosity"));
+ m_channelCB->insertItem(i18n("Red"));
+ m_channelCB->insertItem(i18n("Green"));
+ m_channelCB->insertItem(i18n("Blue"));
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(linHistoButton, i18n("<p>Linear"));
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap(TQPixmap(directory + "histogram-lin.png"));
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(logHistoButton, i18n("<p>Logarithmic"));
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap(TQPixmap(directory + "histogram-log.png"));
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(m_gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal, 10, histoBox);
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ m_HSSelector = new KHSSelector(m_gboxSettings->plainPage());
+ TQWhatsThis::add( m_HSSelector, i18n("<p>Select the hue and saturation adjustments of the image here."));
+ m_HSSelector->setMinimumSize(256, 142);
+ gridSettings->addMultiCellWidget(m_HSSelector, 3, 3, 0, 4);
+
+ m_HSPreview = new HSPreviewWidget(m_gboxSettings->plainPage());
+ TQWhatsThis::add( m_HSPreview, i18n("<p>You can see here a color preview of the hue and "
+ "saturation adjustments."));
+ m_HSPreview->setMinimumSize(256, 15);
+ gridSettings->addMultiCellWidget(m_HSPreview, 4, 4, 0, 4);
+
+ TQLabel *label2 = new TQLabel(i18n("Hue:"), m_gboxSettings->plainPage());
+ m_hInput = new RDoubleNumInput(m_gboxSettings);
+ m_hInput->setPrecision(0);
+ m_hInput->setRange(-180.0, 180.0, 1.0);
+ m_hInput->setDefaultValue(0.0);
+ TQWhatsThis::add( m_hInput, i18n("<p>Set here the hue adjustment of the image."));
+ gridSettings->addMultiCellWidget(label2, 5, 5, 0, 4);
+ gridSettings->addMultiCellWidget(m_hInput, 6, 6, 0, 4);
+
+ TQLabel *label3 = new TQLabel(i18n("Saturation:"), m_gboxSettings->plainPage());
+ m_sInput = new RDoubleNumInput(m_gboxSettings);
+ m_sInput->setPrecision(2);
+ m_sInput->setRange(-100.0, 100.0, 0.01);
+ m_sInput->setDefaultValue(0.0);
+ TQWhatsThis::add( m_sInput, i18n("<p>Set here the saturation adjustment of the image."));
+ gridSettings->addMultiCellWidget(label3, 7, 7, 0, 4);
+ gridSettings->addMultiCellWidget(m_sInput, 8, 8, 0, 4);
+
+ TQLabel *label4 = new TQLabel(i18n("Lightness:"), m_gboxSettings->plainPage());
+ m_lInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_lInput->setPrecision(2);
+ m_lInput->setRange(-100.0, 100.0, 0.01);
+ m_lInput->setDefaultValue(0.0);
+ TQWhatsThis::add( m_lInput, i18n("<p>Set here the lightness adjustment of the image."));
+ gridSettings->addMultiCellWidget(label4, 9, 9, 0, 4);
+ gridSettings->addMultiCellWidget(m_lInput, 10, 10, 0, 4);
+
+ gridSettings->setRowStretch(11, 10);
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_HSSelector, TQ_SIGNAL(valueChanged(int, int)),
+ this, TQ_SLOT(slotHSChanged(int, int)));
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_hInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_hInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotHChanged(double)));
+
+ connect(m_sInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_sInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotSChanged(double)));
+
+ connect(m_lInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings->enableButton(EditorToolSettings::Ok, false);
+}
+
+HSLTool::~HSLTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void HSLTool::slotChannelChanged(int channel)
+{
+ switch (channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("red"));
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("green"));
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("blue"));
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void HSLTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void HSLTool::slotColorSelectedFromTarget( const DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void HSLTool::slotHSChanged(int h, int s)
+{
+ double hue = double(h);
+ if (h >= 180 && h <= 359)
+ hue = double(h) - 359.0;
+
+ double sat = ((double) s * (200.0 / 255.0)) - 100.0;
+
+ m_hInput->blockSignals(true);
+ m_sInput->blockSignals(true);
+
+ m_hInput->setValue(hue);
+ m_sInput->setValue(sat);
+
+ m_hInput->blockSignals(false);
+ m_sInput->blockSignals(false);
+
+ slotTimer();
+}
+
+void HSLTool::slotHChanged(double h)
+{
+ int hue = int(h);
+ if (h >= -180 && h < 0)
+ hue = int(h) + 359;
+
+ m_HSSelector->blockSignals(true);
+ m_HSSelector->setXValue(hue);
+ m_HSSelector->blockSignals(false);
+}
+
+void HSLTool::slotSChanged(double s)
+{
+ int sat = (int) ((s + 100.0) * (255.0 / 200.0));
+
+ m_HSSelector->blockSignals(true);
+ m_HSSelector->setYValue(sat);
+ m_HSSelector->blockSignals(false);
+}
+
+void HSLTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("hsladjust Tool");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+ m_hInput->setValue(config->readDoubleNumEntry("HueAjustment", m_hInput->defaultValue()));
+ m_sInput->setValue(config->readDoubleNumEntry("SaturationAjustment", m_sInput->defaultValue()));
+ m_lInput->setValue(config->readDoubleNumEntry("LighnessAjustment", m_lInput->defaultValue()));
+ slotHChanged(m_hInput->value());
+ slotSChanged(m_sInput->value());
+
+ m_histogramWidget->reset();
+
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void HSLTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("hsladjust Tool");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("HueAjustment", m_hInput->value());
+ config->writeEntry("SaturationAjustment", m_sInput->value());
+ config->writeEntry("LighnessAjustment", m_lInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void HSLTool::slotResetSettings()
+{
+ m_hInput->blockSignals(true);
+ m_sInput->blockSignals(true);
+ m_lInput->blockSignals(true);
+
+ m_hInput->slotReset();
+ m_sInput->slotReset();
+ m_lInput->slotReset();
+
+ slotHChanged(0.0);
+ slotSChanged(0.0);
+
+ slotEffect();
+
+ m_hInput->blockSignals(false);
+ m_sInput->blockSignals(false);
+ m_lInput->blockSignals(false);
+}
+
+void HSLTool::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ double hu = m_hInput->value();
+ double sa = m_sInput->value();
+ double lu = m_lInput->value();
+
+ m_gboxSettings->enableButton(EditorToolSettings::Ok,
+ ( hu != 0.0 || sa != 0.0 || lu != 0.0));
+
+ m_HSPreview->setHS(hu, sa);
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool a = iface->previewHasAlpha();
+ bool sb = iface->previewSixteenBit();
+
+ DImg preview(w, h, sb, a, m_destinationPreviewData);
+ HSLModifier cmod;
+ cmod.setHue(hu);
+ cmod.setSaturation(sa);
+ cmod.setLightness(lu);
+ cmod.applyHSL(preview);
+ iface->putPreviewImage(preview.bits());
+
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, preview.bits(), preview.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void HSLTool::finalRendering()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+
+ double hu = m_hInput->value();
+ double sa = m_sInput->value();
+ double lu = m_lInput->value();
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool a = iface->originalHasAlpha();
+ bool sb = iface->originalSixteenBit();
+ DImg original(w, h, sb, a, data);
+ delete [] data;
+
+ HSLModifier cmod;
+ cmod.setHue(hu);
+ cmod.setSaturation(sa);
+ cmod.setLightness(lu);
+ cmod.applyHSL(original);
+
+ iface->putOriginalImage(i18n("HSL Adjustments"), original.bits());
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/hsl/hsltool.h b/src/imageplugins/coreplugin/hsl/hsltool.h
new file mode 100644
index 00000000..751bacf3
--- /dev/null
+++ b/src/imageplugins/coreplugin/hsl/hsltool.h
@@ -0,0 +1,126 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-16
+ * Description : digiKam image editor to adjust Hue, Saturation,
+ * and Lightness of picture.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef HSLTOOL_H
+#define HSLTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQComboBox;
+class TQHButtonGroup;
+
+class KHSSelector;
+
+namespace KDcrawIface
+{
+class RDoubleNumInput;
+}
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+class DImg;
+class EditorToolSettings;
+}
+
+namespace DigikamImagesPluginCore
+{
+class HSPreviewWidget;
+
+class HSLTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ HSLTool(TQObject *parent);
+ ~HSLTool();
+
+private slots:
+
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget( const Digikam::DColor &color );
+ void slotHSChanged(int h, int s);
+ void slotHChanged(double h);
+ void slotSChanged(double s);
+ void slotResetSettings();
+
+private:
+
+ void writeSettings();
+ void readSettings();
+ void finalRendering();
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ KDcrawIface::RDoubleNumInput *m_hInput;
+ KDcrawIface::RDoubleNumInput *m_sInput;
+ KDcrawIface::RDoubleNumInput *m_lInput;
+
+ KHSSelector *m_HSSelector;
+
+ HSPreviewWidget *m_HSPreview;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::DImg *m_originalImage;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* HSLTOOL_H */
diff --git a/src/imageplugins/coreplugin/hsl/hspreviewwidget.cpp b/src/imageplugins/coreplugin/hsl/hspreviewwidget.cpp
new file mode 100644
index 00000000..3841ca38
--- /dev/null
+++ b/src/imageplugins/coreplugin/hsl/hspreviewwidget.cpp
@@ -0,0 +1,126 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-01-08
+ * Description : Hue/Saturation preview widget
+ *
+ * Copyright (C) 2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqdrawutil.h>
+#include <tqimage.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <tdelocale.h>
+#include <kimageeffect.h>
+
+// Local includes.
+
+#include "hslmodifier.h"
+#include "dimg.h"
+#include "hspreviewwidget.h"
+#include "hspreviewwidget.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+class HSPreviewWidgetPrivate
+{
+
+public:
+
+ HSPreviewWidgetPrivate()
+ {
+ hue = 0.0;
+ sat = 0.0;
+ }
+
+ int xBorder;
+
+ double hue;
+ double sat;
+
+ TQPixmap pixmap;
+};
+
+HSPreviewWidget::HSPreviewWidget(TQWidget *parent, int xBorder)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new HSPreviewWidgetPrivate;
+ d->xBorder = xBorder;
+}
+
+HSPreviewWidget::~HSPreviewWidget()
+{
+ delete d;
+}
+
+void HSPreviewWidget::setHS(double hue, double sat)
+{
+ d->hue = hue;
+ d->sat = sat;
+ updatePixmap();
+ update();
+}
+
+void HSPreviewWidget::resizeEvent( TQResizeEvent * )
+{
+ updatePixmap();
+}
+
+void HSPreviewWidget::paintEvent( TQPaintEvent * )
+{
+ bitBlt(this, 0+d->xBorder, 0, &d->pixmap);
+}
+
+void HSPreviewWidget::updatePixmap()
+{
+ int xSize = width()-2*d->xBorder;
+ int ySize = height();
+
+ Digikam::DImg image(xSize, ySize, false, false, 0, false);
+ TQColor col;
+ uint *p;
+
+ for ( int s = ySize-1; s >= 0; s-- )
+ {
+ p = (uint *)image.scanLine(ySize - s - 1);
+
+ for( int h = 0 ; h < xSize ; h++ )
+ {
+ col.setHsv( 359*h/(xSize-1), 255, 192 );
+ *p = col.rgb();
+ p++;
+ }
+ }
+
+ Digikam::HSLModifier cmod;
+ cmod.setHue(d->hue);
+ cmod.setSaturation(d->sat);
+ cmod.setLightness(0.0);
+ cmod.applyHSL(image);
+
+ d->pixmap = image.convertToPixmap();
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/hsl/hspreviewwidget.h b/src/imageplugins/coreplugin/hsl/hspreviewwidget.h
new file mode 100644
index 00000000..3744907c
--- /dev/null
+++ b/src/imageplugins/coreplugin/hsl/hspreviewwidget.h
@@ -0,0 +1,64 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2007-01-08
+ * Description : Hue/Saturation preview widget
+ *
+ * Copyright (C) 2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef HSPREVIEWWIDGET_H
+#define HSPREVIEWWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+
+namespace DigikamImagesPluginCore
+{
+
+class HSPreviewWidgetPrivate;
+
+class HSPreviewWidget : public TQWidget
+{
+ TQ_OBJECT
+
+
+public:
+
+ HSPreviewWidget(TQWidget *parent=0, int xBorder=0);
+ ~HSPreviewWidget();
+
+ void setHS(double hue, double sat);
+
+protected:
+
+ void resizeEvent( TQResizeEvent * );
+ void paintEvent( TQPaintEvent * );
+
+private:
+
+ void updatePixmap();
+
+private:
+
+ HSPreviewWidgetPrivate *d;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* HSPREVIEWWIDGET_H */
diff --git a/src/imageplugins/coreplugin/hsl/imageeffect_hsl.cpp b/src/imageplugins/coreplugin/hsl/imageeffect_hsl.cpp
new file mode 100644
index 00000000..e179d36f
--- /dev/null
+++ b/src/imageplugins/coreplugin/hsl/imageeffect_hsl.cpp
@@ -0,0 +1,428 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-16
+ * Description : digiKam image editor to adjust Hue, Saturation,
+ * and Lightness of picture.
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqvbox.h>
+#include <tqhbuttongroup.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcombobox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqtimer.h>
+
+// KDE includes.
+
+#include <knuminput.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kstandarddirs.h>
+#include <kcolordialog.h>
+
+// Digikam includes.
+
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "hslmodifier.h"
+#include "dimg.h"
+
+// Local includes.
+
+#include "hspreviewwidget.h"
+#include "imageeffect_hsl.h"
+#include "imageeffect_hsl.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+ImageEffect_HSL::ImageEffect_HSL(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Hue/Saturation/Lightness"), "hsladjust", false)
+{
+ m_destinationPreviewData = 0L;
+ setHelp("hsladjusttool.anchor", "digikam");
+
+ m_previewWidget = new Digikam::ImageWidget("hsladjust Tool Dialog", plainPage(),
+ i18n("<p>Here you can see the image "
+ "Hue/Saturation/Lightness adjustments preview. "
+ "You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings, 11, 4, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ m_HSSelector = new KHSSelector(gboxSettings);
+ TQWhatsThis::add( m_HSSelector, i18n("<p>Select the hue and saturation adjustments of the image here."));
+ m_HSSelector->setMinimumSize(256, 142);
+ gridSettings->addMultiCellWidget(m_HSSelector, 3, 3, 0, 4);
+
+ m_HSPreview = new HSPreviewWidget(gboxSettings, spacingHint());
+ TQWhatsThis::add( m_HSPreview, i18n("<p>You can see here a color preview of the hue and "
+ "saturation adjustments."));
+ m_HSPreview->setMinimumSize(256, 15);
+ gridSettings->addMultiCellWidget(m_HSPreview, 4, 4, 0, 4);
+
+ TQLabel *label2 = new TQLabel(i18n("Hue:"), gboxSettings);
+ m_hInput = new KDoubleNumInput(gboxSettings);
+ m_hInput->setPrecision(0);
+ m_hInput->setRange(-180.0, 180.0, 1.0, true);
+ m_hInput->setValue(0.0);
+ TQWhatsThis::add( m_hInput, i18n("<p>Set here the hue adjustment of the image."));
+ gridSettings->addMultiCellWidget(label2, 5, 5, 0, 4);
+ gridSettings->addMultiCellWidget(m_hInput, 6, 6, 0, 4);
+
+ TQLabel *label3 = new TQLabel(i18n("Saturation:"), gboxSettings);
+ m_sInput = new KDoubleNumInput(gboxSettings);
+ m_sInput->setPrecision(2);
+ m_sInput->setRange(-100.0, 100.0, 0.01, true);
+ m_sInput->setValue(0.0);
+ TQWhatsThis::add( m_sInput, i18n("<p>Set here the saturation adjustment of the image."));
+ gridSettings->addMultiCellWidget(label3, 7, 7, 0, 4);
+ gridSettings->addMultiCellWidget(m_sInput, 8, 8, 0, 4);
+
+ TQLabel *label4 = new TQLabel(i18n("Lightness:"), gboxSettings);
+ m_lInput = new KDoubleNumInput(gboxSettings);
+ m_lInput->setPrecision(2);
+ m_lInput->setRange(-100.0, 100.0, 0.01, true);
+ m_lInput->setValue(0.0);
+ TQWhatsThis::add( m_lInput, i18n("<p>Set here the lightness adjustment of the image."));
+ gridSettings->addMultiCellWidget(label4, 9, 9, 0, 4);
+ gridSettings->addMultiCellWidget(m_lInput, 10, 10, 0, 4);
+
+ gridSettings->setRowStretch(11, 10);
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_HSSelector, TQ_SIGNAL(valueChanged(int, int)),
+ this, TQ_SLOT(slotHSChanged(int, int)));
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_hInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_hInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotHChanged(double)));
+
+ connect(m_sInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_sInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotSChanged(double)));
+
+ connect(m_lInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+
+ enableButtonOK( false );
+}
+
+ImageEffect_HSL::~ImageEffect_HSL()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+ delete m_previewWidget;
+}
+
+void ImageEffect_HSL::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_HSL::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_HSL::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ImageEffect_HSL::slotHSChanged(int h, int s)
+{
+ double hue = double(h);
+ if (h >= 180 && h <= 359)
+ hue = double(h) - 359.0;
+
+ double sat = ((double)s * (200.0/255.0)) - 100.0;
+
+ m_hInput->blockSignals(true);
+ m_sInput->blockSignals(true);
+ m_hInput->setValue(hue);
+ m_sInput->setValue(sat);
+ m_hInput->blockSignals(false);
+ m_sInput->blockSignals(false);
+ slotTimer();
+}
+
+void ImageEffect_HSL::slotHChanged(double h)
+{
+ int hue = int(h);
+ if (h >= -180 && h < 0)
+ hue = int(h) + 359;
+
+ m_HSSelector->blockSignals(true);
+ m_HSSelector->setXValue(hue);
+ m_HSSelector->blockSignals(false);
+}
+
+void ImageEffect_HSL::slotSChanged(double s)
+{
+ int sat = (int)((s + 100.0) * (255.0/200.0));
+
+ m_HSSelector->blockSignals(true);
+ m_HSSelector->setYValue(sat);
+ m_HSSelector->blockSignals(false);
+}
+
+void ImageEffect_HSL::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("hsladjust Tool Dialog");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+ m_hInput->setValue(config->readDoubleNumEntry("HueAjustment", 0.0));
+ m_sInput->setValue(config->readDoubleNumEntry("SaturationAjustment", 0.0));
+ m_lInput->setValue(config->readDoubleNumEntry("LighnessAjustment", 0.0));
+ slotHChanged(m_hInput->value());
+ slotSChanged(m_sInput->value());
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ImageEffect_HSL::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("hsladjust Tool Dialog");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("HueAjustment", m_hInput->value());
+ config->writeEntry("SaturationAjustment", m_sInput->value());
+ config->writeEntry("LighnessAjustment", m_lInput->value());
+ config->sync();
+}
+
+void ImageEffect_HSL::resetValues()
+{
+ m_hInput->blockSignals(true);
+ m_sInput->blockSignals(true);
+ m_lInput->blockSignals(true);
+ m_hInput->setValue(0.0);
+ m_sInput->setValue(0.0);
+ m_lInput->setValue(0.0);
+ slotHChanged(0.0);
+ slotSChanged(0.0);
+ m_hInput->blockSignals(false);
+ m_sInput->blockSignals(false);
+ m_lInput->blockSignals(false);
+}
+
+void ImageEffect_HSL::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ double hu = m_hInput->value();
+ double sa = m_sInput->value();
+ double lu = m_lInput->value();
+
+ enableButtonOK( hu != 0.0 || sa != 0.0 || lu != 0.0);
+
+ m_HSPreview->setHS(hu, sa);
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool a = iface->previewHasAlpha();
+ bool sb = iface->previewSixteenBit();
+
+ Digikam::DImg preview(w, h, sb, a, m_destinationPreviewData);
+ Digikam::HSLModifier cmod;
+ cmod.setHue(hu);
+ cmod.setSaturation(sa);
+ cmod.setLightness(lu);
+ cmod.applyHSL(preview);
+ iface->putPreviewImage(preview.bits());
+
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, preview.bits(), preview.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void ImageEffect_HSL::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ double hu = m_hInput->value();
+ double sa = m_sInput->value();
+ double lu = m_lInput->value();
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool a = iface->originalHasAlpha();
+ bool sb = iface->originalSixteenBit();
+ Digikam::DImg original(w, h, sb, a, data);
+ delete [] data;
+
+ Digikam::HSLModifier cmod;
+ cmod.setHue(hu);
+ cmod.setSaturation(sa);
+ cmod.setLightness(lu);
+ cmod.applyHSL(original);
+
+ iface->putOriginalImage(i18n("HSL Adjustments"), original.bits());
+ kapp->restoreOverrideCursor();
+ accept();
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/hsl/imageeffect_hsl.h b/src/imageplugins/coreplugin/hsl/imageeffect_hsl.h
new file mode 100644
index 00000000..24880f4d
--- /dev/null
+++ b/src/imageplugins/coreplugin/hsl/imageeffect_hsl.h
@@ -0,0 +1,116 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-16
+ * Description : digiKam image editor to adjust Hue, Saturation,
+ * and Lightness of picture.
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_HSL_H
+#define IMAGEEFFECT_HSL_H
+
+// Digikam include.
+
+#include "imagedlgbase.h"
+
+class TQComboBox;
+class TQHButtonGroup;
+
+class KDoubleNumInput;
+class KHSSelector;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+}
+
+namespace DigikamImagesPluginCore
+{
+class HSPreviewWidget;
+
+class ImageEffect_HSL : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_HSL(TQWidget *parent);
+ ~ImageEffect_HSL();
+
+private slots:
+
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget( const Digikam::DColor &color );
+ void slotHSChanged(int h, int s);
+ void slotHChanged(double h);
+ void slotSChanged(double s);
+
+private:
+
+ void writeUserSettings();
+ void readUserSettings();
+ void resetValues();
+ void finalRendering();
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ KDoubleNumInput *m_hInput;
+ KDoubleNumInput *m_sInput;
+ KDoubleNumInput *m_lInput;
+
+ KHSSelector *m_HSSelector;
+
+ HSPreviewWidget *m_HSPreview;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_HSL_H */
diff --git a/src/imageplugins/coreplugin/iccprooftool.cpp b/src/imageplugins/coreplugin/iccprooftool.cpp
new file mode 100644
index 00000000..b74adf9a
--- /dev/null
+++ b/src/imageplugins/coreplugin/iccprooftool.cpp
@@ -0,0 +1,1310 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-12-21
+ * Description : digiKam image editor tool to correct picture
+ * colors using an ICC color profile
+ *
+ * Copyright (C) 2005-2006 by F.J. Cruz <fj.cruz@supercable.es>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqfile.h>
+#include <tqframe.h>
+#include <tqgroupbox.h>
+#include <tqhbox.h>
+#include <tqhbuttongroup.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpoint.h>
+#include <tqpushbutton.h>
+#include <tqradiobutton.h>
+#include <tqtextstream.h>
+#include <tqtoolbox.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqvbuttongroup.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdefile.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <ksqueezedtextlabel.h>
+#include <kstandarddirs.h>
+#include <ktabwidget.h>
+#include <kurllabel.h>
+#include <kurlrequester.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Digikam includes.
+
+#include "bcgmodifier.h"
+#include "colorgradientwidget.h"
+#include "curveswidget.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "iccpreviewwidget.h"
+#include "iccprofileinfodlg.h"
+#include "icctransform.h"
+#include "imagecurves.h"
+#include "imagehistogram.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+
+// Local includes.
+
+#include "iccprooftool.h"
+#include "iccprooftool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+ICCProofTool::ICCProofTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("colormanagement");
+ setToolName(i18n("Color Management"));
+ setToolIcon(SmallIcon("colormanagement"));
+ setToolHelp("colormanagement.anchor");
+
+ m_destinationPreviewData = 0;
+ m_cmEnabled = true;
+ m_hasICC = false;
+
+ ImageIface iface(0, 0);
+ m_originalImage = iface.getOriginalImg();
+ m_embeddedICC = iface.getEmbeddedICCFromOriginalImage();
+
+ m_previewWidget = new ImageWidget("colormanagement Tool",0,
+ i18n("<p>Here you can see the image preview after "
+ "applying a color profile</p>"));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout *gridSettings = new TQGridLayout(m_gboxSettings->plainPage(), 3, 2);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel: "), m_gboxSettings->plainPage());
+ label1->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+ m_channelCB = new TQComboBox(false, m_gboxSettings->plainPage());
+ m_channelCB->insertItem(i18n("Luminosity"));
+ m_channelCB->insertItem(i18n("Red"));
+ m_channelCB->insertItem(i18n("Green"));
+ m_channelCB->insertItem(i18n("Blue"));
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red channel values.<p>"
+ "<b>Green</b>: display the green channel values.<p>"
+ "<b>Blue</b>: display the blue channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin(0);
+ TQWhatsThis::add(m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal values are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal values are big; "
+ "if it is used, all values (small and large) will be visible on the "
+ "graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(linHistoButton, i18n("<p>Linear"));
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap(TQPixmap(directory + "histogram-lin.png"));
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(logHistoButton, i18n("<p>Logarithmic"));
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap(TQPixmap(directory + "histogram-log.png"));
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(m_gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram "
+ "of the selected image channel. "
+ "This one is updated after setting changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget( ColorGradientWidget::Horizontal, 10,
+ histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 2);
+
+ // -------------------------------------------------------------
+
+ m_toolBoxWidgets = new TQToolBox(m_gboxSettings->plainPage());
+ TQWidget *generalOptions = new TQWidget(m_toolBoxWidgets);
+ TQWidget *inProfiles = new TQWidget(m_toolBoxWidgets);
+ TQWidget *spaceProfiles = new TQWidget(m_toolBoxWidgets);
+ TQWidget *proofProfiles = new TQWidget(m_toolBoxWidgets);
+ TQWidget *lightnessadjust = new TQWidget(m_toolBoxWidgets);
+
+ //---------- "General" Page Setup ----------------------------------
+
+ m_toolBoxWidgets->insertItem(GENERALPAGE, generalOptions,
+ SmallIconSet("misc"), i18n("General Settings"));
+ TQWhatsThis::add(generalOptions, i18n("<p>Here you can set general parameters.</p>"));
+
+ TQGridLayout *zeroPageLayout = new TQGridLayout(generalOptions, 5, 1);
+
+ m_doSoftProofBox = new TQCheckBox(generalOptions);
+ m_doSoftProofBox->setText(i18n("Soft-proofing"));
+ TQWhatsThis::add(m_doSoftProofBox, i18n("<p>Rendering emulation of the device described "
+ "by the \"Proofing\" profile. Useful to preview the final "
+ "result without rendering to physical medium.</p>"));
+
+ m_checkGamutBox = new TQCheckBox(generalOptions);
+ m_checkGamutBox->setText(i18n("Check gamut"));
+ TQWhatsThis::add(m_checkGamutBox, i18n("<p>You can use this option if you want to show "
+ "the colors that are outside the printer's gamut<p>"));
+
+ m_embeddProfileBox = new TQCheckBox(generalOptions);
+ m_embeddProfileBox->setChecked(true);
+ m_embeddProfileBox->setText(i18n("Assign profile"));
+ TQWhatsThis::add(m_embeddProfileBox, i18n("<p>You can use this option to embed "
+ "the selected workspace color profile into the image.</p>"));
+
+ m_BPCBox = new TQCheckBox(generalOptions);
+ m_BPCBox->setText(i18n("Use BPC"));
+ TQWhatsThis::add(m_BPCBox, i18n("<p>The Black Point Compensation (BPC) feature does work in conjunction "
+ "with Relative Colorimetric Intent. Perceptual intent should make no "
+ "difference, since BPC is always on, and in Absolute Colorimetric "
+ "Intent it is always turned off.</p>"
+ "<p>BPC does compensate for a lack of ICC profiles in the dark tone rendering. "
+ "With BPC the dark tones are optimally mapped (no clipping) from original media "
+ "to the destination rendering media, e.g. the combination of paper and ink.</p>"));
+
+ TQLabel *intent = new TQLabel(i18n("Rendering Intent:"), generalOptions);
+ m_renderingIntentsCB = new RComboBox(generalOptions);
+ m_renderingIntentsCB->insertItem("Perceptual");
+ m_renderingIntentsCB->insertItem("Absolute Colorimetric");
+ m_renderingIntentsCB->insertItem("Relative Colorimetric");
+ m_renderingIntentsCB->insertItem("Saturation");
+ m_renderingIntentsCB->setDefaultItem(0);
+ TQWhatsThis::add( m_renderingIntentsCB, i18n("<ul><li>Perceptual intent causes the full gamut "
+ "of the image to be compressed or expanded to fill the gamut of the destination media, "
+ "so that gray balance is preserved but colorimetric accuracy may not be preserved.<br>"
+ "In other words, if certain colors in an image fall outside of the range of colors that "
+ "the output device can render, the image intent will cause all the colors in the image "
+ "to be adjusted so that every color in the image falls within the range that can be "
+ "rendered and so that the relationship between colors is preserved as much as possible.<br>"
+ "This intent is most suitable for display of photographs and images, and is the default "
+ "intent.</li>"
+ "<li> Absolute Colorimetric intent causes any colors that fall outside the range that the "
+ "output device can render to be adjusted to the closest color that can be rendered, while all "
+ "other colors are left unchanged.<br>"
+ "This intent preserves the white point and is most suitable for spot colors (Pantone, "
+ "TruMatch, logo colors, ...).</li>"
+ "<li>Relative Colorimetric intent is defined such that any colors that fall outside the "
+ "range that the output device can render are adjusted to the closest color that can be "
+ "rendered, while all other colors are left unchanged. Proof intent does not preserve "
+ "the white point.</li>"
+ "<li>Saturation intent preserves the saturation of colors in the image at the possible "
+ "expense of hue and lightness.<br>"
+ "Implementation of this intent remains somewhat problematic, and the ICC is still working "
+ "on methods to achieve the desired effects.<br>"
+ "This intent is most suitable for business graphics such as charts, where it is more "
+ "important that the colors be vivid and contrast well with each other rather than a "
+ "specific color.</li></ul>"));
+
+ KURLLabel *lcmsLogoLabel = new KURLLabel(generalOptions);
+ lcmsLogoLabel->setAlignment(AlignTop | AlignRight);
+ lcmsLogoLabel->setText(TQString());
+ lcmsLogoLabel->setURL("http://www.littlecms.com");
+ TDEGlobal::dirs()->addResourceType("logo-lcms", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("logo-lcms", "logo-lcms.png");
+ lcmsLogoLabel->setPixmap(TQPixmap(directory + "logo-lcms.png"));
+ TQToolTip::add(lcmsLogoLabel, i18n("Visit Little CMS project website"));
+
+ zeroPageLayout->addMultiCellWidget(m_doSoftProofBox, 0, 0, 0, 0);
+ zeroPageLayout->addMultiCellWidget(m_checkGamutBox, 1, 1, 0, 0);
+ zeroPageLayout->addMultiCellWidget(m_embeddProfileBox, 2, 2, 0, 0);
+ zeroPageLayout->addMultiCellWidget(lcmsLogoLabel, 0, 2, 1, 1);
+ zeroPageLayout->addMultiCellWidget(m_BPCBox, 3, 3, 0, 0);
+ zeroPageLayout->addMultiCellWidget(intent, 4, 4, 0, 0);
+ zeroPageLayout->addMultiCellWidget(m_renderingIntentsCB, 4, 4, 1, 1);
+ zeroPageLayout->setRowStretch(5, 10);
+
+ //---------- "Input" Page Setup ----------------------------------
+
+ m_toolBoxWidgets->insertItem(INPUTPAGE, inProfiles, SmallIconSet("camera-photo"), i18n("Input Profile"));
+ TQWhatsThis::add(inProfiles, i18n("<p>Set here all parameters relevant of Input Color "
+ "Profiles.</p>"));
+
+ TQGridLayout *firstPageLayout = new TQGridLayout(inProfiles, 4, 2);
+
+ m_inProfileBG = new TQButtonGroup(4, TQt::Vertical, inProfiles);
+ m_inProfileBG->setFrameStyle(TQFrame::NoFrame);
+ m_inProfileBG->setInsideMargin(0);
+
+ m_useEmbeddedProfile = new TQRadioButton(m_inProfileBG);
+ m_useEmbeddedProfile->setText(i18n("Use embedded profile"));
+
+ m_useSRGBDefaultProfile = new TQRadioButton(m_inProfileBG);
+ m_useSRGBDefaultProfile->setText(i18n("Use builtin sRGB profile"));
+ m_useSRGBDefaultProfile->setChecked(true);
+
+ m_useInDefaultProfile = new TQRadioButton(m_inProfileBG);
+ m_useInDefaultProfile->setText(i18n("Use default profile"));
+
+ m_useInSelectedProfile = new TQRadioButton(m_inProfileBG);
+ m_useInSelectedProfile->setText(i18n("Use selected profile"));
+
+ m_inProfilesPath = new KURLRequester(inProfiles);
+ m_inProfilesPath->setMode(KFile::File|KFile::ExistingOnly);
+ m_inProfilesPath->setFilter("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)"));
+ KFileDialog *inProfiles_dialog = m_inProfilesPath->fileDialog();
+ m_iccInPreviewWidget = new ICCPreviewWidget(inProfiles_dialog);
+ inProfiles_dialog->setPreviewWidget(m_iccInPreviewWidget);
+
+ TQPushButton *inProfilesInfo = new TQPushButton(i18n("Info..."), inProfiles);
+
+ TQGroupBox *pictureInfo = new TQGroupBox(2, TQt::Horizontal, i18n("Camera information"), inProfiles);
+ new TQLabel(i18n("Make:"), pictureInfo);
+ KSqueezedTextLabel *make = new KSqueezedTextLabel(0, pictureInfo);
+ new TQLabel(i18n("Model:"), pictureInfo);
+ KSqueezedTextLabel *model = new KSqueezedTextLabel(0, pictureInfo);
+ make->setText(iface.getPhotographInformations().make);
+ model->setText(iface.getPhotographInformations().model);
+
+ firstPageLayout->addMultiCellWidget(m_inProfileBG, 0, 1, 0, 0);
+ firstPageLayout->addMultiCellWidget(inProfilesInfo, 0, 0, 2, 2);
+ firstPageLayout->addMultiCellWidget(m_inProfilesPath, 2, 2, 0, 2);
+ firstPageLayout->addMultiCellWidget(pictureInfo, 3, 3, 0, 2);
+ firstPageLayout->setColStretch(1, 10);
+ firstPageLayout->setRowStretch(4, 10);
+
+ //---------- "Workspace" Page Setup ---------------------------------
+
+ m_toolBoxWidgets->insertItem(WORKSPACEPAGE, spaceProfiles,
+ SmallIconSet("input-tablet"), i18n("Workspace Profile"));
+ TQWhatsThis::add(spaceProfiles, i18n("<p>Set here all parameters relevant to Color Workspace "
+ "Profiles.</p>"));
+
+ TQGridLayout *secondPageLayout = new TQGridLayout(spaceProfiles, 3, 2);
+
+ m_spaceProfileBG = new TQButtonGroup(2, TQt::Vertical, spaceProfiles);
+ m_spaceProfileBG->setFrameStyle(TQFrame::NoFrame);
+ m_spaceProfileBG->setInsideMargin(0);
+
+ m_useSpaceDefaultProfile = new TQRadioButton(m_spaceProfileBG);
+ m_useSpaceDefaultProfile->setText(i18n("Use default workspace profile"));
+
+ m_useSpaceSelectedProfile = new TQRadioButton(m_spaceProfileBG);
+ m_useSpaceSelectedProfile->setText(i18n("Use selected profile"));
+
+ m_spaceProfilePath = new KURLRequester(spaceProfiles);
+ m_spaceProfilePath->setMode(KFile::File|KFile::ExistingOnly);
+ m_spaceProfilePath->setFilter("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)"));
+ KFileDialog *spaceProfiles_dialog = m_spaceProfilePath->fileDialog();
+ m_iccSpacePreviewWidget = new ICCPreviewWidget(spaceProfiles_dialog);
+ spaceProfiles_dialog->setPreviewWidget(m_iccSpacePreviewWidget);
+
+ TQPushButton *spaceProfilesInfo = new TQPushButton(i18n("Info..."), spaceProfiles);
+
+ secondPageLayout->addMultiCellWidget(m_spaceProfileBG, 0, 1, 0, 0);
+ secondPageLayout->addMultiCellWidget(spaceProfilesInfo, 0, 0, 2, 2);
+ secondPageLayout->addMultiCellWidget(m_spaceProfilePath, 2, 2, 0, 2);
+ secondPageLayout->setColStretch(1, 10);
+ secondPageLayout->setRowStretch(3, 10);
+
+ //---------- "Proofing" Page Setup ---------------------------------
+
+ m_toolBoxWidgets->insertItem(PROOFINGPAGE, proofProfiles,
+ SmallIconSet("printer"), i18n("Proofing Profile"));
+ TQWhatsThis::add(proofProfiles, i18n("<p>Set here all parameters relevant to Proofing Color "
+ "Profiles.</p>"));
+
+ TQGridLayout *thirdPageLayout = new TQGridLayout(proofProfiles, 3, 2);
+
+ m_proofProfileBG = new TQButtonGroup(2, TQt::Vertical, proofProfiles);
+ m_proofProfileBG->setFrameStyle(TQFrame::NoFrame);
+ m_proofProfileBG->setInsideMargin(0);
+
+ m_useProofDefaultProfile = new TQRadioButton(m_proofProfileBG);
+ m_useProofDefaultProfile->setText(i18n("Use default proof profile"));
+
+ m_useProofSelectedProfile = new TQRadioButton(m_proofProfileBG);
+ m_useProofSelectedProfile->setText(i18n("Use selected profile"));
+
+ m_proofProfilePath = new KURLRequester(proofProfiles);
+ m_proofProfilePath->setMode(KFile::File|KFile::ExistingOnly);
+ m_proofProfilePath->setFilter("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)"));
+ KFileDialog *proofProfiles_dialog = m_proofProfilePath->fileDialog();
+ m_iccProofPreviewWidget = new ICCPreviewWidget(proofProfiles_dialog);
+ proofProfiles_dialog->setPreviewWidget(m_iccProofPreviewWidget);
+
+ TQPushButton *proofProfilesInfo = new TQPushButton(i18n("Info..."), proofProfiles);
+
+ thirdPageLayout->addMultiCellWidget(m_proofProfileBG, 0, 1, 0, 0);
+ thirdPageLayout->addMultiCellWidget(proofProfilesInfo, 0, 0, 2, 2);
+ thirdPageLayout->addMultiCellWidget(m_proofProfilePath, 2, 2, 0, 2);
+ thirdPageLayout->setColStretch(1, 10);
+ thirdPageLayout->setRowStretch(3, 10);
+
+ //---------- "Lightness" Page Setup ----------------------------------
+
+ m_toolBoxWidgets->insertItem(LIGHTNESSPAGE, lightnessadjust,
+ SmallIconSet("blend"), i18n("Lightness Adjustments"));
+ TQWhatsThis::add(lightnessadjust, i18n("<p>Set here all lightness adjustments to the target image.</p>"));
+
+ TQGridLayout *fourPageLayout = new TQGridLayout( lightnessadjust, 5, 2);
+
+ ColorGradientWidget* vGradient = new ColorGradientWidget(ColorGradientWidget::Vertical,
+ 10, lightnessadjust );
+ vGradient->setColors(TQColor("white"), TQColor("black"));
+
+ TQLabel *spacev = new TQLabel(lightnessadjust);
+ spacev->setFixedWidth(1);
+
+ m_curvesWidget = new CurvesWidget(256, 192, m_originalImage->bits(), m_originalImage->width(),
+ m_originalImage->height(), m_originalImage->sixteenBit(),
+ lightnessadjust);
+ TQWhatsThis::add( m_curvesWidget, i18n("<p>This is the curve adjustment of the image luminosity"));
+
+ TQLabel *spaceh = new TQLabel(lightnessadjust);
+ spaceh->setFixedHeight(1);
+
+ ColorGradientWidget *hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal,
+ 10,
+ lightnessadjust);
+
+ hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ m_cInput = new RIntNumInput(lightnessadjust);
+ m_cInput->input()->setLabel(i18n("Contrast:"), AlignLeft | AlignVCenter);
+ m_cInput->setRange(-100, 100, 1);
+ m_cInput->setDefaultValue(0);
+ TQWhatsThis::add( m_cInput, i18n("<p>Set here the contrast adjustment of the image."));
+
+ fourPageLayout->addMultiCellWidget(vGradient, 0, 0, 0, 0);
+ fourPageLayout->addMultiCellWidget(spacev, 0, 0, 1, 1);
+ fourPageLayout->addMultiCellWidget(m_curvesWidget, 0, 0, 2, 2);
+ fourPageLayout->addMultiCellWidget(spaceh, 1, 1, 2, 2);
+ fourPageLayout->addMultiCellWidget(hGradient, 2, 2, 2, 2);
+ fourPageLayout->addMultiCellWidget(m_cInput, 4, 4, 0, 2);
+// fourPageLayout->setRowSpacing(3);
+ fourPageLayout->setRowStretch(5, 10);
+
+ // -------------------------------------------------------------
+
+ gridSettings->addMultiCellWidget(m_toolBoxWidgets, 3, 3, 0, 2);
+
+ setToolSettings(m_gboxSettings);
+ m_gboxSettings->enableButton(EditorToolSettings::Ok, false);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(lcmsLogoLabel, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ this, TQ_SLOT(processLCMSURL(const TQString&)));
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_curvesWidget, TQ_SIGNAL(signalCurvesChanged()),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_cInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_renderingIntentsCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ //-- Check box options connections -------------------------------------------
+
+ connect(m_doSoftProofBox, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_checkGamutBox, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_BPCBox, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ //-- Button Group ICC profile options connections ----------------------------
+
+ connect(m_inProfileBG, TQ_SIGNAL(released (int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_spaceProfileBG, TQ_SIGNAL(released (int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_proofProfileBG, TQ_SIGNAL(released (int)),
+ this, TQ_SLOT(slotEffect()));
+
+ //-- url requester ICC profile connections -----------------------------------
+
+ connect(m_inProfilesPath, TQ_SIGNAL(urlSelected(const TQString&)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_spaceProfilePath, TQ_SIGNAL(urlSelected(const TQString&)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_proofProfilePath, TQ_SIGNAL(urlSelected(const TQString&)),
+ this, TQ_SLOT(slotEffect()));
+
+ //-- Image preview widget connections ----------------------------
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotSpotColorChanged( const Digikam::DColor & )));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ //-- ICC profile preview connections -----------------------------
+
+ connect(inProfilesInfo, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotInICCInfo()));
+
+ connect(spaceProfilesInfo, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotSpaceICCInfo()));
+
+ connect(proofProfilesInfo, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotProofICCInfo()));
+}
+
+ICCProofTool::~ICCProofTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void ICCProofTool::readSettings()
+{
+ TQString defaultICCPath = TDEGlobalSettings::documentPath();
+ TDEConfig* config = kapp->config();
+
+ // General settings of digiKam Color Management
+ config->setGroup("Color Management");
+
+ if (!config->readBoolEntry("EnableCM", false))
+ {
+ m_cmEnabled = false;
+ slotToggledWidgets(false);
+ }
+ else
+ {
+ m_inPath = config->readPathEntry("InProfileFile");
+ m_spacePath = config->readPathEntry("WorkProfileFile");
+ m_proofPath = config->readPathEntry("ProofProfileFile");
+
+ if (TQFile::exists(config->readPathEntry("DefaultPath")))
+ {
+ defaultICCPath = config->readPathEntry("DefaultPath");
+ }
+ else
+ {
+ TQString message = i18n("The ICC profiles path seems to be invalid. You won't be able to use the \"Default profile\"\
+ options.<p>Please fix this in the digiKam ICC setup.");
+ slotToggledWidgets( false );
+ KMessageBox::information(kapp->activeWindow(), message);
+ }
+ }
+
+ // Plugin settings.
+ config->setGroup("colormanagement Tool");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+ m_toolBoxWidgets->setCurrentIndex(config->readNumEntry("Settings Tab", GENERALPAGE));
+ m_inProfilesPath->setURL(config->readPathEntry("InputProfilePath", defaultICCPath));
+ m_proofProfilePath->setURL(config->readPathEntry("ProofProfilePath", defaultICCPath));
+ m_spaceProfilePath->setURL(config->readPathEntry("SpaceProfilePath", defaultICCPath));
+ m_renderingIntentsCB->setCurrentItem(config->readNumEntry("RenderingIntent", m_renderingIntentsCB->defaultItem()));
+ m_doSoftProofBox->setChecked(config->readBoolEntry("DoSoftProof", false));
+ m_checkGamutBox->setChecked(config->readBoolEntry("CheckGamut", false));
+ m_embeddProfileBox->setChecked(config->readBoolEntry("EmbeddProfile", true));
+ m_BPCBox->setChecked(config->readBoolEntry("BPC", true));
+ m_inProfileBG->setButton(config->readNumEntry("InputProfileMethod", 0));
+ m_spaceProfileBG->setButton(config->readNumEntry("SpaceProfileMethod", 0));
+ m_proofProfileBG->setButton(config->readNumEntry("ProofProfileMethod", 0));
+ m_cInput->setValue(config->readNumEntry("ContrastAjustment", m_cInput->defaultValue()));
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curvesWidget->curves()->curvesChannelReset(i);
+
+ m_curvesWidget->curves()->setCurveType(m_curvesWidget->m_channelType, ImageCurves::CURVE_SMOOTH);
+ m_curvesWidget->reset();
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p = config->readPointEntry(TQString("CurveAjustmentPoint%1").arg(j), &disable);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::ValueChannel, j, p);
+ }
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curvesWidget->curves()->curvesCalculateCurve(i);
+
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ICCProofTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("colormanagement Tool");
+ config->writeEntry("Settings Tab", m_toolBoxWidgets->currentIndex());
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writePathEntry("InputProfilePath", m_inProfilesPath->url());
+ config->writePathEntry("ProofProfilePath", m_proofProfilePath->url());
+ config->writePathEntry("SpaceProfilePath", m_spaceProfilePath->url());
+ config->writeEntry("RenderingIntent", m_renderingIntentsCB->currentItem());
+ config->writeEntry("DoSoftProof", m_doSoftProofBox->isChecked());
+ config->writeEntry("CheckGamut", m_checkGamutBox->isChecked());
+ config->writeEntry("EmbeddProfile", m_embeddProfileBox->isChecked());
+ config->writeEntry("BPC", m_BPCBox->isChecked());
+ config->writeEntry("InputProfileMethod", m_inProfileBG->selectedId());
+ config->writeEntry("SpaceProfileMethod", m_spaceProfileBG->selectedId());
+ config->writeEntry("ProofProfileMethod", m_proofProfileBG->selectedId());
+ config->writeEntry("ContrastAjustment", m_cInput->value());
+
+ for (int j = 0; j < 17; j++)
+ {
+ TQPoint p = m_curvesWidget->curves()->getCurvePoint(ImageHistogram::ValueChannel, j);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x() / 255);
+ p.setY(p.y() / 255);
+ }
+
+ config->writeEntry(TQString("CurveAjustmentPoint%1").arg(j), p);
+ }
+
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void ICCProofTool::processLCMSURL(const TQString& url)
+{
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+void ICCProofTool::slotSpotColorChanged(const DColor &color)
+{
+ m_curvesWidget->setCurveGuide(color);
+}
+
+void ICCProofTool::slotColorSelectedFromTarget( const DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ICCProofTool::slotChannelChanged( int channel )
+{
+ switch (channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("red"));
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("green"));
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("blue"));
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ICCProofTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ICCProofTool::slotResetSettings()
+{
+ m_cInput->blockSignals(true);
+ m_renderingIntentsCB->blockSignals(true);
+
+ m_cInput->slotReset();
+ m_renderingIntentsCB->slotReset();
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curvesWidget->curves()->curvesChannelReset(i);
+
+ m_curvesWidget->reset();
+ m_cInput->blockSignals(false);
+ m_renderingIntentsCB->blockSignals(false);
+}
+
+void ICCProofTool::slotEffect()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+ m_gboxSettings->enableButton(EditorToolSettings::Ok, true);
+ m_histogramWidget->stopHistogramComputation();
+
+ IccTransform transform;
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ ImageIface *iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool a = iface->previewHasAlpha();
+ bool sb = iface->previewSixteenBit();
+
+ DImg preview(w, h, sb, a, m_destinationPreviewData);
+
+ TQString tmpInPath = TQString();
+ TQString tmpProofPath = TQString();
+ TQString tmpSpacePath = TQString();
+
+ bool proofCondition = false;
+ bool spaceCondition = false;
+
+ //-- Input profile parameters ------------------
+
+ if (useDefaultInProfile())
+ {
+ tmpInPath = m_inPath;
+ }
+ else if (useSelectedInProfile())
+ {
+ tmpInPath = m_inProfilesPath->url();
+ TQFileInfo info(tmpInPath);
+ if (!info.exists() || !info.isReadable() || !info.isFile())
+ {
+ KMessageBox::information(kapp->activeWindow(),
+ i18n("<p>The selected ICC input profile path seems to be invalid.<p>"
+ "Please check it."));
+ return;
+ }
+ }
+
+ //-- Proof profile parameters ------------------
+
+ if (useDefaultProofProfile())
+ {
+ tmpProofPath = m_proofPath;
+ }
+ else
+ {
+ tmpProofPath = m_proofProfilePath->url();
+ TQFileInfo info(tmpProofPath);
+ if (!info.exists() || !info.isReadable() || !info.isFile())
+ {
+ KMessageBox::information(kapp->activeWindow(),
+ i18n("<p>The selected ICC proof profile path seems to be invalid.<p>"
+ "Please check it."));
+ return;
+ }
+ }
+
+ if (m_doSoftProofBox->isChecked())
+ proofCondition = tmpProofPath.isEmpty();
+
+ //-- Workspace profile parameters --------------
+
+ if (useDefaultSpaceProfile())
+ {
+ tmpSpacePath = m_spacePath;
+ }
+ else
+ {
+ tmpSpacePath = m_spaceProfilePath->url();
+ TQFileInfo info(tmpSpacePath);
+ if (!info.exists() || !info.isReadable() || !info.isFile())
+ {
+ KMessageBox::information(kapp->activeWindow(),
+ i18n("<p>Selected ICC workspace profile path seems to be invalid.<p>"
+ "Please check it."));
+ return;
+ }
+ }
+
+ spaceCondition = tmpSpacePath.isEmpty();
+
+ //-- Perform the color transformations ------------------
+
+ transform.getTransformType(m_doSoftProofBox->isChecked());
+
+ if (m_doSoftProofBox->isChecked())
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.setProfiles(tmpSpacePath, tmpProofPath, true);
+ }
+ else
+ {
+ transform.setProfiles(tmpInPath, tmpSpacePath, tmpProofPath);
+ }
+ }
+ else
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.setProfiles(tmpSpacePath);
+ }
+ else
+ {
+ transform.setProfiles(tmpInPath, tmpSpacePath);
+ }
+ }
+
+ if ( proofCondition || spaceCondition )
+ {
+ kapp->restoreOverrideCursor();
+ TQString error = i18n("<p>Your settings are not sufficient.</p>"
+ "<p>To apply a color transform, you need at least two ICC profiles:</p>"
+ "<ul><li>An \"Input\" profile.</li>"
+ "<li>A \"Workspace\" profile.</li></ul>"
+ "<p>If you want to do a \"soft-proof\" transform, in addition to these profiles "
+ "you need a \"Proof\" profile.</p>");
+ KMessageBox::information(kapp->activeWindow(), error);
+ m_gboxSettings->enableButton(EditorToolSettings::Ok, false);
+ }
+ else
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.apply(preview, m_embeddedICC, m_renderingIntentsCB->currentItem(), useBPC(),
+ m_checkGamutBox->isChecked(), useBuiltinProfile());
+ }
+ else
+ {
+ TQByteArray fakeProfile = TQByteArray();
+ transform.apply(preview, fakeProfile, m_renderingIntentsCB->currentItem(), useBPC(),
+ m_checkGamutBox->isChecked(), useBuiltinProfile());
+ }
+
+ //-- Calculate and apply the curve on image after transformation -------------
+
+ DImg preview2(w, h, sb, a, 0, false);
+ m_curvesWidget->curves()->curvesLutSetup(ImageHistogram::AlphaChannel);
+ m_curvesWidget->curves()->curvesLutProcess(preview.bits(), preview2.bits(), w, h);
+
+ //-- Adjust contrast ---------------------------------------------------------
+
+ BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(preview2);
+
+ iface->putPreviewImage(preview2.bits());
+ m_previewWidget->updatePreview();
+
+ //-- Update histogram --------------------------------------------------------
+
+ memcpy(m_destinationPreviewData, preview2.bits(), preview2.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ kapp->restoreOverrideCursor();
+ }
+}
+
+void ICCProofTool::finalRendering()
+{
+ if (!m_doSoftProofBox->isChecked())
+ {
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ ImageIface *iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool a = iface->originalHasAlpha();
+ bool sb = iface->originalSixteenBit();
+
+ if (data)
+ {
+ IccTransform transform;
+
+ DImg img(w, h, sb, a, data);
+
+ TQString tmpInPath;
+ TQString tmpProofPath;
+ TQString tmpSpacePath;
+ bool proofCondition;
+
+ //-- Input profile parameters ------------------
+
+ if (useDefaultInProfile())
+ {
+ tmpInPath = m_inPath;
+ }
+ else if (useSelectedInProfile())
+ {
+ tmpInPath = m_inProfilesPath->url();
+ TQFileInfo info(tmpInPath);
+ if (!info.exists() || !info.isReadable() || !info.isFile())
+ {
+ KMessageBox::information(kapp->activeWindow(),
+ i18n("<p>Selected ICC input profile path seems "
+ "to be invalid.<p>Please check it."));
+ return;
+ }
+ }
+
+ //-- Proof profile parameters ------------------
+
+ if (useDefaultProofProfile())
+ {
+ tmpProofPath = m_proofPath;
+ }
+ else
+ {
+ tmpProofPath = m_proofProfilePath->url();
+ TQFileInfo info(tmpProofPath);
+ if (!info.exists() || !info.isReadable() || !info.isFile())
+ {
+ KMessageBox::information(kapp->activeWindow(),
+ i18n("<p>The selected ICC proof profile path seems "
+ "to be invalid.<p>Please check it."));
+ return;
+ }
+ }
+
+ if (tmpProofPath.isNull())
+ proofCondition = false;
+
+ //-- Workspace profile parameters --------------
+
+ if (useDefaultSpaceProfile())
+ {
+ tmpSpacePath = m_spacePath;
+ }
+ else
+ {
+ tmpSpacePath = m_spaceProfilePath->url();
+ TQFileInfo info(tmpSpacePath);
+ if (!info.exists() || !info.isReadable() || !info.isFile())
+ {
+ KMessageBox::information(kapp->activeWindow(),
+ i18n("<p>Selected ICC workspace profile path seems "
+ "to be invalid.<p>Please check it."));
+ return;
+ }
+ }
+
+ //-- Perform the color transformations ------------------
+
+ transform.getTransformType(m_doSoftProofBox->isChecked());
+
+ if (m_doSoftProofBox->isChecked())
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.setProfiles( tmpSpacePath, tmpProofPath, true );
+ }
+ else
+ {
+ transform.setProfiles( tmpInPath, tmpSpacePath, tmpProofPath);
+ }
+ }
+ else
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.setProfiles( tmpSpacePath );
+ }
+ else
+ {
+ transform.setProfiles( tmpInPath, tmpSpacePath );
+ }
+ }
+
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.apply(img, m_embeddedICC, m_renderingIntentsCB->currentItem(), useBPC(),
+ m_checkGamutBox->isChecked(), useBuiltinProfile());
+ }
+ else
+ {
+ TQByteArray fakeProfile = TQByteArray();
+ transform.apply(img, fakeProfile, m_renderingIntentsCB->currentItem(), useBPC(),
+ m_checkGamutBox->isChecked(), useBuiltinProfile());
+ }
+
+ //-- Embed the workspace profile if necessary --------------------------------
+
+ if (m_embeddProfileBox->isChecked())
+ {
+ iface->setEmbeddedICCToOriginalImage(tmpSpacePath);
+ DDebug() << k_funcinfo << TQFile::encodeName(tmpSpacePath) << endl;
+ }
+
+ //-- Calculate and apply the curve on image after transformation -------------
+
+ DImg img2(w, h, sb, a, 0, false);
+ m_curvesWidget->curves()->curvesLutSetup(ImageHistogram::AlphaChannel);
+ m_curvesWidget->curves()->curvesLutProcess(img.bits(), img2.bits(), w, h);
+
+ //-- Adjust contrast ---------------------------------------------------------
+
+ BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(img2);
+
+ iface->putOriginalImage("Color Management", img2.bits());
+ delete [] data;
+ }
+
+ kapp->restoreOverrideCursor();
+ }
+}
+
+void ICCProofTool::slotToggledWidgets( bool t)
+{
+ m_useInDefaultProfile->setEnabled(t);
+ m_useProofDefaultProfile->setEnabled(t);
+ m_useSpaceDefaultProfile->setEnabled(t);
+}
+
+void ICCProofTool::slotInICCInfo()
+{
+ if (useEmbeddedProfile())
+ {
+ getICCInfo(m_embeddedICC);
+ }
+ else if (useBuiltinProfile())
+ {
+ TQString message = i18n("<p>You have selected the \"Default builtin sRGB profile\"</p>");
+ message.append(i18n("<p>This profile is built on the fly, so there is no relevant information "
+ "about it.</p>"));
+ KMessageBox::information(kapp->activeWindow(), message);
+ }
+ else if (useDefaultInProfile())
+ {
+ getICCInfo(m_inPath);
+ }
+ else if (useSelectedInProfile())
+ {
+ getICCInfo(m_inProfilesPath->url());
+ }
+}
+
+void ICCProofTool::slotProofICCInfo()
+{
+ if (useDefaultProofProfile())
+ {
+ getICCInfo(m_proofPath);
+ }
+ else
+ {
+ getICCInfo(m_proofProfilePath->url());
+ }
+}
+
+void ICCProofTool::slotSpaceICCInfo()
+{
+ if (useDefaultSpaceProfile())
+ {
+ getICCInfo(m_spacePath);
+ }
+ else
+ {
+ getICCInfo(m_spaceProfilePath->url());
+ }
+}
+
+void ICCProofTool::getICCInfo(const TQString& profile)
+{
+ if (profile.isEmpty())
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Sorry, there is no selected profile"),
+ i18n("Profile Error"));
+ return;
+ }
+
+ ICCProfileInfoDlg infoDlg(kapp->activeWindow(), profile);
+ infoDlg.exec();
+}
+
+void ICCProofTool::getICCInfo(const TQByteArray& profile)
+{
+ if (profile.isNull())
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Sorry, it seems there is no embedded profile"),
+ i18n("Profile Error"));
+ return;
+ }
+
+ ICCProfileInfoDlg infoDlg(kapp->activeWindow(), TQString(), profile);
+ infoDlg.exec();
+}
+
+void ICCProofTool::slotCMDisabledWarning()
+{
+ if (!m_cmEnabled)
+ {
+ TQString message = i18n("<p>You have not enabled Color Management in the digiKam preferences.</p>");
+ message.append(i18n("<p>\"Use of default profile\" options will be disabled now.</p>"));
+ KMessageBox::information(kapp->activeWindow(), message);
+ slotToggledWidgets(false);
+ }
+}
+
+//-- General Tab ---------------------------
+
+bool ICCProofTool::useBPC()
+{
+ return m_BPCBox->isChecked();
+}
+
+bool ICCProofTool::doProof()
+{
+ return m_doSoftProofBox->isChecked();
+}
+
+bool ICCProofTool::checkGamut()
+{
+ return m_checkGamutBox->isChecked();
+}
+
+bool ICCProofTool::embedProfile()
+{
+ return m_embeddProfileBox->isChecked();
+}
+
+//-- Input Tab ---------------------------
+
+bool ICCProofTool::useEmbeddedProfile()
+{
+ return m_useEmbeddedProfile->isChecked();
+}
+
+bool ICCProofTool::useBuiltinProfile()
+{
+ return m_useSRGBDefaultProfile->isChecked();
+}
+
+bool ICCProofTool::useDefaultInProfile()
+{
+ return m_useInDefaultProfile->isChecked();
+}
+
+bool ICCProofTool::useSelectedInProfile()
+{
+ return m_useInSelectedProfile->isChecked();
+}
+
+//-- Workspace Tab ---------------------------
+
+bool ICCProofTool::useDefaultSpaceProfile()
+{
+ return m_useSpaceDefaultProfile->isChecked();
+}
+
+//-- Proofing Tab ---------------------------
+
+bool ICCProofTool::useDefaultProofProfile()
+{
+ return m_useProofDefaultProfile->isChecked();
+}
+
+//-- Load all settings from file --------------------------------------
+
+void ICCProofTool::slotLoadSettings()
+{
+ KURL loadColorManagementFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString("*"), kapp->activeWindow(),
+ TQString(i18n("Color Management Settings File to Load")));
+ if (loadColorManagementFile.isEmpty())
+ return;
+
+ TQFile file(loadColorManagementFile.path());
+
+ if (file.open(IO_ReadOnly))
+ {
+ TQTextStream stream(&file);
+
+ if (stream.readLine() != "# Color Management Configuration File")
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" is not a Color Management settings text file.")
+ .arg(loadColorManagementFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+
+ m_renderingIntentsCB->setCurrentItem(stream.readLine().toInt());
+ m_doSoftProofBox->setChecked((bool) (stream.readLine().toUInt()));
+ m_checkGamutBox->setChecked((bool) (stream.readLine().toUInt()));
+ m_embeddProfileBox->setChecked((bool) (stream.readLine().toUInt()));
+ m_BPCBox->setChecked((bool) (stream.readLine().toUInt()));
+ m_inProfileBG->setButton(stream.readLine().toInt());
+ m_spaceProfileBG->setButton(stream.readLine().toInt());
+ m_proofProfileBG->setButton(stream.readLine().toInt());
+ m_inProfilesPath->setURL(stream.readLine());
+ m_proofProfilePath->setURL(stream.readLine());
+ m_spaceProfilePath->setURL(stream.readLine());
+ m_cInput->setValue(stream.readLine().toInt());
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curvesWidget->curves()->curvesChannelReset(i);
+
+ m_curvesWidget->curves()->setCurveType(m_curvesWidget->m_channelType, ImageCurves::CURVE_SMOOTH);
+ m_curvesWidget->reset();
+
+ for (int j = 0; j < 17; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p;
+ p.setX(stream.readLine().toInt());
+ p.setY(stream.readLine().toInt());
+
+ if (m_originalImage->sixteenBit() && p != disable)
+ {
+ p.setX(p.x() * 255);
+ p.setY(p.y() * 255);
+ }
+
+ m_curvesWidget->curves()->setCurvePoint(ImageHistogram::ValueChannel, j, p);
+ }
+
+ blockSignals(false);
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curvesWidget->curves()->curvesCalculateCurve(i);
+
+ m_histogramWidget->reset();
+ slotEffect();
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot load settings from the Color Management text file."));
+
+ file.close();
+}
+
+//-- Save all settings to file ---------------------------------------
+
+void ICCProofTool::slotSaveAsSettings()
+{
+ KURL saveColorManagementFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString(i18n("Color Management Settings File to Save")));
+ if (saveColorManagementFile.isEmpty())
+ return;
+
+ TQFile file(saveColorManagementFile.path());
+
+ if (file.open(IO_WriteOnly))
+ {
+ TQTextStream stream(&file);
+ stream << "# Color Management Configuration File\n";
+ stream << m_renderingIntentsCB->currentItem() << "\n";
+ stream << m_doSoftProofBox->isChecked() << "\n";
+ stream << m_checkGamutBox->isChecked() << "\n";
+ stream << m_embeddProfileBox->isChecked() << "\n";
+ stream << m_BPCBox->isChecked() << "\n";
+ stream << m_inProfileBG->selectedId() << "\n";
+ stream << m_spaceProfileBG->selectedId() << "\n";
+ stream << m_proofProfileBG->selectedId() << "\n";
+ stream << m_inProfilesPath->url() << "\n";
+ stream << m_proofProfilePath->url() << "\n";
+ stream << m_spaceProfilePath->url() << "\n";
+ stream << m_cInput->value() << "\n";
+
+ for (int j = 0; j < 17; j++)
+ {
+ TQPoint p = m_curvesWidget->curves()->getCurvePoint(ImageHistogram::ValueChannel, j);
+ if (m_originalImage->sixteenBit())
+ {
+ p.setX(p.x() / 255);
+ p.setY(p.y() / 255);
+ }
+ stream << p.x() << "\n";
+ stream << p.y() << "\n";
+ }
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("Cannot save settings to the Color Management text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/iccprooftool.h b/src/imageplugins/coreplugin/iccprooftool.h
new file mode 100644
index 00000000..86d93ea9
--- /dev/null
+++ b/src/imageplugins/coreplugin/iccprooftool.h
@@ -0,0 +1,209 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-12-21
+ * Description : digiKam image editor tool to correct picture
+ * colors using an ICC color profile
+ *
+ * Copyright (C) 2005-2006 by F.J. Cruz <fj.cruz@supercable.es>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef ICCPROOFTOOL_H
+#define ICCPROOFTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQCheckBox;
+class TQComboBox;
+class TQVButtonGroup;
+class TQButtonGroup;
+class TQHButtonGroup;
+class TQRadioButton;
+class TQPushButton;
+class TQToolBox;
+
+class KURLRequester;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class ICCTransform;
+class ImageWidget;
+class HistogramWidget;
+class ColorGradientWidget;
+class DColor;
+class ICCPreviewWidget;
+class CurvesWidget;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class ICCProofTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ ICCProofTool(TQObject* parent);
+ ~ICCProofTool();
+
+protected:
+
+ void finalRendering();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+
+ void getICCInfo(const TQString&);
+ void getICCInfo(const TQByteArray&);
+
+ bool useBPC();
+ bool doProof();
+ bool checkGamut();
+ bool embedProfile();
+
+ bool useEmbeddedProfile();
+ bool useBuiltinProfile();
+ bool useDefaultInProfile();
+ bool useSelectedInProfile();
+
+ bool useDefaultSpaceProfile();
+ bool useSelectedSpaceProfile();
+
+ bool useDefaultProofProfile();
+ bool useSelectedProofProfile();
+
+private slots:
+
+ void slotSaveAsSettings();
+ void slotLoadSettings();
+ void slotEffect();
+ void slotResetSettings();
+ void slotChannelChanged(int);
+ void slotScaleChanged(int);
+ void slotSpotColorChanged(const Digikam::DColor &);
+ void slotColorSelectedFromTarget(const Digikam::DColor &);
+ void slotToggledWidgets(bool);
+ void slotInICCInfo();
+ void slotProofICCInfo();
+ void slotSpaceICCInfo();
+ void slotCMDisabledWarning();
+ void processLCMSURL(const TQString&);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear = 0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel = 0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum ICCSettingsTab
+ {
+ GENERALPAGE=0,
+ INPUTPAGE,
+ WORKSPACEPAGE,
+ PROOFINGPAGE,
+ LIGHTNESSPAGE
+ };
+
+ bool m_cmEnabled;
+ bool m_hasICC;
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQCheckBox *m_doSoftProofBox;
+ TQCheckBox *m_checkGamutBox;
+ TQCheckBox *m_embeddProfileBox;
+ TQCheckBox *m_BPCBox;
+
+ TQRadioButton *m_useEmbeddedProfile;
+ TQRadioButton *m_useInDefaultProfile;
+ TQRadioButton *m_useInSelectedProfile;
+ TQRadioButton *m_useProofDefaultProfile;
+ TQRadioButton *m_useProofSelectedProfile;
+ TQRadioButton *m_useSpaceDefaultProfile;
+ TQRadioButton *m_useSpaceSelectedProfile;
+ TQRadioButton *m_useSRGBDefaultProfile;
+
+ TQString m_inPath;
+ TQString m_spacePath;
+ TQString m_proofPath;
+
+ TQButtonGroup *m_optionsBG;
+ TQButtonGroup *m_inProfileBG;
+ TQButtonGroup *m_spaceProfileBG;
+ TQButtonGroup *m_proofProfileBG;
+
+ TQHButtonGroup *m_scaleBG;
+ TQVButtonGroup *m_renderingIntentBG;
+ TQVButtonGroup *m_profilesBG;
+
+ TQByteArray m_embeddedICC;
+
+ TQToolBox *m_toolBoxWidgets;
+
+ KURLRequester *m_inProfilesPath;
+ KURLRequester *m_spaceProfilePath;
+ KURLRequester *m_proofProfilePath;
+
+ KDcrawIface::RIntNumInput *m_cInput;
+
+ KDcrawIface::RComboBox *m_renderingIntentsCB;
+
+ Digikam::DImg *m_originalImage;
+
+ Digikam::CurvesWidget *m_curvesWidget;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ICCPreviewWidget *m_iccInPreviewWidget;
+ Digikam::ICCPreviewWidget *m_iccSpacePreviewWidget;
+ Digikam::ICCPreviewWidget *m_iccProofPreviewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif // ICCPROOFTOOL_H
diff --git a/src/imageplugins/coreplugin/imageeffect_autocorrection.cpp b/src/imageplugins/coreplugin/imageeffect_autocorrection.cpp
new file mode 100644
index 00000000..290b93cb
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_autocorrection.cpp
@@ -0,0 +1,431 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-31
+ * Description : Auto-Color correction tool.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+ // TQt includes.
+
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqradiobutton.h>
+#include <tqvgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqtimer.h>
+#include <tqvbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqlistbox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <kstandarddirs.h>
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+
+// Digikam includes.
+
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "dimgimagefilters.h"
+#include "whitebalance.h"
+#include "dimg.h"
+#include "listboxpreviewitem.h"
+
+// Local includes.
+
+#include "imageeffect_autocorrection.h"
+#include "imageeffect_autocorrection.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+ImageEffect_AutoCorrection::ImageEffect_AutoCorrection(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Auto Color Correction"),
+ "autocorrection", false), m_destinationPreviewData(0L)
+{
+ setHelp("autocolorcorrectiontool.anchor", "digikam");
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new Digikam::ImageWidget("autocorrection Tool Dialog", plainPage(),
+ i18n("<p>Here you can see the auto-color correction tool "
+ "preview. You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ Digikam::ImageIface iface(0, 0);
+ m_thumbnailImage = iface.getOriginalImg()->smoothScale(128, 128, TQSize::ScaleMin);
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 4, 4, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ m_correctionTools = new TQListBox(gboxSettings);
+ m_correctionTools->setColumnMode(1);
+ m_correctionTools->setVariableWidth(false);
+ m_correctionTools->setVariableHeight(false);
+ Digikam::ListBoxWhatsThis* whatsThis = new Digikam::ListBoxWhatsThis(m_correctionTools);
+
+ TQPixmap pix = getThumbnailForEffect(AutoLevelsCorrection);
+ Digikam::ListBoxPreviewItem *item = new Digikam::ListBoxPreviewItem(pix, i18n("Auto Levels"));
+ whatsThis->add( item, i18n("<b>Auto Levels</b>:"
+ "<p>This option maximizes the tonal range in the Red, "
+ "Green, and Blue channels. It searches the image shadow and highlight "
+ "limit values and adjusts the Red, Green, and Blue channels "
+ "to a full histogram range.</p>"));
+ m_correctionTools->insertItem(item, AutoLevelsCorrection);
+
+ pix = getThumbnailForEffect(NormalizeCorrection);
+ item = new Digikam::ListBoxPreviewItem(pix, i18n("Normalize"));
+ whatsThis->add( item, i18n("<b>Normalize</b>:"
+ "<p>This option scales brightness values across the active "
+ "image so that the darkest point becomes black, and the "
+ "brightest point becomes as bright as possible without "
+ "altering its hue. This is often a \"magic fix\" for "
+ "images that are dim or washed out.</p>"));
+ m_correctionTools->insertItem(item, NormalizeCorrection);
+
+ pix = getThumbnailForEffect(EqualizeCorrection);
+ item = new Digikam::ListBoxPreviewItem(pix, i18n("Equalize"));
+ whatsThis->add( item, i18n("<b>Equalize</b>:"
+ "<p>This option adjusts the brightness of colors across the "
+ "active image so that the histogram for the value channel "
+ "is as nearly as possible flat, that is, so that each possible "
+ "brightness value appears at about the same number of pixels "
+ "as each other value. Sometimes Equalize works wonderfully at "
+ "enhancing the contrasts in an image. Other times it gives "
+ "garbage. It is a very powerful operation, which can either work "
+ "miracles on an image or destroy it.</p>"));
+ m_correctionTools->insertItem(item, EqualizeCorrection);
+
+ pix = getThumbnailForEffect(StretchContrastCorrection);
+ item = new Digikam::ListBoxPreviewItem(pix, i18n("Stretch Contrast"));
+ whatsThis->add( item, i18n("<b>Stretch Contrast</b>:"
+ "<p>This option enhances the contrast and brightness "
+ "of the RGB values of an image by stretching the lowest "
+ "and highest values to their fullest range, adjusting "
+ "everything in between.</p>"));
+ m_correctionTools->insertItem(item, StretchContrastCorrection);
+
+ pix = getThumbnailForEffect(AutoExposureCorrection);
+ item = new Digikam::ListBoxPreviewItem(pix, i18n("Auto Exposure"));
+ whatsThis->add( item, i18n("<b>Auto Exposure</b>:"
+ "<p>This option enhances the contrast and brightness "
+ "of the RGB values of an image to calculate optimal "
+ "exposition and black level using image histogram "
+ "properties.</p>"));
+ m_correctionTools->insertItem(item, AutoExposureCorrection);
+
+ // -------------------------------------------------------------
+
+ m_correctionTools->setFocus();
+ gridSettings->addMultiCellWidget(m_correctionTools, 3, 3, 0, 4);
+ gridSettings->setRowStretch(3, 10);
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_correctionTools, TQ_SIGNAL(highlighted(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+}
+
+ImageEffect_AutoCorrection::~ImageEffect_AutoCorrection()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+ delete m_previewWidget;
+}
+
+void ImageEffect_AutoCorrection::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_AutoCorrection::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_AutoCorrection::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ImageEffect_AutoCorrection::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("autocorrection Tool Dialog");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+ m_correctionTools->setCurrentItem(config->readNumEntry("Auto Correction Filter", AutoLevelsCorrection));
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ImageEffect_AutoCorrection::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("autocorrection Tool Dialog");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("Auto Correction Filter", m_correctionTools->currentItem());
+ config->sync();
+}
+
+void ImageEffect_AutoCorrection::resetValues()
+{
+ m_correctionTools->blockSignals(true);
+ m_correctionTools->setCurrentItem(AutoLevelsCorrection);
+ m_correctionTools->blockSignals(false);
+}
+
+void ImageEffect_AutoCorrection::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ autoCorrection(m_destinationPreviewData, w, h, sb, m_correctionTools->currentItem());
+
+ iface->putPreviewImage(m_destinationPreviewData);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+TQPixmap ImageEffect_AutoCorrection::getThumbnailForEffect(AutoCorrectionType type)
+{
+ Digikam::DImg thumb = m_thumbnailImage.copy();
+ autoCorrection(thumb.bits(), thumb.width(), thumb.height(), thumb.sixteenBit(), type);
+ return (thumb.convertToPixmap());
+}
+
+
+void ImageEffect_AutoCorrection::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ if (data)
+ {
+ int type = m_correctionTools->currentItem();
+ autoCorrection(data, w, h, sb, type);
+ TQString name;
+
+ switch (type)
+ {
+ case AutoLevelsCorrection:
+ name = i18n("Auto Levels");
+ break;
+
+ case NormalizeCorrection:
+ name = i18n("Normalize");
+ break;
+
+ case EqualizeCorrection:
+ name = i18n("Equalize");
+ break;
+
+ case StretchContrastCorrection:
+ name = i18n("Stretch Contrast");
+ break;
+
+ case AutoExposureCorrection:
+ name = i18n("Auto Exposure");
+ break;
+ }
+
+ iface->putOriginalImage(name, data);
+ delete [] data;
+ }
+
+ kapp->restoreOverrideCursor();
+ accept();
+}
+
+void ImageEffect_AutoCorrection::autoCorrection(uchar *data, int w, int h, bool sb, int type)
+{
+ Digikam::DImgImageFilters filter;
+
+ switch (type)
+ {
+ case AutoLevelsCorrection:
+ filter.autoLevelsCorrectionImage(data, w, h, sb);
+ break;
+
+ case NormalizeCorrection:
+ filter.normalizeImage(data, w, h, sb);
+ break;
+
+ case EqualizeCorrection:
+ filter.equalizeImage(data, w, h, sb);
+ break;
+
+ case StretchContrastCorrection:
+ filter.stretchContrastImage(data, w, h, sb);
+ break;
+
+ case AutoExposureCorrection:
+ Digikam::WhiteBalance wbFilter(sb);
+ double blackLevel;
+ double exposureLevel;
+ wbFilter.autoExposureAdjustement(data, w, h, sb, blackLevel, exposureLevel);
+ wbFilter.whiteBalance(data, w, h, sb, blackLevel, exposureLevel);
+ break;
+ }
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/imageeffect_autocorrection.h b/src/imageplugins/coreplugin/imageeffect_autocorrection.h
new file mode 100644
index 00000000..c707ac1b
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_autocorrection.h
@@ -0,0 +1,128 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-31
+ * Description : Auto-Color correction tool.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_AUTOCORRECTION_H
+#define IMAGEEFFECT_AUTOCORRECTION_H
+
+// TQt Includes.
+
+#include <tqstring.h>
+
+// Digikam include.
+
+#include "imagedlgbase.h"
+
+class TQHButtonGroup;
+class TQComboBox;
+class TQListBox;
+class TQButtonGroup;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+class DImg;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageEffect_AutoCorrection : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_AutoCorrection(TQWidget *parent);
+ ~ImageEffect_AutoCorrection();
+
+protected:
+
+ void finalRendering();
+
+private slots:
+
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+
+private:
+
+ enum AutoCorrectionType
+ {
+ AutoLevelsCorrection=0,
+ NormalizeCorrection,
+ EqualizeCorrection,
+ StretchContrastCorrection,
+ AutoExposureCorrection
+ };
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+
+ void autoCorrection(uchar *data, int w, int h, bool sb, int type);
+ TQPixmap getThumbnailForEffect(AutoCorrectionType type);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ TQListBox *m_correctionTools;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::DImg m_thumbnailImage;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_AUTOCORRECTION_H */
diff --git a/src/imageplugins/coreplugin/imageeffect_bcg.cpp b/src/imageplugins/coreplugin/imageeffect_bcg.cpp
new file mode 100644
index 00000000..9d21115d
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_bcg.cpp
@@ -0,0 +1,350 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-05
+ * Description : digiKam image editor to adjust Brightness,
+ Contrast, and Gamma of picture.
+ *
+ * Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqlabel.h>
+#include <tqvbox.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <knuminput.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kstandarddirs.h>
+
+// Digikam includes.
+
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "bcgmodifier.h"
+#include "dimg.h"
+
+// Local includes.
+
+#include "imageeffect_bcg.h"
+#include "imageeffect_bcg.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+ImageEffect_BCG::ImageEffect_BCG(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Brightness Contrast Gamma Adjustments"),
+ "bcgadjust", false)
+{
+ m_destinationPreviewData = 0L;
+ setHelp("bcgadjusttool.anchor", "digikam");
+
+ m_previewWidget = new Digikam::ImageWidget("bcgadjust Tool Dialog", plainPage(),
+ i18n("<p>Here you can see the image "
+ "brightness-contrast-gamma adjustments preview. "
+ "You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 9, 4, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Brightness:"), gboxSettings);
+ m_bInput = new KIntNumInput(gboxSettings);
+ m_bInput->setRange(-100, 100, 1, true);
+ m_bInput->setValue(0);
+ TQWhatsThis::add( m_bInput, i18n("<p>Set here the brightness adjustment of the image."));
+ gridSettings->addMultiCellWidget(label2, 3, 3, 0, 4);
+ gridSettings->addMultiCellWidget(m_bInput, 4, 4, 0, 4);
+
+ TQLabel *label3 = new TQLabel(i18n("Contrast:"), gboxSettings);
+ m_cInput = new KIntNumInput(gboxSettings);
+ m_cInput->setRange(-100, 100, 1, true);
+ m_cInput->setValue(0);
+ TQWhatsThis::add( m_cInput, i18n("<p>Set here the contrast adjustment of the image."));
+ gridSettings->addMultiCellWidget(label3, 5, 5, 0, 4);
+ gridSettings->addMultiCellWidget(m_cInput, 6, 6, 0, 4);
+
+ TQLabel *label4 = new TQLabel(i18n("Gamma:"), gboxSettings);
+ m_gInput = new KDoubleNumInput(gboxSettings);
+ m_gInput->setPrecision(2);
+ m_gInput->setRange(0.1, 3.0, 0.01, true);
+ m_gInput->setValue(1.0);
+ TQWhatsThis::add( m_gInput, i18n("<p>Set here the gamma adjustment of the image."));
+ gridSettings->addMultiCellWidget(label4, 7, 7, 0, 4);
+ gridSettings->addMultiCellWidget(m_gInput, 8, 8, 0, 4);
+
+ gridSettings->setRowStretch(9, 10);
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_bInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_cInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+
+ enableButtonOK( false );
+}
+
+ImageEffect_BCG::~ImageEffect_BCG()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+ delete m_previewWidget;
+}
+
+void ImageEffect_BCG::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_BCG::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_BCG::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ImageEffect_BCG::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("bcgadjust Tool Dialog");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+ m_bInput->setValue(config->readNumEntry("BrightnessAjustment", 0));
+ m_cInput->setValue(config->readNumEntry("ContrastAjustment", 0));
+ m_gInput->setValue(config->readDoubleNumEntry("GammaAjustment", 1.0));
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ImageEffect_BCG::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("bcgadjust Tool Dialog");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("BrightnessAjustment", m_bInput->value());
+ config->writeEntry("ContrastAjustment", m_cInput->value());
+ config->writeEntry("GammaAjustment", m_gInput->value());
+ config->sync();
+}
+
+void ImageEffect_BCG::resetValues()
+{
+ m_bInput->blockSignals(true);
+ m_cInput->blockSignals(true);
+ m_gInput->blockSignals(true);
+ m_bInput->setValue(0);
+ m_cInput->setValue(0);
+ m_gInput->setValue(1.0);
+ m_bInput->blockSignals(false);
+ m_cInput->blockSignals(false);
+ m_gInput->blockSignals(false);
+}
+
+void ImageEffect_BCG::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ double b = (double)m_bInput->value()/250.0;
+ double c = (double)(m_cInput->value()/100.0) + 1.00;
+ double g = m_gInput->value();
+
+ enableButtonOK( b != 0.0 || c != 1.0 || g != 1.0 );
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool a = iface->previewHasAlpha();
+ bool sb = iface->previewSixteenBit();
+
+ Digikam::DImg preview(w, h, sb, a, m_destinationPreviewData);
+ Digikam::BCGModifier cmod;
+ cmod.setGamma(g);
+ cmod.setBrightness(b);
+ cmod.setContrast(c);
+ cmod.applyBCG(preview);
+ iface->putPreviewImage(preview.bits());
+
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, preview.bits(), preview.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void ImageEffect_BCG::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+
+ double b = (double)m_bInput->value()/250.0;
+ double c = (double)(m_cInput->value()/100.0) + 1.00;
+ double g = m_gInput->value();
+
+ iface->setOriginalBCG(b, c, g);
+ kapp->restoreOverrideCursor();
+ accept();
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/imageeffect_bcg.h b/src/imageplugins/coreplugin/imageeffect_bcg.h
new file mode 100644
index 00000000..a9cd020b
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_bcg.h
@@ -0,0 +1,110 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-05
+ * Description : digiKam image editor to adjust Brightness,
+ Contrast, and Gamma of picture.
+ *
+ * Copyright (C) 2004 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_BCG_H
+#define IMAGEEFFECT_BCG_H
+
+// Digikam include.
+
+#include "imagedlgbase.h"
+
+class TQCheckBox;
+class TQComboBox;
+class TQHButtonGroup;
+
+class KIntNumInput;
+class KDoubleNumInput;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageEffect_BCG : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_BCG(TQWidget *parent);
+ ~ImageEffect_BCG();
+
+private slots:
+
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget( const Digikam::DColor &color );
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void finalRendering();
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ KIntNumInput *m_bInput;
+ KIntNumInput *m_cInput;
+ KDoubleNumInput *m_gInput;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_BCG_H */
diff --git a/src/imageplugins/coreplugin/imageeffect_blur.cpp b/src/imageplugins/coreplugin/imageeffect_blur.cpp
new file mode 100644
index 00000000..bd23854b
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_blur.cpp
@@ -0,0 +1,147 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-09
+ * Description : a tool to blur an image
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <knuminput.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+
+// Digikam includes.
+
+#include "ddebug.h"
+#include "imageiface.h"
+#include "dimggaussianblur.h"
+
+// Local includes.
+
+#include "imageeffect_blur.h"
+#include "imageeffect_blur.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+ImageEffect_Blur::ImageEffect_Blur(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Apply Gaussian Blur on Photograph"),
+ "gaussianblur", false, true, true)
+{
+ setHelp("blursharpentool.anchor", "digikam");
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 1, 1, 0, spacingHint());
+ TQLabel *label = new TQLabel(i18n("Smoothness:"), gboxSettings);
+
+ m_radiusInput = new KIntNumInput(gboxSettings);
+ m_radiusInput->setRange(0, 100, 1, true);
+ m_radiusInput->setValue(0);
+ TQWhatsThis::add( m_radiusInput, i18n("<p>A smoothness of 0 has no effect, "
+ "1 and above determine the Gaussian blur matrix radius "
+ "that determines how much to blur the image."));
+
+ gridSettings->addMultiCellWidget(label, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_radiusInput, 1, 1, 0, 1);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+}
+
+ImageEffect_Blur::~ImageEffect_Blur()
+{
+}
+
+void ImageEffect_Blur::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("gaussianblur Tool Dialog");
+ m_radiusInput->setValue(config->readNumEntry("RadiusAjustment", 0));
+}
+
+void ImageEffect_Blur::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("gaussianblur Tool Dialog");
+ config->writeEntry("RadiusAjustment", m_radiusInput->value());
+ config->sync();
+}
+
+void ImageEffect_Blur::resetValues(void)
+{
+ m_radiusInput->blockSignals(true);
+ m_radiusInput->setValue(0);
+ m_radiusInput->blockSignals(false);
+}
+
+void ImageEffect_Blur::prepareEffect()
+{
+ m_radiusInput->setEnabled(false);
+
+ Digikam::DImg img = m_imagePreviewWidget->getOriginalRegionImage();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>
+ (new Digikam::DImgGaussianBlur(&img, this, m_radiusInput->value()));
+}
+
+void ImageEffect_Blur::prepareFinal()
+{
+ m_radiusInput->setEnabled(false);
+
+ Digikam::ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sixteenBit = iface.originalSixteenBit();
+ bool hasAlpha = iface.originalHasAlpha();
+ Digikam::DImg orgImage = Digikam::DImg(w, h, sixteenBit, hasAlpha ,data);
+ delete [] data;
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>
+ (new Digikam::DImgGaussianBlur(&orgImage, this, m_radiusInput->value()));
+}
+
+void ImageEffect_Blur::putPreviewData(void)
+{
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage();
+ m_imagePreviewWidget->setPreviewImage(imDest);
+}
+
+void ImageEffect_Blur::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage();
+ iface.putOriginalImage(i18n("Gaussian Blur"), imDest.bits());
+}
+
+void ImageEffect_Blur::renderingFinished(void)
+{
+ m_radiusInput->setEnabled(true);
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/imageeffect_blur.h b/src/imageplugins/coreplugin/imageeffect_blur.h
new file mode 100644
index 00000000..eab7694e
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_blur.h
@@ -0,0 +1,68 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-09
+ * Description : a tool to blur an image
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_BLUR_H
+#define IMAGEEFFECT_BLUR_H
+
+// Digikam include.
+
+#include "ctrlpaneldlg.h"
+
+class KIntNumInput;
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageEffect_Blur : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Blur(TQWidget *parent);
+ ~ImageEffect_Blur();
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KIntNumInput *m_radiusInput;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_BLUR_H */
diff --git a/src/imageplugins/coreplugin/imageeffect_bwsepia.cpp b/src/imageplugins/coreplugin/imageeffect_bwsepia.cpp
new file mode 100644
index 00000000..7dcdf0da
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_bwsepia.cpp
@@ -0,0 +1,1183 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-06
+ * Description : Black and White conversion tool.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+ // TQt includes.
+
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqlistbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqtimer.h>
+#include <tqcombobox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqintdict.h>
+#include <tqtextstream.h>
+#include <tqfile.h>
+#include <tqvbox.h>
+
+// KDE includes.
+
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <tdemessagebox.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+#include <tdeapplication.h>
+#include <knuminput.h>
+#include <ktabwidget.h>
+#include <tdeconfig.h>
+
+// Digikam includes.
+
+#include "imageiface.h"
+#include "imagehistogram.h"
+#include "dimgimagefilters.h"
+#include "imagewidget.h"
+#include "imagecurves.h"
+#include "histogramwidget.h"
+#include "curveswidget.h"
+#include "colorgradientwidget.h"
+#include "dimg.h"
+#include "bcgmodifier.h"
+#include "listboxpreviewitem.h"
+
+// Local includes.
+
+#include "imageeffect_bwsepia.h"
+#include "imageeffect_bwsepia.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+class PreviewPixmapFactory : public TQObject
+{
+public:
+
+ PreviewPixmapFactory(ImageEffect_BWSepia* bwSepia);
+
+ void invalidate() { m_previewPixmapMap.clear(); }
+
+ const TQPixmap* pixmap(int id);
+
+private:
+
+ TQPixmap makePixmap(int id);
+
+ TQIntDict<TQPixmap> m_previewPixmapMap;
+ ImageEffect_BWSepia *m_bwSepia;
+};
+
+PreviewPixmapFactory::PreviewPixmapFactory(ImageEffect_BWSepia* bwSepia)
+ : TQObject(bwSepia), m_bwSepia(bwSepia)
+{
+ m_previewPixmapMap.setAutoDelete(true);
+}
+
+const TQPixmap* PreviewPixmapFactory::pixmap(int id)
+{
+ if (m_previewPixmapMap.find(id) == 0)
+ {
+ TQPixmap pix = makePixmap(id);
+ m_previewPixmapMap.insert(id, new TQPixmap(pix));
+ }
+
+ TQPixmap* res = m_previewPixmapMap[id];
+
+ return res;
+}
+
+TQPixmap PreviewPixmapFactory::makePixmap(int id)
+{
+ return m_bwSepia->getThumbnailForEffect(id);
+}
+
+// -----------------------------------------------------------------------------------
+
+class ListBoxBWPreviewItem : public Digikam::ListBoxPreviewItem
+{
+
+public:
+
+ ListBoxBWPreviewItem(TQListBox *listbox, const TQString &text,
+ PreviewPixmapFactory* factory, int id)
+ : ListBoxPreviewItem(listbox, TQPixmap(), text)
+ {
+ m_previewPixmapFactory = factory;
+ m_id = id;
+ };
+
+ virtual const TQPixmap* pixmap() const;
+
+private:
+
+ int m_id;
+ PreviewPixmapFactory* m_previewPixmapFactory;
+};
+
+const TQPixmap* ListBoxBWPreviewItem::pixmap() const
+{
+ return m_previewPixmapFactory->pixmap(m_id);
+}
+
+// -----------------------------------------------------------------------------------
+
+ImageEffect_BWSepia::ImageEffect_BWSepia(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Convert to Black & White"),
+ "convertbw", true, false),
+ m_destinationPreviewData(0L),
+ m_channelCB(0),
+ m_scaleBG(0),
+ m_bwFilters(0),
+ m_bwTone(0),
+ m_cInput(0),
+ m_tab(0),
+ m_previewWidget(0),
+ m_histogramWidget(0),
+ m_curvesWidget(0),
+ m_curves(0),
+ m_originalImage(0),
+ m_previewPixmapFactory(0)
+{
+ setHelp("blackandwhitetool.anchor", "digikam");
+
+ Digikam::ImageIface iface(0, 0);
+ m_originalImage = iface.getOriginalImg();
+ m_thumbnailImage = m_originalImage->smoothScale(128, 128, TQSize::ScaleMin);
+ m_curves = new Digikam::ImageCurves(m_originalImage->sixteenBit());
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new Digikam::ImageWidget("convertbw Tool Dialog", plainPage(),
+ i18n("<p>Here you can see the black and white conversion tool preview. "
+ "You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 4, 4, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ m_tab = new KTabWidget(gboxSettings);
+
+ m_bwFilm = new TQListBox(m_tab);
+ m_bwFilm->setColumnMode(1);
+ m_bwFilm->setVariableWidth(false);
+ m_bwFilm->setVariableHeight(false);
+ Digikam::ListBoxWhatsThis* whatsThis2 = new Digikam::ListBoxWhatsThis(m_bwFilm);
+ m_previewPixmapFactory = new PreviewPixmapFactory(this);
+
+ int type = BWGeneric;
+
+ ListBoxBWPreviewItem *item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Generic"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Generic</b>:"
+ "<p>Simulate a generic black and white film</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Agfa 200X"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Agfa 200X</b>:"
+ "<p>Simulate the Agfa 200X black and white film at 200 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Agfa Pan 25"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Agfa Pan 25</b>:"
+ "<p>Simulate the Agfa Pan black and white film at 25 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Agfa Pan 100"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Agfa Pan 100</b>:"
+ "<p>Simulate the Agfa Pan black and white film at 100 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Agfa Pan 400"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Agfa Pan 400</b>:"
+ "<p>Simulate the Agfa Pan black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford Delta 100"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford Delta 100</b>:"
+ "<p>Simulate the Ilford Delta black and white film at 100 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford Delta 400"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford Delta 400</b>:"
+ "<p>Simulate the Ilford Delta black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford Delta 400 Pro 3200"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford Delta 400 Pro 3200</b>:"
+ "<p>Simulate the Ilford Delta 400 Pro black and white film at 3200 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford FP4 Plus"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford FP4 Plus</b>:"
+ "<p>Simulate the Ilford FP4 Plus black and white film at 125 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford HP5 Plus"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford HP5 Plus</b>:"
+ "<p>Simulate the Ilford HP5 Plus black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford PanF Plus"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford PanF Plus</b>:"
+ "<p>Simulate the Ilford PanF Plus black and white film at 50 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Ilford XP2 Super"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Ilford XP2 Super</b>:"
+ "<p>Simulate the Ilford XP2 Super black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Kodak Tmax 100"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Kodak Tmax 100</b>:"
+ "<p>Simulate the Kodak Tmax black and white film at 100 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Kodak Tmax 400"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Kodak Tmax 400</b>:"
+ "<p>Simulate the Kodak Tmax black and white film at 400 ISO</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilm, i18n("Kodak TriX"), m_previewPixmapFactory, type);
+ whatsThis2->add( item, i18n("<b>Kodak TriX</b>:"
+ "<p>Simulate the Kodak TriX black and white film at 400 ISO</p>"));
+
+ // -------------------------------------------------------------
+
+ TQVBox *vbox = new TQVBox(m_tab);
+ vbox->setSpacing(spacingHint());
+
+ m_bwFilters = new TQListBox(vbox);
+ m_bwFilters->setColumnMode(1);
+ m_bwFilters->setVariableWidth(false);
+ m_bwFilters->setVariableHeight(false);
+ Digikam::ListBoxWhatsThis* whatsThis = new Digikam::ListBoxWhatsThis(m_bwFilters);
+
+ type = BWNoFilter;
+
+ item = new ListBoxBWPreviewItem(m_bwFilters,
+ i18n("No Lens Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>No Lens Filter</b>:"
+ "<p>Do not apply a lens filter when rendering the image.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilters, i18n("Green Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>Black & White with Green Filter</b>:"
+ "<p>Simulate black and white film exposure using a green filter. "
+ "This is usefule for all scenic shoots, especially portraits "
+ "photographed against the sky.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilters, i18n("Orange Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>Black & White with Orange Filter</b>:"
+ "<p>Simulate black and white film exposure using an orange filter. "
+ "This will enhance landscapes, marine scenes and aerial "
+ "photography.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilters, i18n("Red Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>Black & White with Red Filter</b>:"
+ "<p>Simulate black and white film exposure using a red filter. "
+ "This creates dramatic sky effects, and simulates moonlight scenes "
+ "in the daytime.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwFilters, i18n("Yellow Filter"), m_previewPixmapFactory, type);
+ whatsThis->add( item, i18n("<b>Black & White with Yellow Filter</b>:"
+ "<p>Simulate black and white film exposure using a yellow filter. "
+ "This has the most natural tonal correction, and improves contrast. Ideal for "
+ "landscapes.</p>"));
+
+ m_strengthInput = new KIntNumInput(vbox);
+ m_strengthInput->setLabel(i18n("Strength:"), AlignLeft | AlignVCenter);
+ m_strengthInput->setRange(1, 5, 1, true);
+ m_strengthInput->setValue(1);
+ TQWhatsThis::add(m_strengthInput, i18n("<p>Here, set the strength adjustment of the lens filter."));
+
+ // -------------------------------------------------------------
+
+ m_bwTone = new TQListBox(m_tab);
+ m_bwTone->setColumnMode(1);
+ m_bwTone->setVariableWidth(false);
+ m_bwTone->setVariableHeight(false);
+ Digikam::ListBoxWhatsThis* whatsThis3 = new Digikam::ListBoxWhatsThis(m_bwTone);
+
+ type = BWNoTone;
+
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("No Tone Filter"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>No Tone Filter</b>:"
+ "<p>Do not apply a tone filter to the image.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Sepia Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Sepia Tone</b>:"
+ "<p>Gives a warm highlight and mid-tone while adding a bit of coolness to "
+ "the shadows - very similar to the process of bleaching a print and "
+ "re-developing in a sepia toner.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Brown Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Brown Tone</b>:"
+ "<p>This filter is more neutral than the Sepia Tone "
+ "filter.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Cold Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Cold Tone</b>:"
+ "<p>Start subtle and replicates printing on a cold tone black and white "
+ "paper such as a bromide enlarging "
+ "paper.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Selenium Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Selenium Tone</b>:"
+ "<p>This effect replicates traditional selenium chemical toning done "
+ "in the darkroom.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Platinum Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with Platinum Tone</b>:"
+ "<p>This effect replicates traditional platinum chemical toning done "
+ "in the darkroom.</p>"));
+
+ ++type;
+ item = new ListBoxBWPreviewItem(m_bwTone, i18n("Green Tone"), m_previewPixmapFactory, type);
+ whatsThis3->add( item, i18n("<b>Black & White with greenish tint</b>:"
+ "<p>This effect is also known as Verdante.</p>"));
+
+ // -------------------------------------------------------------
+
+ TQWidget *curveBox = new TQWidget( m_tab );
+ TQGridLayout *gridTab2 = new TQGridLayout(curveBox, 5, 2, spacingHint(), 0);
+
+ Digikam::ColorGradientWidget* vGradient = new Digikam::ColorGradientWidget(
+ Digikam::ColorGradientWidget::Vertical,
+ 10, curveBox );
+ vGradient->setColors( TQColor( "white" ), TQColor( "black" ) );
+
+ TQLabel *spacev = new TQLabel(curveBox);
+ spacev->setFixedWidth(1);
+
+ m_curvesWidget = new Digikam::CurvesWidget(256, 256, m_originalImage->bits(), m_originalImage->width(),
+ m_originalImage->height(), m_originalImage->sixteenBit(),
+ m_curves, curveBox);
+ TQWhatsThis::add( m_curvesWidget, i18n("<p>This is the curve adjustment of the image luminosity"));
+
+ TQLabel *spaceh = new TQLabel(curveBox);
+ spaceh->setFixedHeight(1);
+
+ Digikam::ColorGradientWidget *hGradient = new Digikam::ColorGradientWidget(
+ Digikam::ColorGradientWidget::Horizontal,
+ 10, curveBox );
+ hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ m_cInput = new KIntNumInput(curveBox);
+ m_cInput->setLabel(i18n("Contrast:"), AlignLeft | AlignVCenter);
+ m_cInput->setRange(-100, 100, 1, true);
+ m_cInput->setValue(0);
+ TQWhatsThis::add( m_cInput, i18n("<p>Set here the contrast adjustment of the image."));
+
+ gridTab2->addMultiCellWidget(vGradient, 0, 0, 0, 0);
+ gridTab2->addMultiCellWidget(spacev, 0, 0, 1, 1);
+ gridTab2->addMultiCellWidget(m_curvesWidget, 0, 0, 2, 2);
+ gridTab2->addMultiCellWidget(spaceh, 1, 1, 2, 2);
+ gridTab2->addMultiCellWidget(hGradient, 2, 2, 2, 2);
+ gridTab2->addMultiCellWidget(m_cInput, 4, 4, 0, 2);
+ gridTab2->setRowSpacing(3, spacingHint());
+ gridTab2->setRowStretch(5, 10);
+
+ // -------------------------------------------------------------
+
+ m_tab->insertTab(m_bwFilm, i18n("Film"), FilmTab);
+ m_tab->insertTab(vbox, i18n("Lens Filters"), BWFiltersTab);
+ m_tab->insertTab(m_bwTone, i18n("Tone"), ToneTab);
+ m_tab->insertTab(curveBox, i18n("Lightness"), LuminosityTab);
+
+ gridSettings->addMultiCellWidget(m_tab, 3, 3, 0, 4);
+ gridSettings->setRowStretch(3, 10);
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotSpotColorChanged(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_bwFilters, TQ_SIGNAL(highlighted(int)),
+ this, TQ_SLOT(slotFilterSelected(int)));
+
+ connect(m_strengthInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_bwFilm, TQ_SIGNAL(highlighted(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_bwTone, TQ_SIGNAL(highlighted(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_curvesWidget, TQ_SIGNAL(signalCurvesChanged()),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_cInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+}
+
+ImageEffect_BWSepia::~ImageEffect_BWSepia()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+ delete m_previewWidget;
+ delete m_curvesWidget;
+ delete m_curves;
+}
+
+void ImageEffect_BWSepia::slotFilterSelected(int filter)
+{
+ if (filter == BWNoFilter)
+ m_strengthInput->setEnabled(false);
+ else
+ m_strengthInput->setEnabled(true);
+
+ slotEffect();
+}
+
+TQPixmap ImageEffect_BWSepia::getThumbnailForEffect(int type)
+{
+ Digikam::DImg thumb = m_thumbnailImage.copy();
+ int w = thumb.width();
+ int h = thumb.height();
+ bool sb = thumb.sixteenBit();
+ bool a = thumb.hasAlpha();
+
+ if (type < BWGeneric)
+ {
+ // In Filter view, we will render a preview of the B&W filter with the generic B&W film.
+ blackAndWhiteConversion(thumb.bits(), w, h, sb, type);
+ blackAndWhiteConversion(thumb.bits(), w, h, sb, BWGeneric);
+ }
+ else
+ {
+ // In Film and Tone view, we will render the preview without to use the B&W Filter
+ blackAndWhiteConversion(thumb.bits(), w, h, sb, type);
+ }
+
+ if (m_curves) // in case we're called before the creator is done
+ {
+ uchar *targetData = new uchar[w*h*(sb ? 8 : 4)];
+ m_curves->curvesLutSetup(Digikam::ImageHistogram::AlphaChannel);
+ m_curves->curvesLutProcess(thumb.bits(), targetData, w, h);
+
+ Digikam::DImg preview(w, h, sb, a, targetData);
+ Digikam::BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(preview);
+
+ thumb.putImageData(preview.bits());
+
+ delete [] targetData;
+ }
+ return (thumb.convertToPixmap());
+}
+
+void ImageEffect_BWSepia::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_BWSepia::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+ m_curvesWidget->m_scaleType = scale;
+ m_curvesWidget->repaint(false);
+}
+
+void ImageEffect_BWSepia::slotSpotColorChanged(const Digikam::DColor &color)
+{
+ m_curvesWidget->setCurveGuide(color);
+}
+
+void ImageEffect_BWSepia::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ImageEffect_BWSepia::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("convertbw Tool Dialog");
+
+ m_tab->setCurrentPage(config->readNumEntry("Settings Tab", BWFiltersTab));
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+ m_bwFilters->setCurrentItem(config->readNumEntry("BW Filter", 0));
+ m_bwFilm->setCurrentItem(config->readNumEntry("BW Film", 0));
+ m_bwTone->setCurrentItem(config->readNumEntry("BW Tone", 0));
+ m_cInput->setValue(config->readNumEntry("ContrastAjustment", 0));
+ m_strengthInput->setValue(config->readNumEntry("StrengthAjustment", 1));
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curves->curvesChannelReset(i);
+
+ m_curves->setCurveType(m_curvesWidget->m_channelType, Digikam::ImageCurves::CURVE_SMOOTH);
+ m_curvesWidget->reset();
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p = config->readPointEntry(TQString("CurveAjustmentPoint%1").arg(j), &disable);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+
+ m_curves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, j, p);
+ }
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curves->curvesCalculateCurve(i);
+
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+ slotFilterSelected(m_bwFilters->currentItem());
+}
+
+void ImageEffect_BWSepia::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("convertbw Tool Dialog");
+ config->writeEntry("Settings Tab", m_tab->currentPageIndex());
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("BW Filter", m_bwFilters->currentItem());
+ config->writeEntry("BW Film", m_bwFilm->currentItem());
+ config->writeEntry("BW Tone", m_bwTone->currentItem());
+ config->writeEntry("ContrastAjustment", m_cInput->value());
+ config->writeEntry("StrengthAjustment", m_strengthInput->value());
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint p = m_curves->getCurvePoint(Digikam::ImageHistogram::ValueChannel, j);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()/255);
+ p.setY(p.y()/255);
+ }
+
+ config->writeEntry(TQString("CurveAjustmentPoint%1").arg(j), p);
+ }
+
+ config->sync();
+}
+
+void ImageEffect_BWSepia::resetValues()
+{
+ m_bwFilters->blockSignals(true);
+ m_bwTone->blockSignals(true);
+ m_cInput->blockSignals(true);
+ m_strengthInput->blockSignals(true);
+
+ m_bwFilters->setCurrentItem(0);
+ m_bwFilters->setSelected(0, true);
+
+ m_bwTone->setCurrentItem(0);
+ m_bwTone->setSelected(0, true);
+
+ m_cInput->setValue(0);
+
+ for (int channel = 0 ; channel < 5 ; channel++)
+ m_curves->curvesChannelReset(channel);
+
+ m_curvesWidget->reset();
+
+ m_cInput->blockSignals(false);
+ m_bwTone->blockSignals(false);
+ m_bwFilters->blockSignals(false);
+ m_strengthInput->blockSignals(false);
+
+ m_histogramWidget->reset();
+ m_previewPixmapFactory->invalidate();
+ m_bwFilters->triggerUpdate(false);
+ m_bwTone->triggerUpdate(false);
+}
+
+void ImageEffect_BWSepia::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ m_histogramWidget->stopHistogramComputation();
+
+ delete [] m_destinationPreviewData;
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool a = iface->previewHasAlpha();
+ bool sb = iface->previewSixteenBit();
+
+ // Apply black and white filter.
+
+ blackAndWhiteConversion(m_destinationPreviewData, w, h, sb, m_bwFilters->currentItem());
+
+ // Apply black and white film type.
+
+ blackAndWhiteConversion(m_destinationPreviewData, w, h, sb, m_bwFilm->currentItem() + BWGeneric);
+
+ // Apply color tone filter.
+
+ blackAndWhiteConversion(m_destinationPreviewData, w, h, sb, m_bwTone->currentItem() + BWNoTone);
+
+ // Calculate and apply the curve on image.
+
+ uchar *targetData = new uchar[w*h*(sb ? 8 : 4)];
+ m_curves->curvesLutSetup(Digikam::ImageHistogram::AlphaChannel);
+ m_curves->curvesLutProcess(m_destinationPreviewData, targetData, w, h);
+
+ // Adjust contrast.
+
+ Digikam::DImg preview(w, h, sb, a, targetData);
+ Digikam::BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(preview);
+ iface->putPreviewImage(preview.bits());
+
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, preview.bits(), preview.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ delete [] targetData;
+
+ kapp->restoreOverrideCursor();
+}
+
+void ImageEffect_BWSepia::slotTimer()
+{
+ Digikam::ImageDlgBase::slotTimer();
+ if (m_previewPixmapFactory && m_bwFilters && m_bwTone)
+ {
+ m_previewPixmapFactory->invalidate();
+ m_bwFilters->triggerUpdate(false);
+ m_bwTone->triggerUpdate(false);
+ }
+}
+
+void ImageEffect_BWSepia::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool a = iface->originalHasAlpha();
+ bool sb = iface->originalSixteenBit();
+
+ if (data)
+ {
+ // Apply black and white filter.
+
+ blackAndWhiteConversion(data, w, h, sb, m_bwFilters->currentItem());
+
+ // Apply black and white film type.
+
+ blackAndWhiteConversion(data, w, h, sb, m_bwFilm->currentItem() + BWGeneric);
+
+ // Apply color tone filter.
+
+ blackAndWhiteConversion(data, w, h, sb, m_bwTone->currentItem() + BWNoTone);
+
+ // Calculate and apply the curve on image.
+
+ uchar *targetData = new uchar[w*h*(sb ? 8 : 4)];
+ m_curves->curvesLutSetup(Digikam::ImageHistogram::AlphaChannel);
+ m_curves->curvesLutProcess(data, targetData, w, h);
+
+ // Adjust contrast.
+
+ Digikam::DImg img(w, h, sb, a, targetData);
+ Digikam::BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(img);
+
+ iface->putOriginalImage(i18n("Convert to Black && White"), img.bits());
+
+ delete [] data;
+ delete [] targetData;
+ }
+
+ kapp->restoreOverrideCursor();
+ accept();
+}
+
+void ImageEffect_BWSepia::blackAndWhiteConversion(uchar *data, int w, int h, bool sb, int type)
+{
+ // Value to multiply RGB 8 bits component of mask used by changeTonality() method.
+ int mul = sb ? 255 : 1;
+ Digikam::DImgImageFilters filter;
+ double strength = 1.0 + ((double)m_strengthInput->value() - 1.0) * (1.0 / 3.0);
+
+ switch (type)
+ {
+ case BWNoFilter:
+ m_redAttn = 0.0;
+ m_greenAttn = 0.0;
+ m_blueAttn = 0.0;
+ break;
+
+ case BWGreenFilter:
+ m_redAttn = -0.20 * strength;
+ m_greenAttn = +0.11 * strength;
+ m_blueAttn = +0.09 * strength;
+ break;
+
+ case BWOrangeFilter:
+ m_redAttn = +0.48 * strength;
+ m_greenAttn = -0.37 * strength;
+ m_blueAttn = -0.11 * strength;
+ break;
+
+ case BWRedFilter:
+ m_redAttn = +0.60 * strength;
+ m_greenAttn = -0.49 * strength;
+ m_blueAttn = -0.11 * strength;
+ break;
+
+ case BWYellowFilter:
+ m_redAttn = +0.30 * strength;
+ m_greenAttn = -0.31 * strength;
+ m_blueAttn = +0.01 * strength;
+ break;
+
+ // --------------------------------------------------------------------------------
+
+ case BWGeneric:
+ case BWNoTone:
+ m_redMult = 0.24;
+ m_greenMult = 0.68;
+ m_blueMult = 0.08;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWAgfa200X:
+ m_redMult = 0.18;
+ m_greenMult = 0.41;
+ m_blueMult = 0.41;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWAgfapan25:
+ m_redMult = 0.25;
+ m_greenMult = 0.39;
+ m_blueMult = 0.36;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWAgfapan100:
+ m_redMult = 0.21;
+ m_greenMult = 0.40;
+ m_blueMult = 0.39;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWAgfapan400:
+ m_redMult = 0.20;
+ m_greenMult = 0.41;
+ m_blueMult = 0.39;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordDelta100:
+ m_redMult = 0.21;
+ m_greenMult = 0.42;
+ m_blueMult = 0.37;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordDelta400:
+ m_redMult = 0.22;
+ m_greenMult = 0.42;
+ m_blueMult = 0.36;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordDelta400Pro3200:
+ m_redMult = 0.31;
+ m_greenMult = 0.36;
+ m_blueMult = 0.33;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordFP4:
+ m_redMult = 0.28;
+ m_greenMult = 0.41;
+ m_blueMult = 0.31;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordHP5:
+ m_redMult = 0.23;
+ m_greenMult = 0.37;
+ m_blueMult = 0.40;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordPanF:
+ m_redMult = 0.33;
+ m_greenMult = 0.36;
+ m_blueMult = 0.31;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWIlfordXP2Super:
+ m_redMult = 0.21;
+ m_greenMult = 0.42;
+ m_blueMult = 0.37;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWKodakTmax100:
+ m_redMult = 0.24;
+ m_greenMult = 0.37;
+ m_blueMult = 0.39;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWKodakTmax400:
+ m_redMult = 0.27;
+ m_greenMult = 0.36;
+ m_blueMult = 0.37;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ case BWKodakTriX:
+ m_redMult = 0.25;
+ m_greenMult = 0.35;
+ m_blueMult = 0.40;
+ filter.channelMixerImage(data, w, h, sb, true, true,
+ m_redMult + m_redMult*m_redAttn, m_greenMult + m_greenMult*m_greenAttn, m_blueMult + m_blueMult*m_blueAttn,
+ 0.0, 1.0, 0.0,
+ 0.0, 0.0, 1.0);
+ break;
+
+ // --------------------------------------------------------------------------------
+
+ case BWSepiaTone:
+ filter.changeTonality(data, w, h, sb, 162*mul, 132*mul, 101*mul);
+ break;
+
+ case BWBrownTone:
+ filter.changeTonality(data, w, h, sb, 129*mul, 115*mul, 104*mul);
+ break;
+
+ case BWColdTone:
+ filter.changeTonality(data, w, h, sb, 102*mul, 109*mul, 128*mul);
+ break;
+
+ case BWSeleniumTone:
+ filter.changeTonality(data, w, h, sb, 122*mul, 115*mul, 122*mul);
+ break;
+
+ case BWPlatinumTone:
+ filter.changeTonality(data, w, h, sb, 115*mul, 110*mul, 106*mul);
+ break;
+
+ case BWGreenTone:
+ filter.changeTonality(data, w, h, sb, 108*mul, 116*mul, 100*mul);
+ break;
+
+ }
+}
+
+//-- Load all settings from file --------------------------------------
+
+void ImageEffect_BWSepia::slotUser3()
+{
+ KURL loadFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Black & White Settings File to Load")) );
+ if( loadFile.isEmpty() )
+ return;
+
+ TQFile file(loadFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+
+ if ( stream.readLine() != "# Black & White Configuration File" )
+ {
+ KMessageBox::error(this,
+ i18n("\"%1\" is not a Black & White settings text file.")
+ .arg(loadFile.fileName()));
+ file.close();
+ return;
+ }
+
+ m_bwFilters->blockSignals(true);
+ m_bwTone->blockSignals(true);
+ m_cInput->blockSignals(true);
+
+ m_bwFilters->setCurrentItem(stream.readLine().toInt());
+ m_bwTone->setCurrentItem(stream.readLine().toInt());
+ m_cInput->setValue(stream.readLine().toInt());
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curves->curvesChannelReset(i);
+
+ m_curves->setCurveType(m_curvesWidget->m_channelType, Digikam::ImageCurves::CURVE_SMOOTH);
+ m_curvesWidget->reset();
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p;
+ p.setX( stream.readLine().toInt() );
+ p.setY( stream.readLine().toInt() );
+
+ if (m_originalImage->sixteenBit() && p != disable)
+ {
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+
+ m_curves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, j, p);
+ }
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curves->curvesCalculateCurve(i);
+
+ m_bwFilters->blockSignals(false);
+ m_bwTone->blockSignals(false);
+ m_cInput->blockSignals(false);
+
+ m_histogramWidget->reset();
+ m_previewPixmapFactory->invalidate();
+ m_bwFilters->triggerUpdate(false);
+ m_bwTone->triggerUpdate(false);
+
+ slotEffect();
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot load settings from the Black & White text file."));
+
+ file.close();
+}
+
+//-- Save all settings to file ---------------------------------------
+
+void ImageEffect_BWSepia::slotUser2()
+{
+ KURL saveFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Black & White Settings File to Save")) );
+ if( saveFile.isEmpty() )
+ return;
+
+ TQFile file(saveFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# Black & White Configuration File\n";
+ stream << m_bwFilters->currentItem() << "\n";
+ stream << m_bwTone->currentItem() << "\n";
+ stream << m_cInput->value() << "\n";
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint p = m_curves->getCurvePoint(Digikam::ImageHistogram::ValueChannel, j);
+ if (m_originalImage->sixteenBit())
+ {
+ p.setX(p.x()/255);
+ p.setY(p.y()/255);
+ }
+ stream << p.x() << "\n";
+ stream << p.y() << "\n";
+ }
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot save settings to the Black & White text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamImagesPluginCore
+
+
diff --git a/src/imageplugins/coreplugin/imageeffect_bwsepia.h b/src/imageplugins/coreplugin/imageeffect_bwsepia.h
new file mode 100644
index 00000000..74b4edf3
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_bwsepia.h
@@ -0,0 +1,195 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-06
+ * Description : Black and White conversion tool.
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2006-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+
+#ifndef IMAGEEFFECT_BWSEPIA_H
+#define IMAGEEFFECT_BWSEPIA_H
+
+// TQt Includes.
+
+#include <tqstring.h>
+
+// Digikam include.
+
+#include "imagedlgbase.h"
+
+class TQHButtonGroup;
+class TQComboBox;
+class TQButtonGroup;
+
+class KIntNumInput;
+class KTabWidget;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+class DImg;
+class ImageCurves;
+class CurvesWidget;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class PreviewPixmapFactory;
+
+class ImageEffect_BWSepia : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_BWSepia(TQWidget *parent);
+ ~ImageEffect_BWSepia();
+
+ friend class PreviewPixmapFactory;
+
+protected:
+
+ TQPixmap getThumbnailForEffect(int type);
+ void finalRendering();
+
+protected slots:
+
+ virtual void slotTimer();
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void blackAndWhiteConversion(uchar *data, int w, int h, bool sb, int type);
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotSpotColorChanged(const Digikam::DColor &color);
+ void slotColorSelectedFromTarget( const Digikam::DColor &color );
+ void slotFilterSelected(int filter);
+
+private:
+
+ enum BlackWhiteConversionType
+ {
+ BWNoFilter=0, // B&W filter to the front of lens.
+ BWGreenFilter,
+ BWOrangeFilter,
+ BWRedFilter,
+ BWYellowFilter,
+
+ BWGeneric, // B&W film simulation.
+ BWAgfa200X,
+ BWAgfapan25,
+ BWAgfapan100,
+ BWAgfapan400,
+ BWIlfordDelta100,
+ BWIlfordDelta400,
+ BWIlfordDelta400Pro3200,
+ BWIlfordFP4,
+ BWIlfordHP5,
+ BWIlfordPanF,
+ BWIlfordXP2Super,
+ BWKodakTmax100,
+ BWKodakTmax400,
+ BWKodakTriX,
+
+ BWNoTone, // Chemical color tone filter.
+ BWSepiaTone,
+ BWBrownTone,
+ BWColdTone,
+ BWSeleniumTone,
+ BWPlatinumTone,
+ BWGreenTone
+ };
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum SettingsTab
+ {
+ FilmTab=0,
+ BWFiltersTab,
+ ToneTab,
+ LuminosityTab
+ };
+
+ // Color filter attenuation in percents.
+ double m_redAttn, m_greenAttn, m_blueAttn;
+
+ // Channel mixer color multiplier.
+ double m_redMult, m_greenMult, m_blueMult;
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ TQListBox *m_bwFilters;
+ TQListBox *m_bwFilm;
+ TQListBox *m_bwTone;
+
+ KIntNumInput *m_cInput;
+ KIntNumInput *m_strengthInput;
+
+ KTabWidget *m_tab;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::CurvesWidget *m_curvesWidget;
+
+ Digikam::ImageCurves *m_curves;
+
+ Digikam::DImg *m_originalImage;
+ Digikam::DImg m_thumbnailImage;
+
+ PreviewPixmapFactory *m_previewPixmapFactory;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_BWSEPIA_H */
diff --git a/src/imageplugins/coreplugin/imageeffect_iccproof.cpp b/src/imageplugins/coreplugin/imageeffect_iccproof.cpp
new file mode 100644
index 00000000..79a09983
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_iccproof.cpp
@@ -0,0 +1,1284 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-12-21
+ * Description : digiKam image editor tool to correct picture
+ * colors using an ICC color profile
+ *
+ * Copyright (C) 2005-2006 by F.J. Cruz <fj.cruz@supercable.es>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhbox.h>
+#include <tqhbuttongroup.h>
+#include <tqvbuttongroup.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqpoint.h>
+#include <tqvbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqradiobutton.h>
+#include <tqfile.h>
+#include <tqtoolbox.h>
+#include <tqtextstream.h>
+
+// KDE includes.
+
+#include <knuminput.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+#include <kcursor.h>
+#include <kstandarddirs.h>
+#include <ktabwidget.h>
+#include <tdeconfig.h>
+#include <kurlrequester.h>
+#include <kurllabel.h>
+#include <tdefiledialog.h>
+#include <tdefile.h>
+#include <tdemessagebox.h>
+#include <tdeglobalsettings.h>
+#include <kiconloader.h>
+#include <ksqueezedtextlabel.h>
+
+// Digikam includes.
+
+#include "ddebug.h"
+#include "bcgmodifier.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagehistogram.h"
+#include "imagecurves.h"
+#include "curveswidget.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "iccpreviewwidget.h"
+#include "icctransform.h"
+#include "iccprofileinfodlg.h"
+
+// Local includes.
+
+#include "imageeffect_iccproof.h"
+#include "imageeffect_iccproof.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+ImageEffect_ICCProof::ImageEffect_ICCProof(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent,i18n("Color Management"),
+ "colormanagement", true, false)
+{
+ m_destinationPreviewData = 0;
+ m_cmEnabled = true;
+ m_hasICC = false;
+
+ setHelp("colormanagement.anchor", "digikam");
+
+ Digikam::ImageIface iface(0, 0);
+ m_originalImage = iface.getOriginalImg();
+ m_embeddedICC = iface.getEmbeddedICCFromOriginalImage();
+ m_curves = new Digikam::ImageCurves(m_originalImage->sixteenBit());
+
+ m_previewWidget = new Digikam::ImageWidget("colormanagement Tool Dialog", plainPage(),
+ i18n("<p>Here you can see the image preview after "
+ "applying a color profile</p>"));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout *gridSettings = new TQGridLayout( gboxSettings, 3, 2, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel: "), gboxSettings);
+ label1->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+ m_channelCB = new TQComboBox(false, gboxSettings);
+ m_channelCB->insertItem(i18n("Luminosity"));
+ m_channelCB->insertItem(i18n("Red"));
+ m_channelCB->insertItem(i18n("Green"));
+ m_channelCB->insertItem(i18n("Blue"));
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red channel values.<p>"
+ "<b>Green</b>: display the green channel values.<p>"
+ "<b>Blue</b>: display the blue channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal values are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal values are big; "
+ "if it is used, all values (small and large) will be visible on the "
+ "graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram "
+ "of the selected image channel. "
+ "This one is updated after setting changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10,
+ histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 2);
+
+ // -------------------------------------------------------------
+
+ m_toolBoxWidgets = new TQToolBox(gboxSettings);
+ TQWidget *generalOptions = new TQWidget(m_toolBoxWidgets);
+ TQWidget *inProfiles = new TQWidget(m_toolBoxWidgets);
+ TQWidget *spaceProfiles = new TQWidget(m_toolBoxWidgets);
+ TQWidget *proofProfiles = new TQWidget(m_toolBoxWidgets);
+ TQWidget *lightnessadjust = new TQWidget(m_toolBoxWidgets);
+
+ //---------- "General" Page Setup ----------------------------------
+
+ m_toolBoxWidgets->insertItem(GENERALPAGE, generalOptions,
+ SmallIconSet("misc"), i18n("General Settings"));
+ TQWhatsThis::add(generalOptions, i18n("<p>Here you can set general parameters.</p>"));
+
+ TQGridLayout *zeroPageLayout = new TQGridLayout(generalOptions, 5, 1, spacingHint());
+
+ m_doSoftProofBox = new TQCheckBox(generalOptions);
+ m_doSoftProofBox->setText(i18n("Soft-proofing"));
+ TQWhatsThis::add(m_doSoftProofBox, i18n("<p>Rendering emulation of the device described "
+ "by the \"Proofing\" profile. Useful to preview the final "
+ "result without rendering to physical medium.</p>"));
+
+ m_checkGamutBox = new TQCheckBox(generalOptions);
+ m_checkGamutBox->setText(i18n("Check gamut"));
+ TQWhatsThis::add(m_checkGamutBox, i18n("<p>You can use this option if you want to show "
+ "the colors that are outside the printer's gamut<p>"));
+
+ m_embeddProfileBox = new TQCheckBox(generalOptions);
+ m_embeddProfileBox->setChecked(true);
+ m_embeddProfileBox->setText(i18n("Assign profile"));
+ TQWhatsThis::add(m_embeddProfileBox, i18n("<p>You can use this option to embed "
+ "the selected workspace color profile into the image.</p>"));
+
+ m_BPCBox = new TQCheckBox(generalOptions);
+ m_BPCBox->setText(i18n("Use BPC"));
+ TQWhatsThis::add(m_BPCBox, i18n("<p>The Black Point Compensation (BPC) feature does work in conjunction "
+ "with Relative Colorimetric Intent. Perceptual intent should make no "
+ "difference, since BPC is always on, and in Absolute Colorimetric "
+ "Intent it is always turned off.</p>"
+ "<p>BPC does compensate for a lack of ICC profiles in the dark tone rendering. "
+ "With BPC the dark tones are optimally mapped (no clipping) from original media "
+ "to the destination rendering media, e.g. the combination of paper and ink.</p>"));
+
+ TQLabel *intent = new TQLabel(i18n("Rendering Intent:"), generalOptions);
+ m_renderingIntentsCB = new TQComboBox(false, generalOptions);
+ m_renderingIntentsCB->insertItem("Perceptual");
+ m_renderingIntentsCB->insertItem("Absolute Colorimetric");
+ m_renderingIntentsCB->insertItem("Relative Colorimetric");
+ m_renderingIntentsCB->insertItem("Saturation");
+ TQWhatsThis::add( m_renderingIntentsCB, i18n("<ul><li>Perceptual intent causes the full gamut "
+ "of the image to be compressed or expanded to fill the gamut of the destination media, "
+ "so that gray balance is preserved but colorimetric accuracy may not be preserved.<br>"
+ "In other words, if certain colors in an image fall outside of the range of colors that "
+ "the output device can render, the image intent will cause all the colors in the image "
+ "to be adjusted so that every color in the image falls within the range that can be "
+ "rendered and so that the relationship between colors is preserved as much as possible.<br>"
+ "This intent is most suitable for display of photographs and images, and is the default "
+ "intent.</li>"
+ "<li> Absolute Colorimetric intent causes any colors that fall outside the range that the "
+ "output device can render to be adjusted to the closest color that can be rendered, while all "
+ "other colors are left unchanged.<br>"
+ "This intent preserves the white point and is most suitable for spot colors (Pantone, "
+ "TruMatch, logo colors, ...).</li>"
+ "<li>Relative Colorimetric intent is defined such that any colors that fall outside the "
+ "range that the output device can render are adjusted to the closest color that can be "
+ "rendered, while all other colors are left unchanged. Proof intent does not preserve "
+ "the white point.</li>"
+ "<li>Saturation intent preserves the saturation of colors in the image at the possible "
+ "expense of hue and lightness.<br>"
+ "Implementation of this intent remains somewhat problematic, and the ICC is still working "
+ "on methods to achieve the desired effects.<br>"
+ "This intent is most suitable for business graphics such as charts, where it is more "
+ "important that the colors be vivid and contrast well with each other rather than a "
+ "specific color.</li></ul>"));
+
+ KURLLabel *lcmsLogoLabel = new KURLLabel(generalOptions);
+ lcmsLogoLabel->setAlignment( AlignTop | AlignRight );
+ lcmsLogoLabel->setText(TQString());
+ lcmsLogoLabel->setURL("http://www.littlecms.com");
+ TDEGlobal::dirs()->addResourceType("logo-lcms", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("logo-lcms", "logo-lcms.png");
+ lcmsLogoLabel->setPixmap( TQPixmap( directory + "logo-lcms.png" ) );
+ TQToolTip::add(lcmsLogoLabel, i18n("Visit Little CMS project website"));
+
+ zeroPageLayout->addMultiCellWidget(m_doSoftProofBox, 0, 0, 0, 0);
+ zeroPageLayout->addMultiCellWidget(m_checkGamutBox, 1, 1, 0, 0);
+ zeroPageLayout->addMultiCellWidget(m_embeddProfileBox, 2, 2, 0, 0);
+ zeroPageLayout->addMultiCellWidget(lcmsLogoLabel, 0, 2, 1, 1);
+ zeroPageLayout->addMultiCellWidget(m_BPCBox, 3, 3, 0, 0);
+ zeroPageLayout->addMultiCellWidget(intent, 4, 4, 0, 0);
+ zeroPageLayout->addMultiCellWidget(m_renderingIntentsCB, 4, 4, 1, 1);
+ zeroPageLayout->setRowStretch(5, 10);
+
+ //---------- "Input" Page Setup ----------------------------------
+
+ m_toolBoxWidgets->insertItem(INPUTPAGE, inProfiles, SmallIconSet("camera-photo"), i18n("Input Profile"));
+ TQWhatsThis::add(inProfiles, i18n("<p>Set here all parameters relevant of Input Color "
+ "Profiles.</p>"));
+
+ TQGridLayout *firstPageLayout = new TQGridLayout(inProfiles, 4, 2, spacingHint());
+
+ m_inProfileBG = new TQButtonGroup(4, TQt::Vertical, inProfiles);
+ m_inProfileBG->setFrameStyle(TQFrame::NoFrame);
+ m_inProfileBG->setInsideMargin(0);
+
+ m_useEmbeddedProfile = new TQRadioButton(m_inProfileBG);
+ m_useEmbeddedProfile->setText(i18n("Use embedded profile"));
+
+ m_useSRGBDefaultProfile = new TQRadioButton(m_inProfileBG);
+ m_useSRGBDefaultProfile->setText(i18n("Use builtin sRGB profile"));
+ m_useSRGBDefaultProfile->setChecked(true);
+
+ m_useInDefaultProfile = new TQRadioButton(m_inProfileBG);
+ m_useInDefaultProfile->setText(i18n("Use default profile"));
+
+ m_useInSelectedProfile = new TQRadioButton(m_inProfileBG);
+ m_useInSelectedProfile->setText(i18n("Use selected profile"));
+
+ m_inProfilesPath = new KURLRequester(inProfiles);
+ m_inProfilesPath->setMode(KFile::File|KFile::ExistingOnly);
+ m_inProfilesPath->setFilter("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)"));
+ KFileDialog *inProfiles_dialog = m_inProfilesPath->fileDialog();
+ m_iccInPreviewWidget = new Digikam::ICCPreviewWidget(inProfiles_dialog);
+ inProfiles_dialog->setPreviewWidget(m_iccInPreviewWidget);
+
+ TQPushButton *inProfilesInfo = new TQPushButton(i18n("Info..."), inProfiles);
+
+ TQGroupBox *pictureInfo = new TQGroupBox(2, TQt::Horizontal, i18n("Camera information"), inProfiles);
+ new TQLabel(i18n("Make:"), pictureInfo);
+ KSqueezedTextLabel *make = new KSqueezedTextLabel(0, pictureInfo);
+ new TQLabel(i18n("Model:"), pictureInfo);
+ KSqueezedTextLabel *model = new KSqueezedTextLabel(0, pictureInfo);
+ make->setText(iface.getPhotographInformations().make);
+ model->setText(iface.getPhotographInformations().model);
+
+ firstPageLayout->addMultiCellWidget(m_inProfileBG, 0, 1, 0, 0);
+ firstPageLayout->addMultiCellWidget(inProfilesInfo, 0, 0, 2, 2);
+ firstPageLayout->addMultiCellWidget(m_inProfilesPath, 2, 2, 0, 2);
+ firstPageLayout->addMultiCellWidget(pictureInfo, 3, 3, 0, 2);
+ firstPageLayout->setColStretch(1, 10);
+ firstPageLayout->setRowStretch(4, 10);
+
+ //---------- "Workspace" Page Setup ---------------------------------
+
+ m_toolBoxWidgets->insertItem(WORKSPACEPAGE, spaceProfiles,
+ SmallIconSet("input-tablet"), i18n("Workspace Profile"));
+ TQWhatsThis::add(spaceProfiles, i18n("<p>Set here all parameters relevant to Color Workspace "
+ "Profiles.</p>"));
+
+ TQGridLayout *secondPageLayout = new TQGridLayout(spaceProfiles, 3, 2, spacingHint());
+
+ m_spaceProfileBG = new TQButtonGroup(2, TQt::Vertical, spaceProfiles);
+ m_spaceProfileBG->setFrameStyle(TQFrame::NoFrame);
+ m_spaceProfileBG->setInsideMargin(0);
+
+ m_useSpaceDefaultProfile = new TQRadioButton(m_spaceProfileBG);
+ m_useSpaceDefaultProfile->setText(i18n("Use default workspace profile"));
+
+ m_useSpaceSelectedProfile = new TQRadioButton(m_spaceProfileBG);
+ m_useSpaceSelectedProfile->setText(i18n("Use selected profile"));
+
+ m_spaceProfilePath = new KURLRequester(spaceProfiles);
+ m_spaceProfilePath->setMode(KFile::File|KFile::ExistingOnly);
+ m_spaceProfilePath->setFilter("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)"));
+ KFileDialog *spaceProfiles_dialog = m_spaceProfilePath->fileDialog();
+ m_iccSpacePreviewWidget = new Digikam::ICCPreviewWidget(spaceProfiles_dialog);
+ spaceProfiles_dialog->setPreviewWidget(m_iccSpacePreviewWidget);
+
+ TQPushButton *spaceProfilesInfo = new TQPushButton(i18n("Info..."), spaceProfiles);
+
+ secondPageLayout->addMultiCellWidget(m_spaceProfileBG, 0, 1, 0, 0);
+ secondPageLayout->addMultiCellWidget(spaceProfilesInfo, 0, 0, 2, 2);
+ secondPageLayout->addMultiCellWidget(m_spaceProfilePath, 2, 2, 0, 2);
+ secondPageLayout->setColStretch(1, 10);
+ secondPageLayout->setRowStretch(3, 10);
+
+ //---------- "Proofing" Page Setup ---------------------------------
+
+ m_toolBoxWidgets->insertItem(PROOFINGPAGE, proofProfiles,
+ SmallIconSet("printer"), i18n("Proofing Profile"));
+ TQWhatsThis::add(proofProfiles, i18n("<p>Set here all parameters relevant to Proofing Color "
+ "Profiles.</p>"));
+
+ TQGridLayout *thirdPageLayout = new TQGridLayout(proofProfiles, 3, 2,
+ spacingHint(), spacingHint());
+
+ m_proofProfileBG = new TQButtonGroup(2, TQt::Vertical, proofProfiles);
+ m_proofProfileBG->setFrameStyle(TQFrame::NoFrame);
+ m_proofProfileBG->setInsideMargin(0);
+
+ m_useProofDefaultProfile = new TQRadioButton(m_proofProfileBG);
+ m_useProofDefaultProfile->setText(i18n("Use default proof profile"));
+
+ m_useProofSelectedProfile = new TQRadioButton(m_proofProfileBG);
+ m_useProofSelectedProfile->setText(i18n("Use selected profile"));
+
+ m_proofProfilePath = new KURLRequester(proofProfiles);
+ m_proofProfilePath->setMode(KFile::File|KFile::ExistingOnly);
+ m_proofProfilePath->setFilter("*.icc *.icm|"+i18n("ICC Files (*.icc; *.icm)"));
+ KFileDialog *proofProfiles_dialog = m_proofProfilePath->fileDialog();
+ m_iccProofPreviewWidget = new Digikam::ICCPreviewWidget(proofProfiles_dialog);
+ proofProfiles_dialog->setPreviewWidget(m_iccProofPreviewWidget);
+
+ TQPushButton *proofProfilesInfo = new TQPushButton(i18n("Info..."), proofProfiles);
+
+ thirdPageLayout->addMultiCellWidget(m_proofProfileBG, 0, 1, 0, 0);
+ thirdPageLayout->addMultiCellWidget(proofProfilesInfo, 0, 0, 2, 2);
+ thirdPageLayout->addMultiCellWidget(m_proofProfilePath, 2, 2, 0, 2);
+ thirdPageLayout->setColStretch(1, 10);
+ thirdPageLayout->setRowStretch(3, 10);
+
+ //---------- "Lightness" Page Setup ----------------------------------
+
+ m_toolBoxWidgets->insertItem(LIGHTNESSPAGE, lightnessadjust,
+ SmallIconSet("blend"), i18n("Lightness Adjustments"));
+ TQWhatsThis::add(lightnessadjust, i18n("<p>Set here all lightness adjustments to the target image.</p>"));
+
+ TQGridLayout *fourPageLayout = new TQGridLayout( lightnessadjust, 5, 2, spacingHint(), 0);
+
+ Digikam::ColorGradientWidget* vGradient = new Digikam::ColorGradientWidget(
+ Digikam::ColorGradientWidget::Vertical,
+ 10, lightnessadjust );
+ vGradient->setColors( TQColor( "white" ), TQColor( "black" ) );
+
+ TQLabel *spacev = new TQLabel(lightnessadjust);
+ spacev->setFixedWidth(1);
+
+ m_curvesWidget = new Digikam::CurvesWidget(256, 192, m_originalImage->bits(), m_originalImage->width(),
+ m_originalImage->height(), m_originalImage->sixteenBit(),
+ m_curves, lightnessadjust);
+ TQWhatsThis::add( m_curvesWidget, i18n("<p>This is the curve adjustment of the image luminosity"));
+
+ TQLabel *spaceh = new TQLabel(lightnessadjust);
+ spaceh->setFixedHeight(1);
+
+ Digikam::ColorGradientWidget *hGradient = new Digikam::ColorGradientWidget(
+ Digikam::ColorGradientWidget::Horizontal,
+ 10, lightnessadjust );
+ hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ m_cInput = new KIntNumInput(lightnessadjust);
+ m_cInput->setLabel(i18n("Contrast:"), AlignLeft | AlignVCenter);
+ m_cInput->setRange(-100, 100, 1, true);
+ m_cInput->setValue(0);
+ TQWhatsThis::add( m_cInput, i18n("<p>Set here the contrast adjustment of the image."));
+
+ fourPageLayout->addMultiCellWidget(vGradient, 0, 0, 0, 0);
+ fourPageLayout->addMultiCellWidget(spacev, 0, 0, 1, 1);
+ fourPageLayout->addMultiCellWidget(m_curvesWidget, 0, 0, 2, 2);
+ fourPageLayout->addMultiCellWidget(spaceh, 1, 1, 2, 2);
+ fourPageLayout->addMultiCellWidget(hGradient, 2, 2, 2, 2);
+ fourPageLayout->addMultiCellWidget(m_cInput, 4, 4, 0, 2);
+ fourPageLayout->setRowSpacing(3, spacingHint());
+ fourPageLayout->setRowStretch(5, 10);
+
+ // -------------------------------------------------------------
+
+ gridSettings->addMultiCellWidget(m_toolBoxWidgets, 3, 3, 0, 2);
+ setUserAreaWidget(gboxSettings);
+ enableButtonOK(false);
+
+ // -------------------------------------------------------------
+
+ connect(lcmsLogoLabel, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ this, TQ_SLOT(processLCMSURL(const TQString&)));
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_curvesWidget, TQ_SIGNAL(signalCurvesChanged()),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_cInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_renderingIntentsCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ //-- Check box options connections -------------------------------------------
+
+ connect(m_doSoftProofBox, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_checkGamutBox, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_BPCBox, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ //-- Button Group ICC profile options connections ----------------------------
+
+ connect(m_inProfileBG, TQ_SIGNAL(released (int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_spaceProfileBG, TQ_SIGNAL(released (int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_proofProfileBG, TQ_SIGNAL(released (int)),
+ this, TQ_SLOT(slotEffect()));
+
+ //-- url requester ICC profile connections -----------------------------------
+
+ connect(m_inProfilesPath, TQ_SIGNAL(urlSelected(const TQString&)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_spaceProfilePath, TQ_SIGNAL(urlSelected(const TQString&)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_proofProfilePath, TQ_SIGNAL(urlSelected(const TQString&)),
+ this, TQ_SLOT(slotEffect()));
+
+ //-- Image preview widget connections ----------------------------
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotSpotColorChanged( const Digikam::DColor & )));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ //-- ICC profile preview connections -----------------------------
+
+ connect(inProfilesInfo, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotInICCInfo()));
+
+ connect(spaceProfilesInfo, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotSpaceICCInfo()));
+
+ connect(proofProfilesInfo, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotProofICCInfo()));
+}
+
+ImageEffect_ICCProof::~ImageEffect_ICCProof()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ delete [] m_destinationPreviewData;
+ delete m_histogramWidget;
+ delete m_previewWidget;
+ delete m_curvesWidget;
+ delete m_curves;
+}
+
+void ImageEffect_ICCProof::readUserSettings()
+{
+ TQString defaultICCPath = TDEGlobalSettings::documentPath();
+ TDEConfig* config = kapp->config();
+
+ // General settings of digiKam Color Management
+ config->setGroup("Color Management");
+
+ if (!config->readBoolEntry("EnableCM", false))
+ {
+ m_cmEnabled = false;
+ slotToggledWidgets(false);
+ }
+ else
+ {
+ m_inPath = config->readPathEntry("InProfileFile");
+ m_spacePath = config->readPathEntry("WorkProfileFile");
+ m_proofPath = config->readPathEntry("ProofProfileFile");
+
+ if (TQFile::exists(config->readPathEntry("DefaultPath")))
+ {
+ defaultICCPath = config->readPathEntry("DefaultPath");
+ }
+ else
+ {
+ TQString message = i18n("The ICC profiles path seems to be invalid. You won't be able to use the \"Default profile\"\
+ options.<p>Please fix this in the digiKam ICC setup.");
+ slotToggledWidgets( false );
+ KMessageBox::information(this, message);
+ }
+ }
+
+ // Plugin settings.
+ config->setGroup("colormanagement Tool Dialog");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+ m_toolBoxWidgets->setCurrentIndex(config->readNumEntry("Settings Tab", GENERALPAGE));
+ m_inProfilesPath->setURL(config->readPathEntry("InputProfilePath", defaultICCPath));
+ m_proofProfilePath->setURL(config->readPathEntry("ProofProfilePath", defaultICCPath));
+ m_spaceProfilePath->setURL(config->readPathEntry("SpaceProfilePath", defaultICCPath));
+ m_renderingIntentsCB->setCurrentItem(config->readNumEntry("RenderingIntent", 0));
+ m_doSoftProofBox->setChecked(config->readBoolEntry("DoSoftProof", false));
+ m_checkGamutBox->setChecked(config->readBoolEntry("CheckGamut", false));
+ m_embeddProfileBox->setChecked(config->readBoolEntry("EmbeddProfile", true));
+ m_BPCBox->setChecked(config->readBoolEntry("BPC", true));
+ m_inProfileBG->setButton(config->readNumEntry("InputProfileMethod", 0));
+ m_spaceProfileBG->setButton(config->readNumEntry("SpaceProfileMethod", 0));
+ m_proofProfileBG->setButton(config->readNumEntry("ProofProfileMethod", 0));
+ m_cInput->setValue(config->readNumEntry("ContrastAjustment", 0));
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curves->curvesChannelReset(i);
+
+ m_curves->setCurveType(m_curvesWidget->m_channelType, Digikam::ImageCurves::CURVE_SMOOTH);
+ m_curvesWidget->reset();
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p = config->readPointEntry(TQString("CurveAjustmentPoint%1").arg(j), &disable);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+
+ m_curves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, j, p);
+ }
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curves->curvesCalculateCurve(i);
+
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ImageEffect_ICCProof::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("colormanagement Tool Dialog");
+ config->writeEntry("Settings Tab", m_toolBoxWidgets->currentIndex());
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writePathEntry("InputProfilePath", m_inProfilesPath->url());
+ config->writePathEntry("ProofProfilePath", m_proofProfilePath->url());
+ config->writePathEntry("SpaceProfilePath", m_spaceProfilePath->url());
+ config->writeEntry("RenderingIntent", m_renderingIntentsCB->currentItem());
+ config->writeEntry("DoSoftProof", m_doSoftProofBox->isChecked());
+ config->writeEntry("CheckGamut", m_checkGamutBox->isChecked());
+ config->writeEntry("EmbeddProfile", m_embeddProfileBox->isChecked());
+ config->writeEntry("BPC", m_BPCBox->isChecked());
+ config->writeEntry("InputProfileMethod", m_inProfileBG->selectedId());
+ config->writeEntry("SpaceProfileMethod", m_spaceProfileBG->selectedId());
+ config->writeEntry("ProofProfileMethod", m_proofProfileBG->selectedId());
+ config->writeEntry("ContrastAjustment", m_cInput->value());
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint p = m_curves->getCurvePoint(Digikam::ImageHistogram::ValueChannel, j);
+
+ if (m_originalImage->sixteenBit() && p.x() != -1)
+ {
+ p.setX(p.x()/255);
+ p.setY(p.y()/255);
+ }
+
+ config->writeEntry(TQString("CurveAjustmentPoint%1").arg(j), p);
+ }
+
+ config->sync();
+}
+
+void ImageEffect_ICCProof::processLCMSURL(const TQString& url)
+{
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+void ImageEffect_ICCProof::slotSpotColorChanged(const Digikam::DColor &color)
+{
+ m_curvesWidget->setCurveGuide(color);
+}
+
+void ImageEffect_ICCProof::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ImageEffect_ICCProof::slotChannelChanged( int channel )
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_ICCProof::slotScaleChanged( int scale )
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_ICCProof::resetValues()
+{
+ m_cInput->blockSignals(true);
+ m_cInput->setValue(0);
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curves->curvesChannelReset(i);
+
+ m_curvesWidget->reset();
+ m_cInput->blockSignals(false);
+}
+
+void ImageEffect_ICCProof::slotEffect()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+ enableButtonOK(true);
+ m_histogramWidget->stopHistogramComputation();
+
+ Digikam::IccTransform transform;
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ Digikam::ImageIface *iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool a = iface->previewHasAlpha();
+ bool sb = iface->previewSixteenBit();
+
+ Digikam::DImg preview(w, h, sb, a, m_destinationPreviewData);
+
+ TQString tmpInPath = TQString();
+ TQString tmpProofPath = TQString();
+ TQString tmpSpacePath = TQString();
+
+ bool proofCondition = false;
+ bool spaceCondition = false;
+
+ //-- Input profile parameters ------------------
+
+ if (useDefaultInProfile())
+ {
+ tmpInPath = m_inPath;
+ }
+ else if (useSelectedInProfile())
+ {
+ tmpInPath = m_inProfilesPath->url();
+ TQFileInfo info(tmpInPath);
+ if (!info.exists() || !info.isReadable() || !info.isFile() )
+ {
+ KMessageBox::information(this, i18n("<p>The selected ICC input profile path seems to be invalid.<p>"
+ "Please check it."));
+ return;
+ }
+ }
+
+ //-- Proof profile parameters ------------------
+
+ if (useDefaultProofProfile())
+ {
+ tmpProofPath = m_proofPath;
+ }
+ else
+ {
+ tmpProofPath = m_proofProfilePath->url();
+ TQFileInfo info(tmpProofPath);
+ if (!info.exists() || !info.isReadable() || !info.isFile() )
+ {
+ KMessageBox::information(this, i18n("<p>The selected ICC proof profile path seems to be invalid.<p>"
+ "Please check it."));
+ return;
+ }
+ }
+
+ if (m_doSoftProofBox->isChecked())
+ proofCondition = tmpProofPath.isEmpty();
+
+ //-- Workspace profile parameters --------------
+
+ if (useDefaultSpaceProfile())
+ {
+ tmpSpacePath = m_spacePath;
+ }
+ else
+ {
+ tmpSpacePath = m_spaceProfilePath->url();
+ TQFileInfo info(tmpSpacePath);
+ if (!info.exists() || !info.isReadable() || !info.isFile() )
+ {
+ KMessageBox::information(this, i18n("<p>Selected ICC workspace profile path seems to be invalid.<p>"
+ "Please check it."));
+ return;
+ }
+ }
+
+ spaceCondition = tmpSpacePath.isEmpty();
+
+ //-- Perform the color transformations ------------------
+
+ transform.getTransformType(m_doSoftProofBox->isChecked());
+
+ if (m_doSoftProofBox->isChecked())
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.setProfiles( tmpSpacePath, tmpProofPath, true );
+ }
+ else
+ {
+ transform.setProfiles( tmpInPath, tmpSpacePath, tmpProofPath);
+ }
+ }
+ else
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.setProfiles( tmpSpacePath );
+ }
+ else
+ {
+ transform.setProfiles( tmpInPath, tmpSpacePath );
+ }
+ }
+
+ if ( proofCondition || spaceCondition )
+ {
+ kapp->restoreOverrideCursor();
+ TQString error = i18n("<p>Your settings are not sufficient.</p>"
+ "<p>To apply a color transform, you need at least two ICC profiles:</p>"
+ "<ul><li>An \"Input\" profile.</li>"
+ "<li>A \"Workspace\" profile.</li></ul>"
+ "<p>If you want to do a \"soft-proof\" transform, in addition to these profiles "
+ "you need a \"Proof\" profile.</p>");
+ KMessageBox::information(this, error);
+ enableButtonOK(false);
+ }
+ else
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.apply(preview, m_embeddedICC, m_renderingIntentsCB->currentItem(), useBPC(),
+ m_checkGamutBox->isChecked(), useBuiltinProfile());
+ }
+ else
+ {
+ TQByteArray fakeProfile = TQByteArray();
+ transform.apply(preview, fakeProfile, m_renderingIntentsCB->currentItem(), useBPC(),
+ m_checkGamutBox->isChecked(), useBuiltinProfile());
+ }
+
+ //-- Calculate and apply the curve on image after transformation -------------
+
+ Digikam::DImg preview2(w, h, sb, a, 0, false);
+ m_curves->curvesLutSetup(Digikam::ImageHistogram::AlphaChannel);
+ m_curves->curvesLutProcess(preview.bits(), preview2.bits(), w, h);
+
+ //-- Adjust contrast ---------------------------------------------------------
+
+ Digikam::BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(preview2);
+
+ iface->putPreviewImage(preview2.bits());
+ m_previewWidget->updatePreview();
+
+ //-- Update histogram --------------------------------------------------------
+
+ memcpy(m_destinationPreviewData, preview2.bits(), preview2.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ kapp->restoreOverrideCursor();
+ }
+}
+
+void ImageEffect_ICCProof::finalRendering()
+{
+ if (!m_doSoftProofBox->isChecked())
+ {
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ Digikam::ImageIface *iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool a = iface->originalHasAlpha();
+ bool sb = iface->originalSixteenBit();
+
+ if (data)
+ {
+ Digikam::IccTransform transform;
+
+ Digikam::DImg img(w, h, sb, a, data);
+
+ TQString tmpInPath;
+ TQString tmpProofPath;
+ TQString tmpSpacePath;
+ bool proofCondition;
+
+ //-- Input profile parameters ------------------
+
+ if (useDefaultInProfile())
+ {
+ tmpInPath = m_inPath;
+ }
+ else if (useSelectedInProfile())
+ {
+ tmpInPath = m_inProfilesPath->url();
+ TQFileInfo info(tmpInPath);
+ if (!info.exists() || !info.isReadable() || !info.isFile() )
+ {
+ KMessageBox::information(this, i18n("<p>Selected ICC input profile path seems "
+ "to be invalid.<p>Please check it."));
+ return;
+ }
+ }
+
+ //-- Proof profile parameters ------------------
+
+ if (useDefaultProofProfile())
+ {
+ tmpProofPath = m_proofPath;
+ }
+ else
+ {
+ tmpProofPath = m_proofProfilePath->url();
+ TQFileInfo info(tmpProofPath);
+ if (!info.exists() || !info.isReadable() || !info.isFile() )
+ {
+ KMessageBox::information(this, i18n("<p>The selected ICC proof profile path seems "
+ "to be invalid.<p>Please check it."));
+ return;
+ }
+ }
+
+ if (tmpProofPath.isNull())
+ proofCondition = false;
+
+ //-- Workspace profile parameters --------------
+
+ if (useDefaultSpaceProfile())
+ {
+ tmpSpacePath = m_spacePath;
+ }
+ else
+ {
+ tmpSpacePath = m_spaceProfilePath->url();
+ TQFileInfo info(tmpSpacePath);
+ if (!info.exists() || !info.isReadable() || !info.isFile() )
+ {
+ KMessageBox::information(this, i18n("<p>Selected ICC workspace profile path seems "
+ "to be invalid.<p>Please check it."));
+ return;
+ }
+ }
+
+ //-- Perform the color transformations ------------------
+
+ transform.getTransformType(m_doSoftProofBox->isChecked());
+
+ if (m_doSoftProofBox->isChecked())
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.setProfiles( tmpSpacePath, tmpProofPath, true );
+ }
+ else
+ {
+ transform.setProfiles( tmpInPath, tmpSpacePath, tmpProofPath);
+ }
+ }
+ else
+ {
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.setProfiles( tmpSpacePath );
+ }
+ else
+ {
+ transform.setProfiles( tmpInPath, tmpSpacePath );
+ }
+ }
+
+ if (m_useEmbeddedProfile->isChecked())
+ {
+ transform.apply(img, m_embeddedICC, m_renderingIntentsCB->currentItem(), useBPC(),
+ m_checkGamutBox->isChecked(), useBuiltinProfile());
+ }
+ else
+ {
+ TQByteArray fakeProfile = TQByteArray();
+ transform.apply(img, fakeProfile, m_renderingIntentsCB->currentItem(), useBPC(),
+ m_checkGamutBox->isChecked(), useBuiltinProfile());
+ }
+
+ //-- Embed the workspace profile if necessary --------------------------------
+
+ if (m_embeddProfileBox->isChecked())
+ {
+ iface->setEmbeddedICCToOriginalImage( tmpSpacePath );
+ DDebug() << k_funcinfo << TQFile::encodeName(tmpSpacePath) << endl;
+ }
+
+ //-- Calculate and apply the curve on image after transformation -------------
+
+ Digikam::DImg img2(w, h, sb, a, 0, false);
+ m_curves->curvesLutSetup(Digikam::ImageHistogram::AlphaChannel);
+ m_curves->curvesLutProcess(img.bits(), img2.bits(), w, h);
+
+ //-- Adjust contrast ---------------------------------------------------------
+
+ Digikam::BCGModifier cmod;
+ cmod.setContrast((double)(m_cInput->value()/100.0) + 1.00);
+ cmod.applyBCG(img2);
+
+ iface->putOriginalImage("Color Management", img2.bits());
+ delete [] data;
+ }
+
+ kapp->restoreOverrideCursor();
+ }
+
+ accept();
+}
+
+void ImageEffect_ICCProof::slotToggledWidgets( bool t)
+{
+ m_useInDefaultProfile->setEnabled(t);
+ m_useProofDefaultProfile->setEnabled(t);
+ m_useSpaceDefaultProfile->setEnabled(t);
+}
+
+void ImageEffect_ICCProof::slotInICCInfo()
+{
+ if (useEmbeddedProfile())
+ {
+ getICCInfo(m_embeddedICC);
+ }
+ else if(useBuiltinProfile())
+ {
+ TQString message = i18n("<p>You have selected the \"Default builtin sRGB profile\"</p>");
+ message.append(i18n("<p>This profile is built on the fly, so there is no relevant information "
+ "about it.</p>"));
+ KMessageBox::information(this, message);
+ }
+ else if (useDefaultInProfile())
+ {
+ getICCInfo(m_inPath);
+ }
+ else if (useSelectedInProfile())
+ {
+ getICCInfo(m_inProfilesPath->url());
+ }
+}
+
+void ImageEffect_ICCProof::slotProofICCInfo()
+{
+ if (useDefaultProofProfile())
+ {
+ getICCInfo(m_proofPath);
+ }
+ else
+ {
+ getICCInfo(m_proofProfilePath->url());
+ }
+}
+
+void ImageEffect_ICCProof::slotSpaceICCInfo()
+{
+ if (useDefaultSpaceProfile())
+ {
+ getICCInfo(m_spacePath);
+ }
+ else
+ {
+ getICCInfo(m_spaceProfilePath->url());
+ }
+}
+
+void ImageEffect_ICCProof::getICCInfo(const TQString& profile)
+{
+ if (profile.isEmpty())
+ {
+ KMessageBox::error(this, i18n("Sorry, there is no selected profile"), i18n("Profile Error"));
+ return;
+ }
+
+ Digikam::ICCProfileInfoDlg infoDlg(this, profile);
+ infoDlg.exec();
+}
+
+void ImageEffect_ICCProof::getICCInfo(const TQByteArray& profile)
+{
+ if (profile.isNull())
+ {
+ KMessageBox::error(this, i18n("Sorry, it seems there is no embedded profile"), i18n("Profile Error"));
+ return;
+ }
+
+ Digikam::ICCProfileInfoDlg infoDlg(this, TQString(), profile);
+ infoDlg.exec();
+}
+
+void ImageEffect_ICCProof::slotCMDisabledWarning()
+{
+ if (!m_cmEnabled)
+ {
+ TQString message = i18n("<p>You have not enabled Color Management in the digiKam preferences.</p>");
+ message.append( i18n("<p>\"Use of default profile\" options will be disabled now.</p>"));
+ KMessageBox::information(this, message);
+ slotToggledWidgets(false);
+ }
+}
+
+//-- General Tab ---------------------------
+
+bool ImageEffect_ICCProof::useBPC()
+{
+ return m_BPCBox->isChecked();
+}
+
+bool ImageEffect_ICCProof::doProof()
+{
+ return m_doSoftProofBox->isChecked();
+}
+
+bool ImageEffect_ICCProof::checkGamut()
+{
+ return m_checkGamutBox->isChecked();
+}
+
+bool ImageEffect_ICCProof::embedProfile()
+{
+ return m_embeddProfileBox->isChecked();
+}
+
+//-- Input Tab ---------------------------
+
+bool ImageEffect_ICCProof::useEmbeddedProfile()
+{
+ return m_useEmbeddedProfile->isChecked();
+}
+
+bool ImageEffect_ICCProof::useBuiltinProfile()
+{
+ return m_useSRGBDefaultProfile->isChecked();
+}
+
+bool ImageEffect_ICCProof::useDefaultInProfile()
+{
+ return m_useInDefaultProfile->isChecked();
+}
+
+bool ImageEffect_ICCProof::useSelectedInProfile()
+{
+ return m_useInSelectedProfile->isChecked();
+}
+
+//-- Workspace Tab ---------------------------
+
+bool ImageEffect_ICCProof::useDefaultSpaceProfile()
+{
+ return m_useSpaceDefaultProfile->isChecked();
+}
+
+//-- Proofing Tab ---------------------------
+
+bool ImageEffect_ICCProof::useDefaultProofProfile()
+{
+ return m_useProofDefaultProfile->isChecked();
+}
+
+//-- Load all settings from file --------------------------------------
+
+void ImageEffect_ICCProof::slotUser3()
+{
+ KURL loadColorManagementFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Color Management Settings File to Load")) );
+ if( loadColorManagementFile.isEmpty() )
+ return;
+
+ TQFile file(loadColorManagementFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+
+ if ( stream.readLine() != "# Color Management Configuration File" )
+ {
+ KMessageBox::error(this,
+ i18n("\"%1\" is not a Color Management settings text file.")
+ .arg(loadColorManagementFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+
+ m_renderingIntentsCB->setCurrentItem( stream.readLine().toInt() );
+ m_doSoftProofBox->setChecked( (bool)(stream.readLine().toUInt()) );
+ m_checkGamutBox->setChecked( (bool)(stream.readLine().toUInt()) );
+ m_embeddProfileBox->setChecked( (bool)(stream.readLine().toUInt()) );
+ m_BPCBox->setChecked( (bool)(stream.readLine().toUInt()) );
+ m_inProfileBG->setButton( stream.readLine().toInt() );
+ m_spaceProfileBG->setButton( stream.readLine().toInt() );
+ m_proofProfileBG->setButton( stream.readLine().toInt() );
+ m_inProfilesPath->setURL( stream.readLine() );
+ m_proofProfilePath->setURL( stream.readLine() );
+ m_spaceProfilePath->setURL( stream.readLine() );
+ m_cInput->setValue( stream.readLine().toInt() );
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curves->curvesChannelReset(i);
+
+ m_curves->setCurveType(m_curvesWidget->m_channelType, Digikam::ImageCurves::CURVE_SMOOTH);
+ m_curvesWidget->reset();
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint disable(-1, -1);
+ TQPoint p;
+ p.setX( stream.readLine().toInt() );
+ p.setY( stream.readLine().toInt() );
+
+ if (m_originalImage->sixteenBit() && p != disable)
+ {
+ p.setX(p.x()*255);
+ p.setY(p.y()*255);
+ }
+
+ m_curves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, j, p);
+ }
+
+ blockSignals(false);
+
+ for (int i = 0 ; i < 5 ; i++)
+ m_curves->curvesCalculateCurve(i);
+
+ m_histogramWidget->reset();
+ slotEffect();
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot load settings from the Color Management text file."));
+
+ file.close();
+}
+
+//-- Save all settings to file ---------------------------------------
+
+void ImageEffect_ICCProof::slotUser2()
+{
+ KURL saveColorManagementFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Color Management Settings File to Save")) );
+ if( saveColorManagementFile.isEmpty() )
+ return;
+
+ TQFile file(saveColorManagementFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# Color Management Configuration File\n";
+ stream << m_renderingIntentsCB->currentItem() << "\n";
+ stream << m_doSoftProofBox->isChecked() << "\n";
+ stream << m_checkGamutBox->isChecked() << "\n";
+ stream << m_embeddProfileBox->isChecked() << "\n";
+ stream << m_BPCBox->isChecked() << "\n";
+ stream << m_inProfileBG->selectedId() << "\n";
+ stream << m_spaceProfileBG->selectedId() << "\n";
+ stream << m_proofProfileBG->selectedId() << "\n";
+ stream << m_inProfilesPath->url() << "\n";
+ stream << m_proofProfilePath->url() << "\n";
+ stream << m_spaceProfilePath->url() << "\n";
+ stream << m_cInput->value() << "\n";
+
+ for (int j = 0 ; j < 17 ; j++)
+ {
+ TQPoint p = m_curves->getCurvePoint(Digikam::ImageHistogram::ValueChannel, j);
+ if (m_originalImage->sixteenBit())
+ {
+ p.setX(p.x()/255);
+ p.setY(p.y()/255);
+ }
+ stream << p.x() << "\n";
+ stream << p.y() << "\n";
+ }
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot save settings to the Color Management text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/imageeffect_iccproof.h b/src/imageplugins/coreplugin/imageeffect_iccproof.h
new file mode 100644
index 00000000..58112aef
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_iccproof.h
@@ -0,0 +1,204 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-12-21
+ * Description : digiKam image editor tool to correct picture
+ * colors using an ICC color profile
+ *
+ * Copyright (C) 2005-2006 by F.J. Cruz <fj.cruz@supercable.es>
+ * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_ICCPROOF_H
+#define IMAGEEFFECT_ICCPROOF_H
+
+// Digikam include.
+
+#include "imagedlgbase.h"
+
+class TQCheckBox;
+class TQComboBox;
+class TQVButtonGroup;
+class TQButtonGroup;
+class TQHButtonGroup;
+class TQRadioButton;
+class TQPushButton;
+class TQToolBox;
+
+class KURLRequester;
+class KIntNumInput;
+
+namespace Digikam
+{
+class ICCTransform;
+class ImageWidget;
+class HistogramWidget;
+class ColorGradientWidget;
+class DColor;
+class ICCPreviewWidget;
+class ImageCurves;
+class CurvesWidget;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageEffect_ICCProof : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_ICCProof(TQWidget* parent);
+ ~ImageEffect_ICCProof();
+
+protected:
+
+ void finalRendering();
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+
+ void getICCInfo(const TQString&);
+ void getICCInfo(const TQByteArray&);
+
+ bool useBPC();
+ bool doProof();
+ bool checkGamut();
+ bool embedProfile();
+
+ bool useEmbeddedProfile();
+ bool useBuiltinProfile();
+ bool useDefaultInProfile();
+ bool useSelectedInProfile();
+
+ bool useDefaultSpaceProfile();
+ bool useSelectedSpaceProfile();
+
+ bool useDefaultProofProfile();
+ bool useSelectedProofProfile();
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+ void slotEffect();
+ void slotChannelChanged(int);
+ void slotScaleChanged(int);
+ void slotSpotColorChanged(const Digikam::DColor &);
+ void slotColorSelectedFromTarget(const Digikam::DColor &);
+ void slotToggledWidgets(bool);
+ void slotInICCInfo();
+ void slotProofICCInfo();
+ void slotSpaceICCInfo();
+ void slotCMDisabledWarning();
+ void processLCMSURL(const TQString&);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear = 0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel = 0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum ICCSettingsTab
+ {
+ GENERALPAGE=0,
+ INPUTPAGE,
+ WORKSPACEPAGE,
+ PROOFINGPAGE,
+ LIGHTNESSPAGE
+ };
+
+ bool m_cmEnabled;
+ bool m_hasICC;
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+ TQComboBox *m_renderingIntentsCB;
+
+ TQCheckBox *m_doSoftProofBox;
+ TQCheckBox *m_checkGamutBox;
+ TQCheckBox *m_embeddProfileBox;
+ TQCheckBox *m_BPCBox;
+
+ TQRadioButton *m_useEmbeddedProfile;
+ TQRadioButton *m_useInDefaultProfile;
+ TQRadioButton *m_useInSelectedProfile;
+ TQRadioButton *m_useProofDefaultProfile;
+ TQRadioButton *m_useProofSelectedProfile;
+ TQRadioButton *m_useSpaceDefaultProfile;
+ TQRadioButton *m_useSpaceSelectedProfile;
+ TQRadioButton *m_useSRGBDefaultProfile;
+
+ TQString m_inPath;
+ TQString m_spacePath;
+ TQString m_proofPath;
+
+ TQButtonGroup *m_optionsBG;
+ TQButtonGroup *m_inProfileBG;
+ TQButtonGroup *m_spaceProfileBG;
+ TQButtonGroup *m_proofProfileBG;
+
+ TQHButtonGroup *m_scaleBG;
+ TQVButtonGroup *m_renderingIntentBG;
+ TQVButtonGroup *m_profilesBG;
+
+ TQByteArray m_embeddedICC;
+
+ TQToolBox *m_toolBoxWidgets;
+
+ KIntNumInput *m_cInput;
+
+ KURLRequester *m_inProfilesPath;
+ KURLRequester *m_spaceProfilePath;
+ KURLRequester *m_proofProfilePath;
+
+ Digikam::DImg *m_originalImage;
+
+ Digikam::CurvesWidget *m_curvesWidget;
+
+ Digikam::ImageCurves *m_curves;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ICCPreviewWidget *m_iccInPreviewWidget;
+ Digikam::ICCPreviewWidget *m_iccSpacePreviewWidget;
+ Digikam::ICCPreviewWidget *m_iccProofPreviewWidget;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif // IMAGEEFFECT_ICCPROOF_H
diff --git a/src/imageplugins/coreplugin/imageeffect_redeye.cpp b/src/imageplugins/coreplugin/imageeffect_redeye.cpp
new file mode 100644
index 00000000..df3ae2e7
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_redeye.cpp
@@ -0,0 +1,574 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-06
+ * Description : Red eyes correction tool for image editor
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqhbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqvbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcombobox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <kcolordialog.h>
+#include <knuminput.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kstandarddirs.h>
+#include <kcolordialog.h>
+
+// Digikam includes.
+
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "bcgmodifier.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+
+// Local includes.
+
+#include "imageeffect_redeye.h"
+#include "imageeffect_redeye.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+ImageEffect_RedEye::ImageEffect_RedEye(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Red Eye Reduction"), "redeye", false)
+{
+ m_destinationPreviewData = 0;
+ setHelp("redeyecorrectiontool.anchor", "digikam");
+
+ m_previewWidget = new Digikam::ImageWidget("redeye Tool Dialog", plainPage(),
+ i18n("<p>Here you can see the image selection preview with "
+ "red eye reduction applied."),
+ true, Digikam::ImageGuideWidget::PickColorMode, true, true);
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings, 11, 4, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image channel values.<p>"
+ "<b>Green</b>: display the green image channel values.<p>"
+ "<b>Blue</b>: display the blue image channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin(0);
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximum counts are small, you can use the linear scale.<p>"
+ "The logarithmic scale can be used when the maximal counts are big "
+ "to show all values (small and large) on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram "
+ "of the selected image channel. It is "
+ "updated upon setting changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget(Digikam::ColorGradientWidget::Horizontal, 10, histoBox);
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ // -------------------------------------------------------------
+
+ m_thresholdLabel = new TQLabel(i18n("Sensitivity:"), gboxSettings);
+ m_redThreshold = new KIntNumInput(gboxSettings);
+ m_redThreshold->setRange(10, 90, 1, true);
+ m_redThreshold->setValue(20);
+ TQWhatsThis::add(m_redThreshold, i18n("<p>Sets the red color pixels selection threshold. "
+ "Low values will select more red color pixels (agressive correction), high "
+ "values less (mild correction). Use low value if eye have been selected "
+ "exactly. Use high value if other parts of the face are also selected."));
+
+ m_smoothLabel = new TQLabel(i18n("Smooth:"), gboxSettings);
+ m_smoothLevel = new KIntNumInput(gboxSettings);
+ m_smoothLevel->setRange(0, 5, 1, true);
+ m_smoothLevel->setValue(1);
+ TQWhatsThis::add(m_smoothLevel, i18n("<p>Sets the smoothness value when blurring the border "
+ "of the changed pixels. "
+ "This leads to a more naturally looking pupil."));
+
+ TQLabel *label3 = new TQLabel(i18n("Coloring Tint:"), gboxSettings);
+ m_HSSelector = new KHSSelector(gboxSettings);
+ m_VSelector = new KValueSelector(gboxSettings);
+ m_HSSelector->setMinimumSize(200, 142);
+ m_VSelector->setMinimumSize(26, 142);
+ TQWhatsThis::add(m_HSSelector, i18n("<p>Sets a custom color to re-colorize the eyes."));
+
+ TQLabel *label4 = new TQLabel(i18n("Tint Level:"), gboxSettings);
+ m_tintLevel = new KIntNumInput(gboxSettings);
+ m_tintLevel->setRange(1, 200, 1, true);
+ m_tintLevel->setValue(128);
+ TQWhatsThis::add(m_tintLevel, i18n("<p>Set the tint level to adjust the luminosity of "
+ "the new color of the pupil."));
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+ gridSettings->addMultiCellWidget(m_thresholdLabel, 3, 3, 0, 4);
+ gridSettings->addMultiCellWidget(m_redThreshold, 4, 4, 0, 4);
+ gridSettings->addMultiCellWidget(m_smoothLabel, 5, 5, 0, 4);
+ gridSettings->addMultiCellWidget(m_smoothLevel, 6, 6, 0, 4);
+ gridSettings->addMultiCellWidget(label3, 7, 7, 0, 4);
+ gridSettings->addMultiCellWidget(m_HSSelector, 8, 8, 0, 3);
+ gridSettings->addMultiCellWidget(m_VSelector, 8, 8, 4, 4);
+ gridSettings->addMultiCellWidget(label4, 9, 9, 0, 4);
+ gridSettings->addMultiCellWidget(m_tintLevel, 10, 10, 0, 4);
+ gridSettings->setRowStretch(11, 10);
+ gridSettings->setColStretch(3, 10);
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotColorSelectedFromTarget(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_redThreshold, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_smoothLevel, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_HSSelector, TQ_SIGNAL(valueChanged(int, int)),
+ this, TQ_SLOT(slotHSChanged(int, int)));
+
+ connect(m_VSelector, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_tintLevel, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_RedEye::~ImageEffect_RedEye()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+ delete m_previewWidget;
+}
+
+void ImageEffect_RedEye::slotHSChanged(int h, int s)
+{
+ m_VSelector->blockSignals(true);
+ m_VSelector->setHue(h);
+ m_VSelector->setSaturation(s);
+ m_VSelector->updateContents();
+ m_VSelector->repaint(false);
+ m_VSelector->blockSignals(false);
+ slotTimer();
+}
+
+void ImageEffect_RedEye::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_RedEye::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_RedEye::slotColorSelectedFromTarget(const Digikam::DColor& color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ImageEffect_RedEye::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("redeye Tool Dialog");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+ m_redThreshold->setValue(config->readNumEntry("RedThreshold", 20));
+ m_smoothLevel->setValue(config->readNumEntry("SmoothLevel", 1));
+ m_HSSelector->setXValue(config->readNumEntry("HueColoringTint", 0));
+ m_HSSelector->setYValue(config->readNumEntry("SatColoringTint", 0));
+ m_VSelector->setValue(config->readNumEntry("ValColoringTint", 0));
+ m_tintLevel->setValue(config->readNumEntry("TintLevel", 128));
+
+ slotHSChanged(m_HSSelector->xValue(), m_HSSelector->yValue());
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ImageEffect_RedEye::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("redeye Tool Dialog");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("RedThreshold", m_redThreshold->value());
+ config->writeEntry("SmoothLevel", m_smoothLevel->value());
+ config->writeEntry("HueColoringTint", m_HSSelector->xValue());
+ config->writeEntry("SatColoringTint", m_HSSelector->yValue());
+ config->writeEntry("ValColoringTint", m_VSelector->value());
+ config->writeEntry("TintLevel", m_tintLevel->value());
+ config->sync();
+}
+
+void ImageEffect_RedEye::resetValues()
+{
+ m_redThreshold->blockSignals(true);
+ m_HSSelector->blockSignals(true);
+ m_VSelector->blockSignals(true);
+ m_tintLevel->blockSignals(true);
+
+ m_redThreshold->setValue(20);
+ m_smoothLevel->setValue(1);
+
+ // Black color by default
+ m_HSSelector->setXValue(0);
+ m_HSSelector->setYValue(0);
+ m_VSelector->setValue(0);
+
+ m_tintLevel->setValue(128);
+
+ m_redThreshold->blockSignals(false);
+ m_HSSelector->blockSignals(false);
+ m_VSelector->blockSignals(false);
+ m_tintLevel->blockSignals(false);
+}
+
+void ImageEffect_RedEye::slotEffect()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ // Here, we need to use the real selection image data because we will apply
+ // a Gaussian blur filter on pixels and we cannot use directly the preview scaled image
+ // else the blur radius will not give the same result between preview and final rendering.
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getImageSelection();
+ int w = iface->selectedWidth();
+ int h = iface->selectedHeight();
+ bool sb = iface->originalSixteenBit();
+ bool a = iface->originalHasAlpha();
+ Digikam::DImg selection(w, h, sb, a, m_destinationPreviewData);
+
+ redEyeFilter(selection);
+
+ Digikam::DImg preview = selection.smoothScale(iface->previewWidth(), iface->previewHeight());
+
+ iface->putPreviewImage(preview.bits());
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, selection.bits(), selection.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void ImageEffect_RedEye::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getImageSelection();
+ int w = iface->selectedWidth();
+ int h = iface->selectedHeight();
+ bool sixteenBit = iface->originalSixteenBit();
+ bool hasAlpha = iface->originalHasAlpha();
+ Digikam::DImg selection(w, h, sixteenBit, hasAlpha, data);
+ delete [] data;
+
+ redEyeFilter(selection);
+
+ iface->putImageSelection(i18n("Red Eyes Correction"), selection.bits());
+
+ kapp->restoreOverrideCursor();
+ accept();
+}
+
+void ImageEffect_RedEye::redEyeFilter(Digikam::DImg& selection)
+{
+ Digikam::DImg mask(selection.width(), selection.height(), selection.sixteenBit(), true,
+ selection.bits(), true);
+
+ selection = mask.copy();
+ float redThreshold = m_redThreshold->value()/10.0;
+ int hue = m_HSSelector->xValue();
+ int sat = m_HSSelector->yValue();
+ int val = m_VSelector->value();
+ KColor coloring;
+ coloring.setHsv(hue, sat, val);
+
+ struct channel
+ {
+ float red_gain;
+ float green_gain;
+ float blue_gain;
+ };
+
+ channel red_chan, green_chan, blue_chan;
+
+ red_chan.red_gain = 0.1;
+ red_chan.green_gain = 0.6;
+ red_chan.blue_gain = 0.3;
+
+ green_chan.red_gain = 0.0;
+ green_chan.green_gain = 1.0;
+ green_chan.blue_gain = 0.0;
+
+ blue_chan.red_gain = 0.0;
+ blue_chan.green_gain = 0.0;
+ blue_chan.blue_gain = 1.0;
+
+ float red_norm, green_norm, blue_norm;
+ int level = 201 - m_tintLevel->value();
+
+ red_norm = 1.0 / (red_chan.red_gain + red_chan.green_gain + red_chan.blue_gain);
+ green_norm = 1.0 / (green_chan.red_gain + green_chan.green_gain + green_chan.blue_gain);
+ blue_norm = 1.0 / (blue_chan.red_gain + blue_chan.green_gain + blue_chan.blue_gain);
+
+ red_norm *= coloring.red() / level;
+ green_norm *= coloring.green() / level;
+ blue_norm *= coloring.blue() / level;
+
+ // Perform a red color pixels detection in selection image and create a correction mask using an alpha channel.
+
+ if (!selection.sixteenBit()) // 8 bits image.
+ {
+ uchar* ptr = selection.bits();
+ uchar* mptr = mask.bits();
+ uchar r, g, b, r1, g1, b1;
+
+ for (uint i = 0 ; i < selection.width() * selection.height() ; i++)
+ {
+ b = ptr[0];
+ g = ptr[1];
+ r = ptr[2];
+ mptr[3] = 255;
+
+ if (r >= ( redThreshold * g))
+ {
+ r1 = TQMIN(255, (int)(red_norm * (red_chan.red_gain * r +
+ red_chan.green_gain * g +
+ red_chan.blue_gain * b)));
+
+ g1 = TQMIN(255, (int)(green_norm * (green_chan.red_gain * r +
+ green_chan.green_gain * g +
+ green_chan.blue_gain * b)));
+
+ b1 = TQMIN(255, (int)(blue_norm * (blue_chan.red_gain * r +
+ blue_chan.green_gain * g +
+ blue_chan.blue_gain * b)));
+
+ mptr[0] = b1;
+ mptr[1] = g1;
+ mptr[2] = r1;
+ mptr[3] = TQMIN( (int)((r-g) / 150.0 * 255.0), 255);
+ }
+
+ ptr += 4;
+ mptr+= 4;
+ }
+ }
+ else // 16 bits image.
+ {
+ unsigned short* ptr = (unsigned short*)selection.bits();
+ unsigned short* mptr = (unsigned short*)mask.bits();
+ unsigned short r, g, b, r1, g1, b1;
+
+ for (uint i = 0 ; i < selection.width() * selection.height() ; i++)
+ {
+ b = ptr[0];
+ g = ptr[1];
+ r = ptr[2];
+ mptr[3] = 65535;
+
+ if (r >= ( redThreshold * g))
+ {
+ r1 = TQMIN(65535, (int)(red_norm * (red_chan.red_gain * r +
+ red_chan.green_gain * g +
+ red_chan.blue_gain * b)));
+
+ g1 = TQMIN(65535, (int)(green_norm * (green_chan.red_gain * r +
+ green_chan.green_gain * g +
+ green_chan.blue_gain * b)));
+
+ b1 = TQMIN(65535, (int)(blue_norm * (blue_chan.red_gain * r +
+ blue_chan.green_gain * g +
+ blue_chan.blue_gain * b)));
+
+ mptr[0] = b1;
+ mptr[1] = g1;
+ mptr[2] = r1;
+ mptr[3] = TQMIN( (int)((r-g) / 38400.0 * 65535.0), 65535);;
+ }
+
+ ptr += 4;
+ mptr+= 4;
+ }
+ }
+
+ // Now, we will blur only the transparency pixels from the mask.
+
+ Digikam::DImg mask2 = mask.copy();
+ Digikam::DImgImageFilters filter;
+ filter.gaussianBlurImage(mask2.bits(), mask2.width(), mask2.height(),
+ mask2.sixteenBit(), m_smoothLevel->value());
+
+ if (!selection.sixteenBit()) // 8 bits image.
+ {
+ uchar* mptr = mask.bits();
+ uchar* mptr2 = mask2.bits();
+
+ for (uint i = 0 ; i < mask2.width() * mask2.height() ; i++)
+ {
+ if (mptr2[3] < 255)
+ {
+ mptr[0] = mptr2[0];
+ mptr[1] = mptr2[1];
+ mptr[2] = mptr2[2];
+ mptr[3] = mptr2[3];
+ }
+
+ mptr += 4;
+ mptr2+= 4;
+ }
+ }
+ else // 16 bits image.
+ {
+ unsigned short* mptr = (unsigned short*)mask.bits();
+ unsigned short* mptr2 = (unsigned short*)mask2.bits();
+
+ for (uint i = 0 ; i < mask2.width() * mask2.height() ; i++)
+ {
+ if (mptr2[3] < 65535)
+ {
+ mptr[0] = mptr2[0];
+ mptr[1] = mptr2[1];
+ mptr[2] = mptr2[2];
+ mptr[3] = mptr2[3];
+ }
+
+ mptr += 4;
+ mptr2+= 4;
+ }
+ }
+
+ // - Perform pixels blending using alpha channel between the mask and the selection.
+
+ Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(Digikam::DColorComposer::PorterDuffSrcOver);
+
+ // NOTE: 'mask' is the Source image, 'selection' is the Destination image.
+
+ selection.bitBlendImage(composer, &mask,
+ 0, 0, mask.width(), mask.height(),
+ 0, 0);
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/imageeffect_redeye.h b/src/imageplugins/coreplugin/imageeffect_redeye.h
new file mode 100644
index 00000000..79b517ee
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_redeye.h
@@ -0,0 +1,153 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-06
+ * Description : Red eyes correction tool for image editor
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+
+#ifndef IMAGEEFFECT_REDEYE_H
+#define IMAGEEFFECT_REDEYE_H
+
+// KDE includes.
+
+#include <kpassivepopup.h>
+
+// Digikam include.
+
+#include "imagedlgbase.h"
+
+class TQLabel;
+class TQComboBox;
+class TQHButtonGroup;
+
+class KHSSelector;
+class KValueSelector;
+class KIntNumInput;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+class DImg;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class RedEyePassivePopup : public KPassivePopup
+{
+public:
+
+ RedEyePassivePopup(TQWidget* parent)
+ : KPassivePopup(parent), m_parent(parent)
+ {
+ }
+
+protected:
+
+ virtual void positionSelf()
+ {
+ move(m_parent->x() + 30, m_parent->y() + 30);
+ }
+
+private:
+
+ TQWidget* m_parent;
+};
+
+// ----------------------------------------------------------------
+
+class ImageEffect_RedEye : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_RedEye(TQWidget *parent);
+ ~ImageEffect_RedEye();
+
+private slots:
+
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+ void slotHSChanged(int h, int s);
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void finalRendering();
+ void redEyeFilter(Digikam::DImg& selection);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum RedThresold
+ {
+ Mild=0,
+ Aggressive
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQLabel *m_thresholdLabel;
+ TQLabel *m_smoothLabel;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ KIntNumInput *m_tintLevel;
+ KIntNumInput *m_redThreshold;
+ KIntNumInput *m_smoothLevel;
+
+ KHSSelector *m_HSSelector;
+ KValueSelector *m_VSelector;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_REDEYE_H */
diff --git a/src/imageplugins/coreplugin/imageeffect_rgb.cpp b/src/imageplugins/coreplugin/imageeffect_rgb.cpp
new file mode 100644
index 00000000..fcff9c41
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_rgb.cpp
@@ -0,0 +1,419 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-11
+ * Description : digiKam image editor Color Balance tool.
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqspinbox.h>
+#include <tqslider.h>
+#include <tqcolor.h>
+#include <tqgroupbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqvbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+#include <kcursor.h>
+#include <kstandarddirs.h>
+
+// Digikam includes.
+
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "histogramwidget.h"
+#include "colorgradientwidget.h"
+#include "colormodifier.h"
+#include "dimg.h"
+
+// Local includes.
+
+#include "imageeffect_rgb.h"
+#include "imageeffect_rgb.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+ImageEffect_RGB::ImageEffect_RGB(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Color Balance"), "colorbalance", false)
+{
+ m_destinationPreviewData = 0L;
+ setHelp("colorbalancetool.anchor", "digikam");
+
+ m_previewWidget = new Digikam::ImageWidget("colorbalance Tool Dialog", plainPage(),
+ i18n("<p>Here you can see the image "
+ "color-balance adjustments preview. "
+ "You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 7, 4, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQLabel *labelLeft = new TQLabel(i18n("Cyan"), gboxSettings);
+ labelLeft->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_rSlider = new TQSlider(-100, 100, 1, 0, TQt::Horizontal, gboxSettings, "m_rSlider");
+ m_rSlider->setTickmarks(TQSlider::Below);
+ m_rSlider->setTickInterval(20);
+ TQWhatsThis::add( m_rSlider, i18n("<p>Set here the cyan/red color adjustment of the image."));
+ TQLabel *labelRight = new TQLabel(i18n("Red"), gboxSettings);
+ labelRight->setAlignment ( TQt::AlignLeft | TQt::AlignVCenter );
+ m_rInput = new TQSpinBox(-100, 100, 1, gboxSettings, "m_rInput");
+
+ gridSettings->addMultiCellWidget(labelLeft, 3, 3, 0, 0);
+ gridSettings->addMultiCellWidget(m_rSlider, 3, 3, 1, 1);
+ gridSettings->addMultiCellWidget(labelRight, 3, 3, 2, 2);
+ gridSettings->addMultiCellWidget(m_rInput, 3, 3, 3, 3);
+
+ // -------------------------------------------------------------
+
+ labelLeft = new TQLabel(i18n("Magenta"), gboxSettings);
+ labelLeft->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_gSlider = new TQSlider(-100, 100, 1, 0, TQt::Horizontal, gboxSettings, "m_gSlider");
+ m_gSlider->setTickmarks(TQSlider::Below);
+ m_gSlider->setTickInterval(20);
+ TQWhatsThis::add( m_gSlider, i18n("<p>Set here the magenta/green color adjustment of the image."));
+ labelRight = new TQLabel(i18n("Green"), gboxSettings);
+ labelRight->setAlignment ( TQt::AlignLeft | TQt::AlignVCenter );
+ m_gInput = new TQSpinBox(-100, 100, 1, gboxSettings, "m_gInput");
+
+ gridSettings->addMultiCellWidget(labelLeft, 4, 4, 0, 0);
+ gridSettings->addMultiCellWidget(m_gSlider, 4, 4, 1, 1);
+ gridSettings->addMultiCellWidget(labelRight, 4, 4, 2, 2);
+ gridSettings->addMultiCellWidget(m_gInput, 4, 4, 3, 3);
+
+ // -------------------------------------------------------------
+
+ labelLeft = new TQLabel(i18n("Yellow"), gboxSettings);
+ labelLeft->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_bSlider = new TQSlider(-100, 100, 1, 0, TQt::Horizontal, gboxSettings, "m_bSlider");
+ m_bSlider->setTickmarks(TQSlider::Below);
+ m_bSlider->setTickInterval(20);
+ TQWhatsThis::add( m_bSlider, i18n("<p>Set here the yellow/blue color adjustment of the image."));
+ labelRight = new TQLabel(i18n("Blue"), gboxSettings);
+ labelRight->setAlignment ( TQt::AlignLeft | TQt::AlignVCenter );
+ m_bInput = new TQSpinBox(-100, 100, 1, gboxSettings, "m_bInput");
+
+ gridSettings->addMultiCellWidget(labelLeft, 5, 5, 0, 0);
+ gridSettings->addMultiCellWidget(m_bSlider, 5, 5, 1, 1);
+ gridSettings->addMultiCellWidget(labelRight, 5, 5, 2, 2);
+ gridSettings->addMultiCellWidget(m_bInput, 5, 5, 3, 3);
+
+ m_rInput->setValue(0);
+ m_gInput->setValue(0);
+ m_bInput->setValue(0);
+
+ gridSettings->setRowStretch(6, 10);
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_rSlider, TQ_SIGNAL(valueChanged(int)),
+ m_rInput, TQ_SLOT(setValue(int)));
+ connect(m_rInput, TQ_SIGNAL(valueChanged (int)),
+ m_rSlider, TQ_SLOT(setValue(int)));
+ connect(m_rInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gSlider, TQ_SIGNAL(valueChanged(int)),
+ m_gInput, TQ_SLOT(setValue(int)));
+ connect(m_gInput, TQ_SIGNAL(valueChanged (int)),
+ m_gSlider, TQ_SLOT(setValue(int)));
+ connect(m_gInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_bSlider, TQ_SIGNAL(valueChanged(int)),
+ m_bInput, TQ_SLOT(setValue(int)));
+ connect(m_bInput, TQ_SIGNAL(valueChanged (int)),
+ m_bSlider, TQ_SLOT(setValue(int)));
+ connect(m_bInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+
+ enableButtonOK( false );
+}
+
+ImageEffect_RGB::~ImageEffect_RGB()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+ delete m_previewWidget;
+}
+
+void ImageEffect_RGB::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_RGB::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_RGB::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ImageEffect_RGB::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("colorbalance Tool Dialog");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+ int r = config->readNumEntry("RedAjustment", 0);
+ int g = config->readNumEntry("GreenAjustment", 0);
+ int b = config->readNumEntry("BlueAjustment", 0);
+ adjustSliders(r, g, b);
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ImageEffect_RGB::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("colorbalance Tool Dialog");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("RedAjustment", m_rSlider->value());
+ config->writeEntry("GreenAjustment", m_gInput->value());
+ config->writeEntry("BlueAjustment", m_bInput->value());
+ config->sync();
+}
+
+void ImageEffect_RGB::resetValues()
+{
+ adjustSliders(0, 0, 0);
+}
+
+void ImageEffect_RGB::adjustSliders(int r, int g, int b)
+{
+ m_rSlider->blockSignals(true);
+ m_gSlider->blockSignals(true);
+ m_bSlider->blockSignals(true);
+ m_rInput->blockSignals(true);
+ m_gInput->blockSignals(true);
+ m_bInput->blockSignals(true);
+
+ m_rSlider->setValue(r);
+ m_gSlider->setValue(g);
+ m_bSlider->setValue(b);
+ m_rInput->setValue(r);
+ m_gInput->setValue(g);
+ m_bInput->setValue(b);
+
+ m_rSlider->blockSignals(false);
+ m_gSlider->blockSignals(false);
+ m_bSlider->blockSignals(false);
+ m_rInput->blockSignals(false);
+ m_gInput->blockSignals(false);
+ m_bInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ImageEffect_RGB::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ enableButtonOK(m_rInput->value() != 0 ||
+ m_gInput->value() != 0 ||
+ m_bInput->value() != 0);
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool alpha = iface->previewHasAlpha();
+ bool sixteenBit = iface->previewSixteenBit();
+
+ double r = ((double)m_rInput->value() + 100.0)/100.0;
+ double g = ((double)m_gInput->value() + 100.0)/100.0;
+ double b = ((double)m_bInput->value() + 100.0)/100.0;
+ double a = 1.0;
+
+ Digikam::DImg preview(w, h, sixteenBit, alpha, m_destinationPreviewData);
+ Digikam::ColorModifier cmod;
+ cmod.applyColorModifier(preview, r, g, b, a);
+ iface->putPreviewImage(preview.bits());
+
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, preview.bits(), preview.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sixteenBit, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void ImageEffect_RGB::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ double r = ((double)m_rInput->value() + 100.0)/100.0;
+ double g = ((double)m_gInput->value() + 100.0)/100.0;
+ double b = ((double)m_bInput->value() + 100.0)/100.0;
+ double a = 1.0;
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool alpha = iface->originalHasAlpha();
+ bool sixteenBit = iface->originalSixteenBit();
+ Digikam::DImg original(w, h, sixteenBit, alpha, data);
+ delete [] data;
+
+ Digikam::ColorModifier cmod;
+ cmod.applyColorModifier(original, r, g, b, a);
+
+ iface->putOriginalImage(i18n("Color Balance"), original.bits());
+ kapp->restoreOverrideCursor();
+ accept();
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/imageeffect_rgb.h b/src/imageplugins/coreplugin/imageeffect_rgb.h
new file mode 100644
index 00000000..9f5db52c
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageeffect_rgb.h
@@ -0,0 +1,113 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-11
+ * Description : digiKam image editor Color Balance tool.
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_RGB_H
+#define IMAGEEFFECT_RGB_H
+
+// Digikam include.
+
+#include "imagedlgbase.h"
+
+class TQComboBox;
+class TQHButtonGroup;
+
+class TQSpinBox;
+class TQSlider;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageEffect_RGB : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_RGB(TQWidget *parent);
+ ~ImageEffect_RGB();
+
+private:
+
+ void writeUserSettings();
+ void readUserSettings();
+ void resetValues();
+ void adjustSliders(int r, int g, int b);
+ void finalRendering();
+
+private slots:
+
+ void slotEffect();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget( const Digikam::DColor &color );
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ TQSpinBox *m_rInput;
+ TQSpinBox *m_gInput;
+ TQSpinBox *m_bInput;
+
+ TQSlider *m_rSlider;
+ TQSlider *m_gSlider;
+ TQSlider *m_bSlider;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_RGB_H */
diff --git a/src/imageplugins/coreplugin/imageplugin_core.cpp b/src/imageplugins/coreplugin/imageplugin_core.cpp
new file mode 100644
index 00000000..22c63b34
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageplugin_core.cpp
@@ -0,0 +1,295 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-04
+ * Description : digiKam image editor plugin core
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#include <config.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdemessagebox.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "imageiface.h"
+#include "rgbtool.h"
+#include "hsltool.h"
+#include "bcgtool.h"
+#include "bwsepiatool.h"
+#include "redeyetool.h"
+#include "blurtool.h"
+#include "sharpentool.h"
+#include "ratiocroptool.h"
+#include "autocorrectiontool.h"
+#include "iccprooftool.h"
+#include "imageplugin_core.h"
+#include "imageplugin_core.moc"
+
+using namespace DigikamImagesPluginCore;
+using namespace Digikam;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_core,
+ KGenericFactory<ImagePlugin_Core>("digikam"));
+
+ImagePlugin_Core::ImagePlugin_Core(TQObject *parent, const char*, const TQStringList&)
+ : ImagePlugin(parent, "ImagePlugin_Core")
+{
+ //-------------------------------
+ // Fix and Colors menu actions
+
+ m_blurAction = new TDEAction(i18n("Blur..."), "blurimage", 0,
+ this, TQ_SLOT(slotBlur()),
+ actionCollection(), "implugcore_blur");
+
+ m_sharpenAction = new TDEAction(i18n("Sharpen..."), "sharpenimage", 0,
+ this, TQ_SLOT(slotSharpen()),
+ actionCollection(), "implugcore_sharpen");
+
+ m_redeyeAction = new TDEAction(i18n("Red Eye..."), "redeyes", 0,
+ this, TQ_SLOT(slotRedEye()),
+ actionCollection(), "implugcore_redeye");
+ m_redeyeAction->setWhatsThis( i18n( "This filter can be used to correct red eyes in a photo. "
+ "Select a region including the eyes to use this option.") );
+
+ m_BCGAction = new TDEAction(i18n("Brightness/Contrast/Gamma..."), "contrast", 0,
+ this, TQ_SLOT(slotBCG()),
+ actionCollection(), "implugcore_bcg");
+
+ m_HSLAction = new TDEAction(i18n("Hue/Saturation/Lightness..."), "adjusthsl",
+ CTRL+Key_U, // NOTE: Photoshop 7 use CTRL+U.
+ this, TQ_SLOT(slotHSL()),
+ actionCollection(), "implugcore_hsl");
+
+ m_RGBAction = new TDEAction(i18n("Color Balance..."), "adjustrgb",
+ CTRL+Key_B, // NOTE: Photoshop 7 use CTRL+B.
+ this, TQ_SLOT(slotRGB()),
+ actionCollection(), "implugcore_rgb");
+
+ m_autoCorrectionAction = new TDEAction(i18n("Auto-Correction..."), "autocorrection",
+ CTRL+SHIFT+Key_B, // NOTE: Photoshop 7 use CTRL+SHIFT+B with 'Auto-Color' option.
+ this, TQ_SLOT(slotAutoCorrection()),
+ actionCollection(), "implugcore_autocorrection");
+
+ m_invertAction = new TDEAction(i18n("Invert"), "invertimage",
+ CTRL+Key_I, // NOTE: Photoshop 7 use CTRL+I.
+ this, TQ_SLOT(slotInvert()),
+ actionCollection(), "implugcore_invert");
+
+ m_convertTo8Bits = new TDEAction(i18n("8 bits"), "depth16to8", 0,
+ this, TQ_SLOT(slotConvertTo8Bits()),
+ actionCollection(), "implugcore_convertto8bits");
+
+ m_convertTo16Bits = new TDEAction(i18n("16 bits"), "depth8to16", 0,
+ this, TQ_SLOT(slotConvertTo16Bits()),
+ actionCollection(), "implugcore_convertto16bits");
+
+ m_colorManagementAction = new TDEAction(i18n("Color Management..."), "colormanagement", 0,
+ this, TQ_SLOT(slotColorManagement()),
+ actionCollection(), "implugcore_colormanagement");
+ //-------------------------------
+ // Filters menu actions.
+
+ m_BWAction = new TDEAction(i18n("Black && White..."), "bwtonal", 0,
+ this, TQ_SLOT(slotBW()),
+ actionCollection(), "implugcore_blackwhite");
+
+ //-------------------------------
+ // Transform menu actions.
+
+ m_aspectRatioCropAction = new TDEAction(i18n("Aspect Ratio Crop..."), "ratiocrop", 0,
+ this, TQ_SLOT(slotRatioCrop()),
+ actionCollection(), "implugcore_ratiocrop");
+
+ //-------------------------------
+ // Init. menu actions.
+
+ setXMLFile("digikamimageplugin_core_ui.rc");
+
+ DDebug() << "ImagePlugin_Core plugin loaded" << endl;
+}
+
+ImagePlugin_Core::~ImagePlugin_Core()
+{
+}
+
+void ImagePlugin_Core::setEnabledSelectionActions(bool)
+{
+}
+
+void ImagePlugin_Core::setEnabledActions(bool enable)
+{
+ m_redeyeAction->setEnabled(enable);
+ m_BCGAction->setEnabled(enable);
+ m_HSLAction->setEnabled(enable);
+ m_RGBAction->setEnabled(enable);
+ m_autoCorrectionAction->setEnabled(enable);
+ m_invertAction->setEnabled(enable);
+ m_BWAction->setEnabled(enable);
+ m_aspectRatioCropAction->setEnabled(enable);
+ m_sharpenAction->setEnabled(enable);
+ m_blurAction->setEnabled(enable);
+ m_colorManagementAction->setEnabled(enable);
+ m_convertTo8Bits->setEnabled(enable);
+ m_convertTo16Bits->setEnabled(enable);
+}
+
+void ImagePlugin_Core::slotBlur()
+{
+ BlurTool *tool = new BlurTool(this);
+ loadTool(tool);
+}
+
+void ImagePlugin_Core::slotSharpen()
+{
+ SharpenTool *tool = new SharpenTool(this);
+ loadTool(tool);
+}
+
+void ImagePlugin_Core::slotBCG()
+{
+ BCGTool *bcg = new BCGTool(this);
+ loadTool(bcg);
+}
+
+void ImagePlugin_Core::slotRGB()
+{
+ RGBTool *rgb = new RGBTool(this);
+ loadTool(rgb);
+}
+
+void ImagePlugin_Core::slotHSL()
+{
+ HSLTool *hsl = new HSLTool(this);
+ loadTool(hsl);
+}
+
+void ImagePlugin_Core::slotAutoCorrection()
+{
+ AutoCorrectionTool *autocorrection = new AutoCorrectionTool(this);
+ loadTool(autocorrection);
+}
+
+void ImagePlugin_Core::slotInvert()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ ImageIface iface(0, 0);
+
+ uchar *data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sixteenBit = iface.originalSixteenBit();
+
+ DImgImageFilters filter;
+ filter.invertImage(data, w, h, sixteenBit);
+ iface.putOriginalImage(i18n("Invert"), data);
+ delete [] data;
+
+ kapp->restoreOverrideCursor();
+}
+
+void ImagePlugin_Core::slotBW()
+{
+ BWSepiaTool *bwsepia = new BWSepiaTool(this);
+ loadTool(bwsepia);
+}
+
+void ImagePlugin_Core::slotRedEye()
+{
+ ImageIface iface(0, 0);
+
+ if (!iface.selectedWidth() || !iface.selectedHeight())
+ {
+ RedEyePassivePopup* popup = new RedEyePassivePopup(kapp->activeWindow());
+ popup->setView(i18n("Red-Eye Correction Tool"),
+ i18n("You need to select a region including the eyes to use "
+ "the red-eye correction tool"));
+ popup->setAutoDelete(true);
+ popup->setTimeout(2500);
+ popup->show();
+ return;
+ }
+
+ RedEyeTool *redeye = new RedEyeTool(this);
+ loadTool(redeye);
+}
+
+void ImagePlugin_Core::slotColorManagement()
+{
+ ICCProofTool *tool = new ICCProofTool(this);
+ loadTool(tool);
+}
+
+void ImagePlugin_Core::slotRatioCrop()
+{
+ RatioCropTool *ratiocrop = new RatioCropTool(this);
+ loadTool(ratiocrop);
+}
+
+void ImagePlugin_Core::slotConvertTo8Bits()
+{
+ ImageIface iface(0, 0);
+
+ if (!iface.originalSixteenBit())
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("This image is already using a depth of 8 bits / color / pixel."));
+ return;
+ }
+ else
+ {
+ if (KMessageBox::warningContinueCancel(
+ kapp->activeWindow(),
+ i18n("Performing this operation will reduce image color quality. "
+ "Do you want to continue?"), TQString(),
+ KStdGuiItem::cont(),
+ TQString("ImagePluginCore16To8Bits")) == KMessageBox::Cancel)
+ return;
+ }
+
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ iface.convertOriginalColorDepth(32);
+ kapp->restoreOverrideCursor();
+}
+
+void ImagePlugin_Core::slotConvertTo16Bits()
+{
+ ImageIface iface(0, 0);
+
+ if (iface.originalSixteenBit())
+ {
+ KMessageBox::error(kapp->activeWindow(), i18n("This image is already using a depth of 16 bits / color / pixel."));
+ return;
+ }
+
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ iface.convertOriginalColorDepth(64);
+ kapp->restoreOverrideCursor();
+}
diff --git a/src/imageplugins/coreplugin/imageplugin_core.h b/src/imageplugins/coreplugin/imageplugin_core.h
new file mode 100644
index 00000000..41168d26
--- /dev/null
+++ b/src/imageplugins/coreplugin/imageplugin_core.h
@@ -0,0 +1,85 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-04
+ * Description : digiKam image editor plugin core
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_CORE_H
+#define IMAGEPLUGIN_CORE_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_Core : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_Core(TQObject *parent, const char* name, const TQStringList &args);
+ ~ImagePlugin_Core();
+
+ void setEnabledSelectionActions(bool enable);
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotBlur();
+ void slotSharpen();
+ void slotBCG();
+ void slotRGB();
+ void slotHSL();
+ void slotAutoCorrection();
+ void slotInvert();
+
+ void slotBW();
+
+ void slotRedEye();
+ void slotRatioCrop();
+
+ void slotConvertTo8Bits();
+ void slotConvertTo16Bits();
+
+ void slotColorManagement();
+
+private:
+
+ TDEAction *m_redeyeAction;
+ TDEAction *m_BCGAction;
+ TDEAction *m_HSLAction;
+ TDEAction *m_RGBAction;
+ TDEAction *m_autoCorrectionAction;
+ TDEAction *m_invertAction;
+ TDEAction *m_BWAction;
+ TDEAction *m_aspectRatioCropAction;
+ TDEAction *m_sharpenAction;
+ TDEAction *m_blurAction;
+ TDEAction *m_colorManagementAction;
+ TDEAction *m_convertTo8Bits;
+ TDEAction *m_convertTo16Bits;
+};
+
+#endif /* IMAGEPLUGIN_CORE_H */
diff --git a/src/imageplugins/coreplugin/ratiocrop/Makefile.am b/src/imageplugins/coreplugin/ratiocrop/Makefile.am
new file mode 100644
index 00000000..47ec5b58
--- /dev/null
+++ b/src/imageplugins/coreplugin/ratiocrop/Makefile.am
@@ -0,0 +1,26 @@
+noinst_LTLIBRARIES = libratiocrop.la
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+libratiocrop_la_SOURCES = ratiocroptool.cpp imageselectionwidget.cpp
+
+libratiocrop_la_LDFLAGS = $(all_libraries)
+
+noinst_HEADERS = ratiocroptool.h imageselectionwidget.h
+
diff --git a/src/imageplugins/coreplugin/ratiocrop/imageeffect_ratiocrop.cpp b/src/imageplugins/coreplugin/ratiocrop/imageeffect_ratiocrop.cpp
new file mode 100644
index 00000000..64bc7a8e
--- /dev/null
+++ b/src/imageplugins/coreplugin/ratiocrop/imageeffect_ratiocrop.cpp
@@ -0,0 +1,799 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-06
+ * Description : digiKam image editor Ratio Crop tool
+ *
+ * Copyright (C) 2007 by Jaromir Malenko <malenko at email dot cz>
+ * Copyright (C) 2008 by Roberto Castagnola <roberto dot castagnola at gmail dot com>
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqrect.h>
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqcombobox.h>
+#include <tqspinbox.h>
+#include <tqimage.h>
+#include <tqpushbutton.h>
+#include <tqtimer.h>
+#include <tqcheckbox.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <knuminput.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kstandarddirs.h>
+#include <kcolorbutton.h>
+
+// Digikam includes.
+
+#include "imageiface.h"
+#include "imageselectionwidget.h"
+
+// Local includes.
+
+#include "imageeffect_ratiocrop.h"
+#include "imageeffect_ratiocrop.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+ImageEffect_RatioCrop::ImageEffect_RatioCrop(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Aspect Ratio Crop & Composition Guide"),
+ "aspectratiocrop", false)
+{
+ setHelp("ratiocroptool.anchor", "digikam");
+ setButtonWhatsThis ( User1, i18n("<p>Set selection area to the maximum size according "
+ "to the current ratio.") );
+ setButtonText(User1, i18n("&Max. Aspect"));
+ showButton(User1, true);
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(plainPage());
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* l = new TQVBoxLayout(frame, 5, 0);
+ m_imageSelectionWidget = new ImageSelectionWidget(480, 320, frame);
+ l->addWidget(m_imageSelectionWidget);
+ TQWhatsThis::add( m_imageSelectionWidget, i18n("<p>Here you can see the aspect ratio selection preview "
+ "used for cropping. You can use the mouse to move and "
+ "resize the crop area. "
+ "Press and hold the CTRL key to move the opposite corner too. "
+ "Press and hold the SHIFT key to move the closest corner to the "
+ "mouse pointer."));
+ setPreviewAreaWidget(frame);
+
+ m_originalIsLandscape = m_imageSelectionWidget->getOriginalImageWidth() >
+ m_imageSelectionWidget->getOriginalImageHeight();
+
+ // -------------------------------------------------------------
+
+ TQWidget *gbox2 = new TQWidget(plainPage());
+ TQGridLayout *gridBox2 = new TQGridLayout( gbox2, 2, 0);
+
+ TQFrame *cropSelection = new TQFrame( gbox2 );
+ cropSelection->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQGridLayout* grid = new TQGridLayout( cropSelection, 6, 4, spacingHint());
+
+ TQLabel *label = new TQLabel(i18n("Aspect ratio:"), cropSelection);
+ m_ratioCB = new TQComboBox( false, cropSelection );
+ setRatioCBText(ImageSelectionWidget::Landscape);
+ TQWhatsThis::add( m_ratioCB, i18n("<p>Select your constrained aspect ratio for cropping. "
+ "Aspect Ratio Crop tool uses a relative ratio. That means it "
+ "is the same if you use centimeters or inches and it doesn't "
+ "specify the physical size.<p>"
+ "You can see below a correspondence list of traditional photographic "
+ "paper sizes and aspect ratio crop:<p>"
+ "<b>2:3</b>: 10x15cm, 20x30cm, 30x45cm, 4x6\", 8x12\", "
+ "12x18\", 16x24\", 20x30\"<p>"
+ "<b>3:4</b>: 6x8cm, 15x20cm, 18x24cm, 30x40cm, 3.75x5\", 4.5x6\", "
+ "6x8\", 7.5x10\", 9x12\"<p>"
+ "<b>4:5</b>: 20x25cm, 40x50cm, 8x10\", 16x20\"<p>"
+ "<b>5:7</b>: 15x21cm, 30x42cm, 5x7\"<p>"
+ "<b>7:10</b>: 21x30cm, 42x60cm, 3.5x5\"<p>"
+ "The <b>Golden Ratio</b> is 1:1.618. A composition following this rule "
+ "is considered visually harmonious but can be unadapted to print on "
+ "standard photographic paper."));
+
+ m_preciseCrop = new TQCheckBox(i18n("Exact"), cropSelection);
+ TQWhatsThis::add( m_preciseCrop, i18n("<p>Enable this option to force exact aspect ratio crop."));
+
+ m_orientLabel = new TQLabel(i18n("Orientation:"), cropSelection);
+ m_orientCB = new TQComboBox( false, cropSelection );
+ m_orientCB->insertItem( i18n("Landscape") );
+ m_orientCB->insertItem( i18n("Portrait") );
+ TQWhatsThis::add( m_orientCB, i18n("<p>Select constrained aspect ratio orientation."));
+
+ m_autoOrientation = new TQCheckBox(i18n("Auto"), cropSelection);
+ TQWhatsThis::add( m_autoOrientation, i18n("<p>Enable this option to automatically set the orientation."));
+
+ grid->addMultiCellWidget(label, 0, 0, 0, 0);
+ grid->addMultiCellWidget(m_ratioCB, 0, 0, 1, 3);
+ grid->addMultiCellWidget(m_preciseCrop, 0, 0, 4, 4);
+ grid->addMultiCellWidget(m_orientLabel, 2, 2, 0, 0);
+ grid->addMultiCellWidget(m_orientCB, 2, 2, 1, 3);
+ grid->addMultiCellWidget(m_autoOrientation, 2, 2, 4, 4);
+
+ // -------------------------------------------------------------
+
+ m_customLabel1 = new TQLabel(i18n("Custom ratio:"), cropSelection);
+ m_customLabel1->setAlignment(AlignLeft|AlignVCenter);
+ m_customRatioNInput = new KIntSpinBox(1, 10000, 1, 1, 10, cropSelection);
+ TQWhatsThis::add( m_customRatioNInput, i18n("<p>Set here the desired custom aspect numerator value."));
+ m_customLabel2 = new TQLabel(" : ", cropSelection);
+ m_customLabel2->setAlignment(AlignCenter|AlignVCenter);
+ m_customRatioDInput = new KIntSpinBox(1, 10000, 1, 1, 10, cropSelection);
+ TQWhatsThis::add( m_customRatioDInput, i18n("<p>Set here the desired custom aspect denominator value."));
+
+ grid->addMultiCellWidget(m_customLabel1, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_customRatioNInput, 1, 1, 1, 1);
+ grid->addMultiCellWidget(m_customLabel2, 1, 1, 2, 2);
+ grid->addMultiCellWidget(m_customRatioDInput, 1, 1, 3, 3);
+
+ // -------------------------------------------------------------
+
+ m_xInput = new KIntNumInput(cropSelection);
+ TQWhatsThis::add( m_xInput, i18n("<p>Set here the top left selection corner position for cropping."));
+ m_xInput->setLabel(i18n("X:"), AlignLeft|AlignVCenter);
+ m_xInput->setRange(0, m_imageSelectionWidget->getOriginalImageWidth(), 1, true);
+
+ m_widthInput = new KIntNumInput(cropSelection);
+ m_widthInput->setLabel(i18n("Width:"), AlignLeft|AlignVCenter);
+ TQWhatsThis::add( m_widthInput, i18n("<p>Set here the width selection for cropping."));
+ m_widthInput->setRange(m_imageSelectionWidget->getMinWidthRange(),
+ m_imageSelectionWidget->getMaxWidthRange(),
+ m_imageSelectionWidget->getWidthStep(), true);
+
+ m_centerWidth = new TQPushButton(cropSelection);
+ TDEGlobal::dirs()->addResourceType("centerwidth", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("centerwidth", "centerwidth.png");
+ m_centerWidth->setPixmap( TQPixmap( directory + "centerwidth.png" ) );
+ TQWhatsThis::add( m_centerWidth, i18n("<p>Set width position to center."));
+
+ grid->addMultiCellWidget(m_xInput, 3, 3, 0, 3);
+ grid->addMultiCellWidget(m_widthInput, 4, 4, 0, 3);
+ grid->addMultiCellWidget(m_centerWidth, 3, 3, 4, 4);
+
+ // -------------------------------------------------------------
+
+ m_yInput = new KIntNumInput(cropSelection);
+ m_yInput->setLabel(i18n("Y:"), AlignLeft|AlignVCenter);
+ TQWhatsThis::add( m_yInput, i18n("<p>Set here the top left selection corner position for cropping."));
+ m_yInput->setRange(0, m_imageSelectionWidget->getOriginalImageHeight(), 1, true);
+
+ m_heightInput = new KIntNumInput(cropSelection);
+ m_heightInput->setLabel(i18n("Height:"), AlignLeft|AlignVCenter);
+ TQWhatsThis::add( m_heightInput, i18n("<p>Set here the height selection for cropping."));
+ m_heightInput->setRange(m_imageSelectionWidget->getMinHeightRange(),
+ m_imageSelectionWidget->getMaxHeightRange(),
+ m_imageSelectionWidget->getHeightStep(), true);
+
+ m_centerHeight = new TQPushButton(cropSelection);
+ TDEGlobal::dirs()->addResourceType("centerheight", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("centerheight", "centerheight.png");
+ m_centerHeight->setPixmap( TQPixmap( directory + "centerheight.png" ) );
+ TQWhatsThis::add( m_centerHeight, i18n("<p>Set height position to center."));
+
+ grid->addMultiCellWidget(m_yInput, 5, 5, 0, 3);
+ grid->addMultiCellWidget(m_heightInput, 6, 6, 0, 3);
+ grid->addMultiCellWidget(m_centerHeight, 5, 5, 4, 4);
+
+ gridBox2->addMultiCellWidget(cropSelection, 0, 0, 0, 0);
+
+ // -------------------------------------------------------------
+
+ TQFrame* compositionGuide = new TQFrame( gbox2 );
+ TQGridLayout* grid2 = new TQGridLayout( compositionGuide, 7, 2, spacingHint());
+ compositionGuide->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+
+ TQLabel *labelGuideLines = new TQLabel(i18n("Composition guide:"), compositionGuide);
+ m_guideLinesCB = new TQComboBox( false, compositionGuide );
+ m_guideLinesCB->insertItem( i18n("Rules of Thirds") );
+ m_guideLinesCB->insertItem( i18n("Harmonious Triangles") );
+ m_guideLinesCB->insertItem( i18n("Golden Mean") );
+ m_guideLinesCB->insertItem( i18n("None") );
+ m_guideLinesCB->setCurrentText( i18n("None") );
+ TQWhatsThis::add( m_guideLinesCB, i18n("<p>With this option, you can display guide lines "
+ "which help you to compose your photograph."));
+
+ m_goldenSectionBox = new TQCheckBox(i18n("Golden sections"), compositionGuide);
+ TQWhatsThis::add( m_goldenSectionBox, i18n("<p>Enable this option to show golden sections."));
+
+ m_goldenSpiralSectionBox = new TQCheckBox(i18n("Golden spiral sections"), compositionGuide);
+ TQWhatsThis::add( m_goldenSpiralSectionBox, i18n("<p>Enable this option to show golden spiral sections."));
+
+ m_goldenSpiralBox = new TQCheckBox(i18n("Golden spiral"), compositionGuide);
+ TQWhatsThis::add( m_goldenSpiralBox, i18n("<p>Enable this option to show golden spiral guide."));
+
+ m_goldenTriangleBox = new TQCheckBox(i18n("Golden triangles"), compositionGuide);
+ TQWhatsThis::add( m_goldenTriangleBox, i18n("<p>Enable this option to show golden triangles."));
+
+ m_flipHorBox = new TQCheckBox(i18n("Flip horizontally"), compositionGuide);
+ TQWhatsThis::add( m_flipHorBox, i18n("<p>Enable this option to flip horizontally guidelines."));
+
+ m_flipVerBox = new TQCheckBox(i18n("Flip vertically"), compositionGuide);
+ TQWhatsThis::add( m_flipVerBox, i18n("<p>Enable this option to flip vertically guidelines."));
+
+ m_colorGuideLabel = new TQLabel(i18n("Color and width:"), compositionGuide);
+ m_guideColorBt = new KColorButton( TQColor( 250, 250, 255 ), compositionGuide );
+ m_guideSize = new TQSpinBox( 1, 5, 1, compositionGuide);
+ TQWhatsThis::add( m_guideColorBt, i18n("<p>Set here the color used to draw composition guides."));
+ TQWhatsThis::add( m_guideSize, i18n("<p>Set here the width in pixels used to draw composition guides."));
+
+ grid2->addMultiCellWidget(labelGuideLines, 0, 0, 0, 0);
+ grid2->addMultiCellWidget(m_guideLinesCB, 0, 0, 1, 2);
+ grid2->addMultiCellWidget(m_goldenSectionBox, 1, 1, 0, 2);
+ grid2->addMultiCellWidget(m_goldenSpiralSectionBox, 2, 2, 0, 2);
+ grid2->addMultiCellWidget(m_goldenSpiralBox, 3, 3, 0, 2);
+ grid2->addMultiCellWidget(m_goldenTriangleBox, 4, 4, 0, 2);
+ grid2->addMultiCellWidget(m_flipHorBox, 5, 5, 0, 2);
+ grid2->addMultiCellWidget(m_flipVerBox, 6, 6, 0, 2);
+ grid2->addMultiCellWidget(m_colorGuideLabel, 7, 7, 0, 0);
+ grid2->addMultiCellWidget(m_guideColorBt, 7, 7, 1, 1);
+ grid2->addMultiCellWidget(m_guideSize, 7, 7, 2, 2);
+
+ gridBox2->addMultiCellWidget(compositionGuide, 1, 1, 0, 0);
+ gridBox2->setRowStretch(2, 10);
+
+ setUserAreaWidget(gbox2);
+
+ // -------------------------------------------------------------
+
+ connect(m_ratioCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotRatioChanged(int)));
+
+ connect(m_preciseCrop, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotPreciseCropChanged(bool)));
+
+ connect(m_orientCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotOrientChanged(int)));
+
+ connect(m_autoOrientation, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotAutoOrientChanged(bool)));
+
+ connect(m_xInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotXChanged(int)));
+
+ connect(m_yInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotYChanged(int)));
+
+ connect(m_customRatioNInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotCustomNRatioChanged(int)));
+
+ connect(m_customRatioDInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotCustomDRatioChanged(int)));
+
+ connect(m_guideLinesCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotGuideTypeChanged(int)));
+
+ connect(m_goldenSectionBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_goldenSpiralSectionBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_goldenSpiralBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_goldenTriangleBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_flipHorBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_flipVerBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_guideColorBt, TQ_SIGNAL(changed(const TQColor &)),
+ m_imageSelectionWidget, TQ_SLOT(slotChangeGuideColor(const TQColor &)));
+
+ connect(m_guideSize, TQ_SIGNAL(valueChanged(int)),
+ m_imageSelectionWidget, TQ_SLOT(slotChangeGuideSize(int)));
+
+ connect(m_widthInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotWidthChanged(int)));
+
+ connect(m_heightInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotHeightChanged(int)));
+
+ connect(m_imageSelectionWidget, TQ_SIGNAL(signalSelectionChanged(TQRect)),
+ this, TQ_SLOT(slotSelectionChanged(TQRect)));
+
+ connect(m_imageSelectionWidget, TQ_SIGNAL(signalSelectionMoved(TQRect)),
+ this, TQ_SLOT(slotSelectionChanged(TQRect)));
+
+ connect(m_imageSelectionWidget, TQ_SIGNAL(signalSelectionOrientationChanged(int)),
+ this, TQ_SLOT(slotSelectionOrientationChanged(int)));
+
+ connect(m_centerWidth, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotCenterWidth()));
+
+ connect(m_centerHeight, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotCenterHeight()));
+
+ // -------------------------------------------------------------
+
+ // Sets current region selection
+ slotSelectionChanged(m_imageSelectionWidget->getRegionSelection());
+
+ readSettings();
+}
+
+ImageEffect_RatioCrop::~ImageEffect_RatioCrop()
+{
+}
+
+void ImageEffect_RatioCrop::readSettings()
+{
+ TQColor defaultGuideColor(250, 250, 255);
+ TDEConfig *config = kapp->config();
+ config->setGroup("aspectratiocrop Tool Dialog");
+
+ // No guide lines per default.
+ m_guideLinesCB->setCurrentItem( config->readNumEntry("Guide Lines Type",
+ ImageSelectionWidget::GuideNone) );
+ m_goldenSectionBox->setChecked( config->readBoolEntry("Golden Section", true) );
+ m_goldenSpiralSectionBox->setChecked( config->readBoolEntry("Golden Spiral Section", false) );
+ m_goldenSpiralBox->setChecked( config->readBoolEntry("Golden Spiral", false) );
+ m_goldenTriangleBox->setChecked( config->readBoolEntry("Golden Triangle", false) );
+ m_flipHorBox->setChecked( config->readBoolEntry("Golden Flip Horizontal", false) );
+ m_flipVerBox->setChecked( config->readBoolEntry("Golden Flip Vertical", false) );
+ m_guideColorBt->setColor(config->readColorEntry("Guide Color", &defaultGuideColor));
+ m_guideSize->setValue(config->readNumEntry("Guide Width", 1));
+ m_imageSelectionWidget->slotGuideLines(m_guideLinesCB->currentItem());
+ m_imageSelectionWidget->slotChangeGuideColor(m_guideColorBt->color());
+
+ m_preciseCrop->setChecked( config->readBoolEntry("Precise Aspect Ratio Crop", false) );
+ m_imageSelectionWidget->setPreciseCrop( m_preciseCrop->isChecked() );
+
+ if (m_originalIsLandscape)
+ {
+ m_orientCB->setCurrentItem( config->readNumEntry("Hor.Oriented Aspect Ratio Orientation",
+ ImageSelectionWidget::Landscape) );
+
+ m_imageSelectionWidget->setSelectionOrientation(m_orientCB->currentItem());
+
+ m_customRatioNInput->setValue( config->readNumEntry("Hor.Oriented Custom Aspect Ratio Num", 1) );
+ m_customRatioDInput->setValue( config->readNumEntry("Hor.Oriented Custom Aspect Ratio Den", 1) );
+ m_ratioCB->setCurrentItem( config->readNumEntry("Hor.Oriented Aspect Ratio",
+ ImageSelectionWidget::RATIO03X04) );
+
+ applyRatioChanges(m_ratioCB->currentItem());
+
+ // Empty selection so it can be moved w/out size constraint
+ m_widthInput->setValue( 0 );
+ m_heightInput->setValue( 0 );
+
+ m_xInput->setValue( config->readNumEntry("Hor.Oriented Custom Aspect Ratio Xpos", 50) );
+ m_yInput->setValue( config->readNumEntry("Hor.Oriented Custom Aspect Ratio Ypos", 50) );
+
+ m_widthInput->setValue( config->readNumEntry("Hor.Oriented Custom Aspect Ratio Width", 800) );
+ m_heightInput->setValue( config->readNumEntry("Hor.Oriented Custom Aspect Ratio Height", 600) );
+ }
+ else
+ {
+ m_orientCB->setCurrentItem( config->readNumEntry("Ver.Oriented Aspect Ratio Orientation",
+ ImageSelectionWidget::Portrait) );
+
+ m_imageSelectionWidget->setSelectionOrientation(m_orientCB->currentItem());
+
+ m_customRatioNInput->setValue( config->readNumEntry("Ver.Oriented Custom Aspect Ratio Num", 1) );
+ m_customRatioDInput->setValue( config->readNumEntry("Ver.Oriented Custom Aspect Ratio Den", 1) );
+ m_ratioCB->setCurrentItem( config->readNumEntry("Ver.Oriented Aspect Ratio",
+ ImageSelectionWidget::RATIO03X04) );
+
+ applyRatioChanges(m_ratioCB->currentItem());
+
+ // Empty selection so it can be moved w/out size constraint
+ m_widthInput->setValue( 0 );
+ m_heightInput->setValue( 0 );
+
+ m_xInput->setValue( config->readNumEntry("Ver.Oriented Custom Aspect Ratio Xpos", 50) );
+ m_yInput->setValue( config->readNumEntry("Ver.Oriented Custom Aspect Ratio Ypos", 50) );
+
+ m_widthInput->setValue( config->readNumEntry("Ver.Oriented Custom Aspect Ratio Width", 800) );
+ m_heightInput->setValue( config->readNumEntry("Ver.Oriented Custom Aspect Ratio Height", 600) );
+ }
+
+ m_autoOrientation->setChecked( config->readBoolEntry("Auto Orientation", false) );
+ slotAutoOrientChanged( m_autoOrientation->isChecked() );
+}
+
+void ImageEffect_RatioCrop::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("aspectratiocrop Tool Dialog");
+
+ if (m_originalIsLandscape)
+ {
+ config->writeEntry( "Hor.Oriented Aspect Ratio", m_ratioCB->currentItem() );
+ config->writeEntry( "Hor.Oriented Aspect Ratio Orientation", m_orientCB->currentItem() );
+ config->writeEntry( "Hor.Oriented Custom Aspect Ratio Num", m_customRatioNInput->value() );
+ config->writeEntry( "Hor.Oriented Custom Aspect Ratio Den", m_customRatioDInput->value() );
+
+ config->writeEntry( "Hor.Oriented Custom Aspect Ratio Xpos", m_xInput->value() );
+ config->writeEntry( "Hor.Oriented Custom Aspect Ratio Ypos", m_yInput->value() );
+ config->writeEntry( "Hor.Oriented Custom Aspect Ratio Width", m_widthInput->value() );
+ config->writeEntry( "Hor.Oriented Custom Aspect Ratio Height", m_heightInput->value() );
+ }
+ else
+ {
+ config->writeEntry( "Ver.Oriented Aspect Ratio", m_ratioCB->currentItem() );
+ config->writeEntry( "Ver.Oriented Aspect Ratio Orientation", m_orientCB->currentItem() );
+ config->writeEntry( "Ver.Oriented Custom Aspect Ratio Num", m_customRatioNInput->value() );
+ config->writeEntry( "Ver.Oriented Custom Aspect Ratio Den", m_customRatioDInput->value() );
+
+ config->writeEntry( "Ver.Oriented Custom Aspect Ratio Xpos", m_xInput->value() );
+ config->writeEntry( "Ver.Oriented Custom Aspect Ratio Ypos", m_yInput->value() );
+ config->writeEntry( "Ver.Oriented Custom Aspect Ratio Width", m_widthInput->value() );
+ config->writeEntry( "Ver.Oriented Custom Aspect Ratio Height", m_heightInput->value() );
+ }
+
+ config->writeEntry( "Precise Aspect Ratio Crop", m_preciseCrop->isChecked() );
+ config->writeEntry( "Auto Orientation", m_autoOrientation->isChecked() );
+ config->writeEntry( "Guide Lines Type", m_guideLinesCB->currentItem() );
+ config->writeEntry( "Golden Section", m_goldenSectionBox->isChecked() );
+ config->writeEntry( "Golden Spiral Section", m_goldenSpiralSectionBox->isChecked() );
+ config->writeEntry( "Golden Spiral", m_goldenSpiralBox->isChecked() );
+ config->writeEntry( "Golden Triangle", m_goldenTriangleBox->isChecked() );
+ config->writeEntry( "Golden Flip Horizontal", m_flipHorBox->isChecked() );
+ config->writeEntry( "Golden Flip Vertical", m_flipVerBox->isChecked() );
+ config->writeEntry( "Guide Color", m_guideColorBt->color() );
+ config->writeEntry( "Guide Width", m_guideSize->value() );
+ config->sync();
+}
+
+void ImageEffect_RatioCrop::slotDefault()
+{
+ m_imageSelectionWidget->resetSelection();
+}
+
+void ImageEffect_RatioCrop::slotUser1()
+{
+ m_imageSelectionWidget->maxAspectSelection();
+}
+
+void ImageEffect_RatioCrop::slotCenterWidth()
+{
+ m_imageSelectionWidget->setCenterSelection(ImageSelectionWidget::CenterWidth);
+}
+
+void ImageEffect_RatioCrop::slotCenterHeight()
+{
+ m_imageSelectionWidget->setCenterSelection(ImageSelectionWidget::CenterHeight);
+}
+
+void ImageEffect_RatioCrop::slotSelectionChanged(TQRect rect)
+{
+ m_xInput->blockSignals(true);
+ m_yInput->blockSignals(true);
+ m_widthInput->blockSignals(true);
+ m_heightInput->blockSignals(true);
+
+ m_xInput->setRange(0, m_imageSelectionWidget->getOriginalImageWidth() - rect.width(), 1, true);
+ m_yInput->setRange(0, m_imageSelectionWidget->getOriginalImageHeight() - rect.height(), 1, true);
+ m_widthInput->setRange(m_imageSelectionWidget->getMinWidthRange(),
+ m_imageSelectionWidget->getMaxWidthRange(),
+ m_imageSelectionWidget->getWidthStep(), true);
+ m_heightInput->setRange(m_imageSelectionWidget->getMinHeightRange(),
+ m_imageSelectionWidget->getMaxHeightRange(),
+ m_imageSelectionWidget->getHeightStep(), true);
+
+ m_xInput->setValue(rect.x());
+ m_yInput->setValue(rect.y());
+ m_widthInput->setValue(rect.width());
+ m_heightInput->setValue(rect.height());
+
+ enableButtonOK( rect.isValid() );
+ m_preciseCrop->setEnabled(m_imageSelectionWidget->preciseCropAvailable());
+
+ m_xInput->blockSignals(false);
+ m_yInput->blockSignals(false);
+ m_widthInput->blockSignals(false);
+ m_heightInput->blockSignals(false);
+}
+
+void ImageEffect_RatioCrop::setRatioCBText(int orientation)
+{
+ int item = m_ratioCB->currentItem();
+
+ m_ratioCB->blockSignals(true);
+ m_ratioCB->clear();
+ m_ratioCB->insertItem( i18n("Custom") );
+ m_ratioCB->insertItem( "1:1" );
+ if ( orientation == ImageSelectionWidget::Landscape )
+ {
+ m_ratioCB->insertItem( "3:2" );
+ m_ratioCB->insertItem( "4:3" );
+ m_ratioCB->insertItem( "5:4" );
+ m_ratioCB->insertItem( "7:5" );
+ m_ratioCB->insertItem( "10:7" );
+ }
+ else
+ {
+ m_ratioCB->insertItem( "2:3" );
+ m_ratioCB->insertItem( "3:4" );
+ m_ratioCB->insertItem( "4:5" );
+ m_ratioCB->insertItem( "5:7" );
+ m_ratioCB->insertItem( "7:10" );
+ }
+ m_ratioCB->insertItem( i18n("Golden Ratio") );
+ m_ratioCB->insertItem( i18n("None") );
+ m_ratioCB->setCurrentItem( item );
+ m_ratioCB->blockSignals(false);
+}
+
+void ImageEffect_RatioCrop::slotSelectionOrientationChanged(int newOrientation)
+{
+ // Change text for Aspect ratio ComboBox
+
+ setRatioCBText(newOrientation);
+
+ // Change Orientation ComboBox
+
+ m_orientCB->setCurrentItem(newOrientation);
+
+ // Reverse custom values
+
+ if ( ( m_customRatioNInput->value() < m_customRatioDInput->value() &&
+ newOrientation == ImageSelectionWidget::Landscape ) ||
+ ( m_customRatioNInput->value() > m_customRatioDInput->value() &&
+ newOrientation == ImageSelectionWidget::Portrait ) )
+ {
+ m_customRatioNInput->blockSignals(true);
+ m_customRatioDInput->blockSignals(true);
+
+ int tmp = m_customRatioNInput->value();
+ m_customRatioNInput->setValue( m_customRatioDInput->value() );
+ m_customRatioDInput->setValue( tmp );
+
+ m_customRatioNInput->blockSignals(false);
+ m_customRatioDInput->blockSignals(false);
+ }
+}
+
+void ImageEffect_RatioCrop::slotXChanged(int x)
+{
+ m_imageSelectionWidget->setSelectionX(x);
+}
+
+void ImageEffect_RatioCrop::slotYChanged(int y)
+{
+ m_imageSelectionWidget->setSelectionY(y);
+}
+
+void ImageEffect_RatioCrop::slotWidthChanged(int w)
+{
+ m_imageSelectionWidget->setSelectionWidth(w);
+}
+
+void ImageEffect_RatioCrop::slotHeightChanged(int h)
+{
+ m_imageSelectionWidget->setSelectionHeight(h);
+}
+
+void ImageEffect_RatioCrop::slotPreciseCropChanged(bool a)
+{
+ m_imageSelectionWidget->setPreciseCrop(a);
+}
+
+void ImageEffect_RatioCrop::slotOrientChanged(int o)
+{
+ m_imageSelectionWidget->setSelectionOrientation(o);
+
+ // Reset selection area.
+ slotDefault();
+}
+
+void ImageEffect_RatioCrop::slotAutoOrientChanged(bool a)
+{
+ m_orientCB->setEnabled(!a /*|| m_ratioCB->currentItem() == ImageSelectionWidget::RATIONONE*/);
+ m_imageSelectionWidget->setAutoOrientation(a);
+}
+
+void ImageEffect_RatioCrop::slotRatioChanged(int a)
+{
+ applyRatioChanges(a);
+
+ // Reset selection area.
+ slotDefault();
+}
+
+void ImageEffect_RatioCrop::applyRatioChanges(int a)
+{
+ m_imageSelectionWidget->setSelectionAspectRatioType(a);
+
+ if ( a == ImageSelectionWidget::RATIOCUSTOM )
+ {
+ m_customLabel1->setEnabled(true);
+ m_customLabel2->setEnabled(true);
+ m_customRatioNInput->setEnabled(true);
+ m_customRatioDInput->setEnabled(true);
+ m_orientLabel->setEnabled(true);
+ m_orientCB->setEnabled(! m_autoOrientation->isChecked());
+ m_autoOrientation->setEnabled(true);
+ slotCustomRatioChanged();
+ }
+ else if ( a == ImageSelectionWidget::RATIONONE )
+ {
+ m_orientLabel->setEnabled(false);
+ m_orientCB->setEnabled(false);
+ m_autoOrientation->setEnabled(false);
+ m_customLabel1->setEnabled(false);
+ m_customLabel2->setEnabled(false);
+ m_customRatioNInput->setEnabled(false);
+ m_customRatioDInput->setEnabled(false);
+ }
+ else // Pre-config ratio selected.
+ {
+ m_orientLabel->setEnabled(true);
+ m_orientCB->setEnabled(! m_autoOrientation->isChecked());
+ m_autoOrientation->setEnabled(true);
+ m_customLabel1->setEnabled(false);
+ m_customLabel2->setEnabled(false);
+ m_customRatioNInput->setEnabled(false);
+ m_customRatioDInput->setEnabled(false);
+ }
+}
+
+void ImageEffect_RatioCrop::slotGuideTypeChanged(int t)
+{
+ if ( t == ImageSelectionWidget::GuideNone )
+ {
+ m_goldenSectionBox->setEnabled(false);
+ m_goldenSpiralSectionBox->setEnabled(false);
+ m_goldenSpiralBox->setEnabled(false);
+ m_goldenTriangleBox->setEnabled(false);
+ m_flipHorBox->setEnabled(false);
+ m_flipVerBox->setEnabled(false);
+ m_colorGuideLabel->setEnabled(false);
+ m_guideColorBt->setEnabled(false);
+ m_guideSize->setEnabled(false);
+ }
+ else if ( t == ImageSelectionWidget::RulesOfThirds )
+ {
+ m_goldenSectionBox->setEnabled(false);
+ m_goldenSpiralSectionBox->setEnabled(false);
+ m_goldenSpiralBox->setEnabled(false);
+ m_goldenTriangleBox->setEnabled(false);
+ m_flipHorBox->setEnabled(false);
+ m_flipVerBox->setEnabled(false);
+ m_colorGuideLabel->setEnabled(true);
+ m_guideColorBt->setEnabled(true);
+ m_guideSize->setEnabled(true);
+ }
+ else if ( t == ImageSelectionWidget::HarmoniousTriangles )
+ {
+ m_goldenSectionBox->setEnabled(false);
+ m_goldenSpiralSectionBox->setEnabled(false);
+ m_goldenSpiralBox->setEnabled(false);
+ m_goldenTriangleBox->setEnabled(false);
+ m_flipHorBox->setEnabled(true);
+ m_flipVerBox->setEnabled(true);
+ m_colorGuideLabel->setEnabled(true);
+ m_guideColorBt->setEnabled(true);
+ m_guideSize->setEnabled(true);
+ }
+ else
+ {
+ m_goldenSectionBox->setEnabled(true);
+ m_goldenSpiralSectionBox->setEnabled(true);
+ m_goldenSpiralBox->setEnabled(true);
+ m_goldenTriangleBox->setEnabled(true);
+ m_flipHorBox->setEnabled(true);
+ m_flipVerBox->setEnabled(true);
+ m_colorGuideLabel->setEnabled(true);
+ m_guideColorBt->setEnabled(true);
+ m_guideSize->setEnabled(true);
+ }
+
+ m_imageSelectionWidget->setGoldenGuideTypes(m_goldenSectionBox->isChecked(),
+ m_goldenSpiralSectionBox->isChecked(),
+ m_goldenSpiralBox->isChecked(),
+ m_goldenTriangleBox->isChecked(),
+ m_flipHorBox->isChecked(),
+ m_flipVerBox->isChecked());
+ m_imageSelectionWidget->slotGuideLines(t);
+}
+
+void ImageEffect_RatioCrop::slotGoldenGuideTypeChanged()
+{
+ slotGuideTypeChanged(m_guideLinesCB->currentItem());
+}
+
+void ImageEffect_RatioCrop::slotCustomNRatioChanged(int a)
+{
+ if ( ! m_autoOrientation->isChecked() )
+ {
+ if ( ( m_orientCB->currentItem() == ImageSelectionWidget::Portrait &&
+ m_customRatioDInput->value() < a ) ||
+ ( m_orientCB->currentItem() == ImageSelectionWidget::Landscape &&
+ m_customRatioDInput->value() > a ) )
+ {
+ m_customRatioDInput->blockSignals(true);
+ m_customRatioDInput->setValue(a);
+ m_customRatioDInput->blockSignals(false);
+ }
+ }
+
+ slotCustomRatioChanged();
+}
+
+void ImageEffect_RatioCrop::slotCustomDRatioChanged(int a)
+{
+ if ( ! m_autoOrientation->isChecked() )
+ {
+ if ( ( m_orientCB->currentItem() == ImageSelectionWidget::Landscape &&
+ m_customRatioNInput->value() < a ) ||
+ ( m_orientCB->currentItem() == ImageSelectionWidget::Portrait &&
+ m_customRatioNInput->value() > a ) )
+ {
+ m_customRatioNInput->blockSignals(true);
+ m_customRatioNInput->setValue(a);
+ m_customRatioNInput->blockSignals(false);
+ }
+ }
+
+ slotCustomRatioChanged();
+}
+
+void ImageEffect_RatioCrop::slotCustomRatioChanged()
+{
+ m_imageSelectionWidget->setSelectionAspectRatioValue(
+ m_customRatioNInput->value(), m_customRatioDInput->value() );
+
+ // Reset selection area.
+ slotDefault();
+}
+
+void ImageEffect_RatioCrop::slotOk()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ TQRect currentRegion = m_imageSelectionWidget->getRegionSelection();
+ Digikam::ImageIface* iface = m_imageSelectionWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool a = iface->originalHasAlpha();
+ bool sb = iface->originalSixteenBit();
+
+ TQRect normalizedRegion = currentRegion.normalize();
+ if (normalizedRegion.right() > w) normalizedRegion.setRight(w);
+ if (normalizedRegion.bottom() > h) normalizedRegion.setBottom(h);
+
+ Digikam::DImg imOrg(w, h, sb, a, data);
+ delete [] data;
+ imOrg.crop(normalizedRegion);
+
+ iface->putOriginalImage(i18n("Aspect Ratio Crop"), imOrg.bits(), imOrg.width(), imOrg.height());
+
+ kapp->restoreOverrideCursor();
+ writeSettings();
+ accept();
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/ratiocrop/imageeffect_ratiocrop.h b/src/imageplugins/coreplugin/ratiocrop/imageeffect_ratiocrop.h
new file mode 100644
index 00000000..ca24eeac
--- /dev/null
+++ b/src/imageplugins/coreplugin/ratiocrop/imageeffect_ratiocrop.h
@@ -0,0 +1,132 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-06
+ * Description : digiKam image editor Ratio Crop tool
+ *
+ * Copyright (C) 2007 by Jaromir Malenko <malenko at email dot cz>
+ * Copyright (C) 2008 by Roberto Castagnola <roberto dot castagnola at gmail dot com>
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_RATIOCROP_H
+#define IMAGEEFFECT_RATIOCROP_H
+
+// Digikam include.
+
+#include "imagedlgbase.h"
+
+class TQLabel;
+class TQComboBox;
+class TQPushButton;
+class TQCheckBox;
+class TQSpinBox;
+
+class KIntNumInput;
+class KIntSpinBox;
+class KColorButton;
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageSelectionWidget;
+
+class ImageEffect_RatioCrop : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_RatioCrop(TQWidget *parent);
+ ~ImageEffect_RatioCrop();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+
+ void applyRatioChanges(int a);
+ void setRatioCBText(int orientation);
+
+private slots:
+
+ void slotUser1();
+ void slotDefault();
+ void slotOk();
+
+ void slotCenterWidth();
+ void slotCenterHeight();
+ void slotXChanged(int x);
+ void slotYChanged(int y);
+ void slotWidthChanged(int w);
+ void slotHeightChanged(int h);
+ void slotCustomRatioChanged();
+ void slotCustomNRatioChanged(int a);
+ void slotCustomDRatioChanged(int a);
+ void slotPreciseCropChanged(bool a);
+ void slotOrientChanged(int o);
+ void slotAutoOrientChanged(bool a);
+ void slotRatioChanged(int a);
+ void slotSelectionChanged(TQRect rect );
+ void slotSelectionOrientationChanged(int);
+ void slotGuideTypeChanged(int t);
+ void slotGoldenGuideTypeChanged();
+
+private:
+
+ bool m_originalIsLandscape;
+
+ TQLabel *m_customLabel1;
+ TQLabel *m_customLabel2;
+ TQLabel *m_orientLabel;
+ TQLabel *m_colorGuideLabel;
+
+ TQComboBox *m_ratioCB;
+ TQComboBox *m_orientCB;
+ TQComboBox *m_guideLinesCB;
+
+ TQPushButton *m_centerWidth;
+ TQPushButton *m_centerHeight;
+
+ TQCheckBox *m_goldenSectionBox;
+ TQCheckBox *m_goldenSpiralSectionBox;
+ TQCheckBox *m_goldenSpiralBox;
+ TQCheckBox *m_goldenTriangleBox;
+ TQCheckBox *m_flipHorBox;
+ TQCheckBox *m_flipVerBox;
+ TQCheckBox *m_autoOrientation;
+ TQCheckBox *m_preciseCrop;
+
+ TQSpinBox *m_guideSize;
+
+ KIntNumInput *m_widthInput;
+ KIntNumInput *m_heightInput;
+ KIntNumInput *m_xInput;
+ KIntNumInput *m_yInput;
+
+ KIntSpinBox *m_customRatioNInput;
+ KIntSpinBox *m_customRatioDInput;
+
+ KColorButton *m_guideColorBt;
+
+ ImageSelectionWidget *m_imageSelectionWidget;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_RATIOCROP_H */
diff --git a/src/imageplugins/coreplugin/ratiocrop/imageselectionwidget.cpp b/src/imageplugins/coreplugin/ratiocrop/imageselectionwidget.cpp
new file mode 100644
index 00000000..17eaf415
--- /dev/null
+++ b/src/imageplugins/coreplugin/ratiocrop/imageselectionwidget.cpp
@@ -0,0 +1,1422 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-09
+ * Description : image selection widget used by ratio crop tool.
+ *
+ * Copyright (C) 2007 by Jaromir Malenko <malenko at email.cz>
+ * Copyright (C) 2008 by Roberto Castagnola <roberto dot castagnola at gmail dot com>
+ * Copyright (C) 2004-2009 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#define OPACITY 0.7
+#define RCOL 0xAA
+#define GCOL 0xAA
+#define BCOL 0xAA
+
+#define MINRANGE 0
+
+// Golden number (1+sqrt(5))/2
+#define PHI 1.61803398874989479
+// 1/PHI
+#define INVPHI 0.61803398874989479
+
+// C++ includes.
+
+#include <iostream>
+#include <cstdio>
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqregion.h>
+#include <tqcolor.h>
+#include <tqpainter.h>
+#include <tqbrush.h>
+#include <tqpixmap.h>
+#include <tqimage.h>
+#include <tqpen.h>
+#include <tqpoint.h>
+#include <tqtimer.h>
+#include <tqsizepolicy.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdeglobal.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imageiface.h"
+#include "dimg.h"
+#include "imageselectionwidget.h"
+#include "imageselectionwidget.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageSelectionWidgetPriv
+{
+public:
+
+ enum ResizingMode
+ {
+ ResizingNone = 0,
+ ResizingTopLeft,
+ ResizingTopRight,
+ ResizingBottomLeft,
+ ResizingBottomRight
+ };
+
+ ImageSelectionWidgetPriv()
+ {
+ currentResizing = ResizingNone;
+ iface = 0;
+ pixmap = 0;
+ guideSize = 1;
+ }
+
+ // Golden guide types.
+ bool drawGoldenSection;
+ bool drawGoldenSpiralSection;
+ bool drawGoldenSpiral;
+ bool drawGoldenTriangle;
+
+ // Golden guide translations.
+ bool flipHorGoldenGuide;
+ bool flipVerGoldenGuide;
+
+ bool moving;
+ bool autoOrientation;
+ bool preciseCrop;
+
+ int guideLinesType;
+ int guideSize;
+
+ int currentAspectRatioType;
+ int currentResizing;
+ int currentOrientation;
+
+ float currentWidthRatioValue;
+ float currentHeightRatioValue;
+
+ TQPoint lastPos;
+
+ TQRect rect;
+ TQRect image; // Real image dimension.
+ TQRect regionSelection; // Real size image selection.
+ TQRect localRegionSelection; // Local size selection.
+
+ // Draggable local region selection corners.
+ TQRect localTopLeftCorner;
+ TQRect localBottomLeftCorner;
+ TQRect localTopRightCorner;
+ TQRect localBottomRightCorner;
+
+ TQPixmap *pixmap;
+
+ TQColor guideColor;
+
+ Digikam::DImg preview;
+
+ Digikam::ImageIface *iface;
+};
+
+ImageSelectionWidget::ImageSelectionWidget(int w, int h, TQWidget *parent,
+ int widthRatioValue, int heightRatioValue,
+ int aspectRatioType, int orient, int guideLinesType)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ d = new ImageSelectionWidgetPriv;
+ d->currentAspectRatioType = aspectRatioType;
+ d->currentWidthRatioValue = widthRatioValue;
+ d->currentHeightRatioValue = heightRatioValue;
+ d->currentOrientation = orient;
+ d->guideLinesType = guideLinesType;
+ d->autoOrientation = false;
+ d->preciseCrop = false;
+ d->moving = true;
+ reverseRatioValues();
+
+ setBackgroundMode(TQt::NoBackground);
+ setMinimumSize(w, h);
+ setMouseTracking(true);
+
+ d->iface = new Digikam::ImageIface(w, h);
+ uchar *data = d->iface->getPreviewImage();
+ int width = d->iface->previewWidth();
+ int height = d->iface->previewHeight();
+ bool sixteenBit = d->iface->previewSixteenBit();
+ bool hasAlpha = d->iface->previewHasAlpha();
+ d->preview = Digikam::DImg(width, height, sixteenBit, hasAlpha, data);
+ delete [] data;
+ d->preview.convertToEightBit();
+ d->pixmap = new TQPixmap(w, h);
+
+ d->image = TQRect(0, 0, d->iface->originalWidth(), d->iface->originalHeight());
+ d->rect = TQRect(w/2-d->preview.width()/2, h/2-d->preview.height()/2,
+ d->preview.width(), d->preview.height());
+ updatePixmap();
+ setGoldenGuideTypes(true, false, false, false, false, false);
+}
+
+ImageSelectionWidget::~ImageSelectionWidget()
+{
+ delete d->iface;
+ delete d->pixmap;
+ delete d;
+}
+
+Digikam::ImageIface* ImageSelectionWidget::imageIface()
+{
+ return d->iface;
+}
+
+void ImageSelectionWidget::resizeEvent(TQResizeEvent *e)
+{
+ delete d->pixmap;
+
+ int w = e->size().width();
+ int h = e->size().height();
+
+ uchar *data = d->iface->setPreviewImageSize(w, h);
+ int width = d->iface->previewWidth();
+ int height = d->iface->previewHeight();
+ bool sixteenBit = d->iface->previewSixteenBit();
+ bool hasAlpha = d->iface->previewHasAlpha();
+ d->preview = Digikam::DImg(width, height, sixteenBit, hasAlpha, data);
+ delete [] data;
+ d->preview.convertToEightBit();
+
+ d->pixmap = new TQPixmap(w, h);
+
+ d->rect = TQRect(w/2-d->preview.width()/2, h/2-d->preview.height()/2,
+ d->preview.width(), d->preview.height());
+ updatePixmap();
+}
+
+int ImageSelectionWidget::getOriginalImageWidth()
+{
+ return d->image.width();
+}
+
+int ImageSelectionWidget::getOriginalImageHeight()
+{
+ return d->image.height();
+}
+
+TQRect ImageSelectionWidget::getRegionSelection()
+{
+ return d->regionSelection;
+}
+
+int ImageSelectionWidget::getMinWidthRange()
+{
+ return MINRANGE;
+}
+
+int ImageSelectionWidget::getMinHeightRange()
+{
+ return MINRANGE;
+}
+
+int ImageSelectionWidget::getMaxWidthRange()
+{
+ int maxW = d->image.width() - d->regionSelection.left();
+
+ if (d->currentAspectRatioType != RATIONONE)
+ {
+ // Compute max width taking aspect ratio into account
+ int t = d->currentWidthRatioValue > d->currentHeightRatioValue ? 1 : 0;
+ int h = d->image.height() - d->regionSelection.top();
+ int w = rint( ( h + t ) * d->currentWidthRatioValue /
+ d->currentHeightRatioValue ) - t;
+ if ( w < maxW )
+ maxW = w;
+ }
+
+ // Return max width adjusted if a precise crop is wanted
+ return computePreciseSize(maxW, d->currentWidthRatioValue);
+}
+
+int ImageSelectionWidget::getMaxHeightRange()
+{
+ int maxH = d->image.height() - d->regionSelection.top();
+
+ if (d->currentAspectRatioType != RATIONONE)
+ {
+ // Compute max height taking aspect ratio into account
+ int t = d->currentHeightRatioValue > d->currentWidthRatioValue ? 1 : 0;
+ int w = d->image.width() - d->regionSelection.left();
+ int h = rint( ( w + t ) * d->currentHeightRatioValue /
+ d->currentWidthRatioValue ) - t;
+ if ( h < maxH )
+ maxH = h;
+ }
+
+ // Return max height adjusted if a precise crop is wanted
+ return computePreciseSize(maxH, d->currentHeightRatioValue);
+}
+
+int ImageSelectionWidget::getWidthStep()
+{
+ if ( d->preciseCrop && preciseCropAvailable() )
+ return d->currentWidthRatioValue;
+ else
+ return 1;
+}
+
+int ImageSelectionWidget::getHeightStep()
+{
+ if ( d->preciseCrop && preciseCropAvailable() )
+ return d->currentHeightRatioValue;
+ else
+ return 1;
+}
+
+// Draw a new centered selection with half width (if orientation = Landscape)
+// or with half height (if orientation = Portrait)
+void ImageSelectionWidget::resetSelection()
+{
+ d->regionSelection.setWidth(d->image.width()/2);
+ d->regionSelection.setHeight(d->image.height()/2);
+ applyAspectRatio(d->currentOrientation == Portrait, false);
+
+ setCenterSelection(CenterImage);
+}
+
+void ImageSelectionWidget::setCenterSelection(int centerType)
+{
+ // Adjust selection size if bigger than real image
+ if ( d->regionSelection.height() > d->image.height() )
+ {
+ d->regionSelection.setHeight(d->image.height());
+ applyAspectRatio(true, false);
+ }
+ if ( d->regionSelection.width() > d->image.width() )
+ {
+ d->regionSelection.setWidth(d->image.width());
+ applyAspectRatio(false, false);
+ }
+
+ // Set center point for selection
+ TQPoint center = d->image.center();
+ switch (centerType)
+ {
+ case CenterWidth:
+ center.setY(d->regionSelection.center().y());
+ break;
+
+ case CenterHeight:
+ center.setX(d->regionSelection.center().x());
+ break;
+ }
+ d->regionSelection.moveCenter(center);
+
+ // Repaint
+ updatePixmap();
+ repaint(false);
+ regionSelectionChanged();
+}
+
+// Draw a new centered selection with max size
+void ImageSelectionWidget::maxAspectSelection()
+{
+ d->regionSelection.setWidth(d->image.width());
+ d->regionSelection.setHeight(d->image.height());
+ if ( d->currentAspectRatioType != RATIONONE )
+ applyAspectRatio(d->currentOrientation == Portrait, false);
+
+ setCenterSelection(CenterImage);
+}
+
+void ImageSelectionWidget::setGoldenGuideTypes(bool drawGoldenSection, bool drawGoldenSpiralSection,
+ bool drawGoldenSpiral, bool drawGoldenTriangle,
+ bool flipHorGoldenGuide, bool flipVerGoldenGuide)
+{
+ d->drawGoldenSection = drawGoldenSection;
+ d->drawGoldenSpiralSection = drawGoldenSpiralSection;
+ d->drawGoldenSpiral = drawGoldenSpiral;
+ d->drawGoldenTriangle = drawGoldenTriangle;
+ d->flipHorGoldenGuide = flipHorGoldenGuide;
+ d->flipVerGoldenGuide = flipVerGoldenGuide;
+}
+
+void ImageSelectionWidget::slotGuideLines(int guideLinesType)
+{
+ d->guideLinesType = guideLinesType;
+ updatePixmap();
+ repaint(false);
+}
+
+void ImageSelectionWidget::slotChangeGuideColor(const TQColor &color)
+{
+ d->guideColor = color;
+ updatePixmap();
+ repaint(false);
+}
+
+void ImageSelectionWidget::slotChangeGuideSize(int size)
+{
+ d->guideSize = size;
+ updatePixmap();
+ repaint(false);
+}
+
+void ImageSelectionWidget::setSelectionOrientation(int orient)
+{
+ d->currentOrientation = orient;
+ reverseRatioValues();
+ applyAspectRatio(true);
+ emit signalSelectionOrientationChanged( d->currentOrientation );
+}
+
+void ImageSelectionWidget::setSelectionAspectRatioType(int aspectRatioType)
+{
+ d->currentAspectRatioType = aspectRatioType;
+
+ // Set ratio values
+ switch(aspectRatioType)
+ {
+ case RATIO01X01:
+ d->currentWidthRatioValue = 1.0;
+ d->currentHeightRatioValue = 1.0;
+ break;
+
+ case RATIO03X04:
+ d->currentWidthRatioValue = 4.0;
+ d->currentHeightRatioValue = 3.0;
+ break;
+
+ case RATIO02x03:
+ d->currentWidthRatioValue = 3.0;
+ d->currentHeightRatioValue = 2.0;
+ break;
+
+ case RATIO05x07:
+ d->currentWidthRatioValue = 7.0;
+ d->currentHeightRatioValue = 5.0;
+ break;
+
+ case RATIO07x10:
+ d->currentWidthRatioValue = 10.0;
+ d->currentHeightRatioValue = 7.0;
+ break;
+
+ case RATIO04X05:
+ d->currentWidthRatioValue = 5.0;
+ d->currentHeightRatioValue = 4.0;
+ break;
+
+ case RATIOGOLDEN:
+ d->currentWidthRatioValue = PHI;
+ d->currentHeightRatioValue = 1.0;
+ break;
+ }
+
+ reverseRatioValues();
+ applyAspectRatio(false);
+}
+
+void ImageSelectionWidget::setSelectionAspectRatioValue(int widthRatioValue,
+ int heightRatioValue)
+{
+ int gdc = widthRatioValue;
+
+ // Compute greatest common divisor using Euclidean algorithm
+ for (int tmp, mod = heightRatioValue; mod != 0; mod = tmp % mod)
+ {
+ tmp = gdc;
+ gdc = mod;
+ }
+
+ d->currentWidthRatioValue = widthRatioValue / gdc;
+ d->currentHeightRatioValue = heightRatioValue / gdc;
+ d->currentAspectRatioType = RATIOCUSTOM;
+
+ // Fix orientation
+ if ( d->autoOrientation )
+ {
+ if ( heightRatioValue > widthRatioValue &&
+ d->currentOrientation == Landscape )
+ {
+ d->currentOrientation = Portrait;
+ emit signalSelectionOrientationChanged( d->currentOrientation );
+ }
+ else if ( widthRatioValue > heightRatioValue &&
+ d->currentOrientation == Portrait )
+ {
+ d->currentOrientation = Landscape;
+ emit signalSelectionOrientationChanged( d->currentOrientation );
+ }
+ }
+ else
+ reverseRatioValues();
+
+ applyAspectRatio(false);
+}
+
+void ImageSelectionWidget::reverseRatioValues()
+{
+ // Reverse ratio values if needed
+ if ( ( d->currentWidthRatioValue > d->currentHeightRatioValue &&
+ d->currentOrientation == Portrait ) ||
+ ( d->currentHeightRatioValue > d->currentWidthRatioValue &&
+ d->currentOrientation == Landscape ) )
+ {
+ float tmp = d->currentWidthRatioValue;
+ d->currentWidthRatioValue = d->currentHeightRatioValue;
+ d->currentHeightRatioValue = tmp;
+ }
+}
+
+bool ImageSelectionWidget::preciseCropAvailable()
+{
+ // Define when precise crop feature can be used
+ // No needed when aspect ratio is 1:1
+ switch(d->currentAspectRatioType)
+ {
+ case RATIONONE:
+ case RATIO01X01:
+ case RATIOGOLDEN:
+ return false;
+
+ case RATIOCUSTOM:
+ return ( d->currentWidthRatioValue != d->currentHeightRatioValue );
+
+ default:
+ return true;
+ }
+}
+
+void ImageSelectionWidget::setPreciseCrop(bool precise)
+{
+ d->preciseCrop = precise;
+ applyAspectRatio(false, true);
+ regionSelectionChanged();
+}
+
+void ImageSelectionWidget::setAutoOrientation(bool orientation)
+{
+ d->autoOrientation = orientation;
+}
+
+void ImageSelectionWidget::setSelectionX(int x)
+{
+ d->regionSelection.moveLeft(x);
+ regionSelectionMoved();
+}
+
+void ImageSelectionWidget::setSelectionY(int y)
+{
+ d->regionSelection.moveTop(y);
+ regionSelectionMoved();
+}
+
+void ImageSelectionWidget::setSelectionWidth(int w)
+{
+ d->regionSelection.setWidth(w);
+ applyAspectRatio(false, true);
+
+ regionSelectionChanged();
+}
+
+void ImageSelectionWidget::setSelectionHeight(int h)
+{
+ d->regionSelection.setHeight(h);
+ applyAspectRatio(true, true);
+
+ regionSelectionChanged();
+}
+
+TQPoint ImageSelectionWidget::convertPoint(const TQPoint pm, bool localToReal)
+{
+ return convertPoint(pm.x(), pm.y(), localToReal);
+}
+
+TQPoint ImageSelectionWidget::convertPoint(int x, int y, bool localToReal)
+{
+ int pmX, pmY;
+
+ if (localToReal)
+ {
+ pmX = ( x - d->rect.left() ) * (float)d->image.width() /
+ (float)d->preview.width();
+
+ pmY = ( y - d->rect.top() ) * (float)d->image.height() /
+ (float)d->preview.height();
+ }
+ else
+ {
+ pmX = d->rect.left() + ( x * (float)d->preview.width() /
+ (float)d->image.width() );
+
+ pmY = d->rect.top() + ( y * (float)d->preview.height() /
+ (float)d->image.height() );
+ }
+
+ return TQPoint(pmX, pmY);
+}
+
+int ImageSelectionWidget::computePreciseSize(int size, int step)
+{
+ // Adjust size if precise crop is wanted
+ if ( d->preciseCrop && preciseCropAvailable() )
+ size = int(size / step) * step;
+
+ return size;
+}
+
+void ImageSelectionWidget::applyAspectRatio(bool useHeight, bool repaintWidget)
+{
+ // Save selection area for re-adjustment after changing width and height.
+ TQRect oldRegionSelection = d->regionSelection;
+
+ if ( !useHeight ) // Width changed.
+ {
+ int w = computePreciseSize(d->regionSelection.width(),
+ d->currentWidthRatioValue);
+
+ d->regionSelection.setWidth(w);
+ switch(d->currentAspectRatioType)
+ {
+ case RATIONONE:
+ break;
+
+ default:
+ d->regionSelection.setHeight(rint( w * d->currentHeightRatioValue /
+ d->currentWidthRatioValue ) );
+ break;
+ }
+ }
+ else // Height changed.
+ {
+ int h = computePreciseSize(d->regionSelection.height(),
+ d->currentHeightRatioValue);
+
+ d->regionSelection.setHeight(h);
+ switch(d->currentAspectRatioType)
+ {
+ case RATIONONE:
+ break;
+
+ default:
+ d->regionSelection.setWidth(rint( h * d->currentWidthRatioValue /
+ d->currentHeightRatioValue ) );
+ break;
+ }
+ }
+
+ // If we change selection size by a corner, re-adjust the oposite corner position.
+ switch(d->currentResizing)
+ {
+ case ImageSelectionWidgetPriv::ResizingTopLeft:
+ d->regionSelection.moveBottomRight( oldRegionSelection.bottomRight() );
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingTopRight:
+ d->regionSelection.moveBottomLeft( oldRegionSelection.bottomLeft() );
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingBottomLeft:
+ d->regionSelection.moveTopRight( oldRegionSelection.topRight() );
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingBottomRight:
+ d->regionSelection.moveTopLeft( oldRegionSelection.topLeft() );
+ break;
+ }
+
+ if (repaintWidget)
+ {
+ updatePixmap();
+ repaint(false);
+ }
+}
+
+void ImageSelectionWidget::normalizeRegion()
+{
+ // Perform normalization of selection area.
+
+ if (d->regionSelection.left() < d->image.left())
+ d->regionSelection.moveLeft(d->image.left());
+
+ if (d->regionSelection.top() < d->image.top())
+ d->regionSelection.moveTop(d->image.top());
+
+ if (d->regionSelection.right() > d->image.right())
+ d->regionSelection.moveRight(d->image.right());
+
+ if (d->regionSelection.bottom() > d->image.bottom())
+ d->regionSelection.moveBottom(d->image.bottom());
+}
+
+void ImageSelectionWidget::regionSelectionMoved()
+{
+ normalizeRegion();
+
+ updatePixmap();
+ repaint(false);
+
+ emit signalSelectionMoved( d->regionSelection );
+}
+
+void ImageSelectionWidget::regionSelectionChanged()
+{
+ // Compute the intersection of selection region and image region
+ TQRect cut = d->regionSelection & d->image;
+
+ // Adjust selection size if it was cropped
+ if ( d->regionSelection.width() > cut.width() )
+ {
+ d->regionSelection = cut;
+ applyAspectRatio(false);
+ }
+ if ( d->regionSelection.height() > cut.height() )
+ {
+ d->regionSelection = cut;
+ applyAspectRatio(true);
+ }
+
+ emit signalSelectionChanged( d->regionSelection );
+}
+
+void ImageSelectionWidget::updatePixmap()
+{
+ // Updated local selection region.
+ d->localRegionSelection.setTopLeft(
+ convertPoint(d->regionSelection.topLeft(), false));
+ d->localRegionSelection.setBottomRight(
+ convertPoint(d->regionSelection.bottomRight(), false));
+
+ // Updated dragging corners region.
+ d->localTopLeftCorner.setRect(d->localRegionSelection.left(),
+ d->localRegionSelection.top(), 8, 8);
+ d->localBottomLeftCorner.setRect(d->localRegionSelection.left(),
+ d->localRegionSelection.bottom() - 7, 8, 8);
+ d->localTopRightCorner.setRect(d->localRegionSelection.right() - 7,
+ d->localRegionSelection.top(), 8, 8);
+ d->localBottomRightCorner.setRect(d->localRegionSelection.right() - 7,
+ d->localRegionSelection.bottom() - 7, 8, 8);
+
+ // Drawing background and image.
+ d->pixmap->fill(colorGroup().background());
+
+ if (d->preview.isNull())
+ return;
+
+ // Drawing region outside selection grayed.
+
+ Digikam::DImg image = d->preview.copy();
+
+ uchar* ptr = image.bits();
+ uchar r, g, b;
+
+ for (int y=d->rect.top() ; y <= d->rect.bottom() ; y++)
+ {
+ for (int x=d->rect.left() ; x <= d->rect.right() ; x++)
+ {
+ if (! d->localRegionSelection.contains(x, y, true) )
+ {
+ b = ptr[0];
+ g = ptr[1];
+ r = ptr[2];
+
+ r += (uchar)((RCOL - r) * OPACITY);
+ g += (uchar)((GCOL - g) * OPACITY);
+ b += (uchar)((BCOL - b) * OPACITY);
+
+ ptr[0] = b;
+ ptr[1] = g;
+ ptr[2] = r;
+ }
+
+ ptr+=4;
+ }
+ }
+
+ TQPixmap pix = d->iface->convertToPixmap(image);
+ bitBlt(d->pixmap, d->rect.x(), d->rect.y(), &pix);
+
+ // Stop here if no selection to draw
+ if ( d->regionSelection.isEmpty() )
+ return;
+
+ TQPainter p(d->pixmap);
+
+ // Drawing selection borders.
+
+ p.setPen(TQPen(TQColor(250, 250, 255), 1, TQt::SolidLine));
+ p.drawRect(d->localRegionSelection);
+
+ // Drawing selection corners.
+
+ p.drawRect(d->localTopLeftCorner);
+ p.drawRect(d->localBottomLeftCorner);
+ p.drawRect(d->localTopRightCorner);
+ p.drawRect(d->localBottomRightCorner);
+
+ // Drawing guide lines.
+
+ // Constraint drawing only on local selection region.
+ // This is needed because arcs and incurved lines can draw
+ // outside a little of local selection region.
+ p.setClipping(true);
+ p.setClipRect(d->localRegionSelection);
+
+ switch (d->guideLinesType)
+ {
+ case RulesOfThirds:
+ {
+ int xThird = d->localRegionSelection.width() / 3;
+ int yThird = d->localRegionSelection.height() / 3;
+
+ p.setPen(TQPen(TQt::white, d->guideSize, TQt::SolidLine));
+ p.drawLine( d->localRegionSelection.left() + xThird, d->localRegionSelection.top(),
+ d->localRegionSelection.left() + xThird, d->localRegionSelection.bottom() );
+ p.drawLine( d->localRegionSelection.left() + 2*xThird, d->localRegionSelection.top(),
+ d->localRegionSelection.left() + 2*xThird, d->localRegionSelection.bottom() );
+
+ p.drawLine( d->localRegionSelection.left(), d->localRegionSelection.top() + yThird,
+ d->localRegionSelection.right(), d->localRegionSelection.top() + yThird );
+ p.drawLine( d->localRegionSelection.left(), d->localRegionSelection.top() + 2*yThird,
+ d->localRegionSelection.right(), d->localRegionSelection.top() + 2*yThird );
+
+ p.setPen(TQPen(d->guideColor, d->guideSize, TQt::DotLine));
+ p.drawLine( d->localRegionSelection.left() + xThird, d->localRegionSelection.top(),
+ d->localRegionSelection.left() + xThird, d->localRegionSelection.bottom() );
+ p.drawLine( d->localRegionSelection.left() + 2*xThird, d->localRegionSelection.top(),
+ d->localRegionSelection.left() + 2*xThird, d->localRegionSelection.bottom() );
+
+ p.drawLine( d->localRegionSelection.left(), d->localRegionSelection.top() + yThird,
+ d->localRegionSelection.right(), d->localRegionSelection.top() + yThird );
+ p.drawLine( d->localRegionSelection.left(), d->localRegionSelection.top() + 2*yThird,
+ d->localRegionSelection.right(), d->localRegionSelection.top() + 2*yThird );
+ break;
+ }
+
+ case DiagonalMethod:
+ {
+ // Move coordinates to top, left
+ p.translate(d->localRegionSelection.topLeft().x(), d->localRegionSelection.topLeft().y());
+
+ float w = (float)d->localRegionSelection.width();
+ float h = (float)d->localRegionSelection.height();
+
+ p.setPen(TQPen(TQt::white, d->guideSize, TQt::SolidLine));
+ if (w > h)
+ {
+ p.drawLine( 0, 0, h, h);
+ p.drawLine( 0, h, h, 0);
+ p.drawLine( w-h, 0, w, h);
+ p.drawLine( w-h, h, w, 0);
+
+ }
+ else
+ {
+ p.drawLine( 0, 0, w, w);
+ p.drawLine( 0, w, w, 0);
+ p.drawLine( 0, h-w, w, h);
+ p.drawLine( 0, h, w, h-w);
+ }
+
+ p.setPen(TQPen(d->guideColor, d->guideSize, TQt::DotLine));
+ if (w > h)
+ {
+ p.drawLine( 0, 0, h, h);
+ p.drawLine( 0, h, h, 0);
+ p.drawLine( w-h, 0, w, h);
+ p.drawLine( w-h, h, w, 0);
+
+ }
+ else
+ {
+ p.drawLine( 0, 0, w, w);
+ p.drawLine( 0, w, w, 0);
+ p.drawLine( 0, h-w, w, h);
+ p.drawLine( 0, h, w, h-w);
+ }
+ break;
+ }
+
+ case HarmoniousTriangles:
+ {
+ // Move coordinates to local center selection.
+ p.translate(d->localRegionSelection.center().x(), d->localRegionSelection.center().y());
+
+ // Flip horizontal.
+ if (d->flipHorGoldenGuide)
+ p.scale(-1, 1);
+
+ // Flip verical.
+ if (d->flipVerGoldenGuide)
+ p.scale(1, -1);
+
+ float w = (float)d->localRegionSelection.width();
+ float h = (float)d->localRegionSelection.height();
+ int dst = (int)((h*cos(atan(w/h)) / (cos(atan(h/w)))));
+
+ p.setPen(TQPen(TQt::white, d->guideSize, TQt::SolidLine));
+ p.drawLine( -d->localRegionSelection.width()/2, -d->localRegionSelection.height()/2,
+ d->localRegionSelection.width()/2, d->localRegionSelection.height()/2);
+
+ p.drawLine( -d->localRegionSelection.width()/2 + dst, -d->localRegionSelection.height()/2,
+ -d->localRegionSelection.width()/2, d->localRegionSelection.height()/2);
+
+ p.drawLine( d->localRegionSelection.width()/2, -d->localRegionSelection.height()/2,
+ d->localRegionSelection.width()/2 - dst, d->localRegionSelection.height()/2);
+
+ p.setPen(TQPen(d->guideColor, d->guideSize, TQt::DotLine));
+ p.drawLine( -d->localRegionSelection.width()/2, -d->localRegionSelection.height()/2,
+ d->localRegionSelection.width()/2, d->localRegionSelection.height()/2);
+
+ p.drawLine( -d->localRegionSelection.width()/2 + dst, -d->localRegionSelection.height()/2,
+ -d->localRegionSelection.width()/2, d->localRegionSelection.height()/2);
+
+ p.drawLine( d->localRegionSelection.width()/2, -d->localRegionSelection.height()/2,
+ d->localRegionSelection.width()/2 - dst, d->localRegionSelection.height()/2);
+ break;
+ }
+
+ case GoldenMean:
+ {
+ // Move coordinates to local center selection.
+ p.translate(d->localRegionSelection.center().x(), d->localRegionSelection.center().y());
+
+ // Flip horizontal.
+ if (d->flipHorGoldenGuide)
+ p.scale(-1, 1);
+
+ // Flip vertical.
+ if (d->flipVerGoldenGuide)
+ p.scale(1, -1);
+
+ int w = d->localRegionSelection.width();
+ int h = d->localRegionSelection.height();
+
+ // lengths for the golden mean and half the sizes of the region:
+ int w_g = (int)(w*INVPHI);
+ int h_g = (int)(h*INVPHI);
+ int w_2 = w/2;
+ int h_2 = h/2;
+
+ TQRect R1(-w_2, -h_2, w_g, h);
+ // w - 2*w_2 corrects for one-pixel difference
+ // so that R2.right() is really at the right end of the region
+ TQRect R2(w_g-w_2, h_2-h_g, w-w_g+1-(w - 2*w_2), h_g);
+
+ TQRect R3((int)(w_2 - R2.width()*INVPHI), -h_2,
+ (int)(R2.width()*INVPHI), h - R2.height());
+ TQRect R4(R2.x(), R1.y(), R3.x() - R2.x(),
+ (int)(R3.height()*INVPHI));
+ TQRect R5(R4.x(), R4.bottom(), (int)(R4.width()*INVPHI),
+ R3.height() - R4.height());
+ TQRect R6(R5.x() + R5.width(), R5.bottom() - (int)(R5.height()*INVPHI),
+ R3.x() - R5.right(), (int)(R5.height()*INVPHI));
+ TQRect R7(R6.right() - (int)(R6.width()*INVPHI), R4.bottom(),
+ (int)(R6.width()*INVPHI), R5.height() - R6.height());
+
+ p.setPen(TQPen(TQt::white, d->guideSize, TQt::SolidLine));
+
+ // Drawing Golden sections.
+ if (d->drawGoldenSection)
+ {
+ // horizontal lines:
+ p.drawLine( R1.left(), R2.top(),
+ R2.right(), R2.top());
+
+ p.drawLine( R1.left(), R1.top() + R2.height(),
+ R2.right(), R1.top() + R2.height());
+
+ // vertical lines:
+ p.drawLine( R1.right(), R1.top(),
+ R1.right(), R1.bottom() );
+
+ p.drawLine( R1.left()+R2.width(), R1.top(),
+ R1.left()+R2.width(), R1.bottom() );
+ }
+
+ // Drawing Golden triangle guides.
+ if (d->drawGoldenTriangle)
+ {
+ p.drawLine( R1.left(), R1.bottom(),
+ R2.right(), R1.top() );
+
+ p.drawLine( R1.left(), R1.top(),
+ R2.right() - R1.width(), R1.bottom());
+
+ p.drawLine( R1.left() + R1.width(), R1.top(),
+ R2.right(), R1.bottom() );
+ }
+
+ // Drawing Golden spiral sections.
+ if (d->drawGoldenSpiralSection)
+ {
+ p.drawLine( R1.topRight(), R1.bottomRight() );
+ p.drawLine( R2.topLeft(), R2.topRight() );
+ p.drawLine( R3.topLeft(), R3.bottomLeft() );
+ p.drawLine( R4.bottomLeft(), R4.bottomRight() );
+ p.drawLine( R5.topRight(), R5.bottomRight() );
+ p.drawLine( R6.topLeft(), R6.topRight() );
+ p.drawLine( R7.topLeft(), R7.bottomLeft() );
+ }
+
+ // Drawing Golden Spiral.
+ if (d->drawGoldenSpiral)
+ {
+ p.drawArc ( R1.left(),
+ R1.top() - R1.height(),
+ 2*R1.width(), 2*R1.height(),
+ 180*16, 90*16);
+
+ p.drawArc ( R2.right() - 2*R2.width(),
+ R1.bottom() - 2*R2.height(),
+ 2*R2.width(), 2*R2.height(),
+ 270*16, 90*16);
+
+ p.drawArc ( R2.right() - 2*R3.width(),
+ R3.top(),
+ 2*R3.width(), 2*R3.height(),
+ 0, 90*16);
+
+ p.drawArc ( R4.left(),
+ R4.top(),
+ 2*R4.width(), 2*R4.height(),
+ 90*16, 90*16);
+
+ p.drawArc ( R5.left(),
+ R5.top()-R5.height(),
+ 2*R5.width(), 2*R5.height(),
+ 180*16, 90*16);
+
+ p.drawArc ( R6.left()-R6.width(),
+ R6.top()-R6.height(),
+ 2*R6.width(), 2*R6.height(),
+ 270*16, 90*16);
+
+ p.drawArc ( R7.left()-R7.width(),
+ R7.top(),
+ 2*R7.width(), 2*R7.height(),
+ 0, 90*16);
+ }
+
+ p.setPen(TQPen(d->guideColor, d->guideSize, TQt::DotLine));
+
+ // Drawing Golden sections.
+ if (d->drawGoldenSection)
+ {
+ // horizontal lines:
+ p.drawLine( R1.left(), R2.top(),
+ R2.right(), R2.top());
+
+ p.drawLine( R1.left(), R1.top() + R2.height(),
+ R2.right(), R1.top() + R2.height());
+
+ // vertical lines:
+ p.drawLine( R1.right(), R1.top(),
+ R1.right(), R1.bottom() );
+
+ p.drawLine( R1.left()+R2.width(), R1.top(),
+ R1.left()+R2.width(), R1.bottom() );
+ }
+
+ // Drawing Golden triangle guides.
+ if (d->drawGoldenTriangle)
+ {
+ p.drawLine( R1.left(), R1.bottom(),
+ R2.right(), R1.top() );
+
+ p.drawLine( R1.left(), R1.top(),
+ R2.right() - R1.width(), R1.bottom());
+
+ p.drawLine( R1.left() + R1.width(), R1.top(),
+ R2.right(), R1.bottom() );
+ }
+
+ // Drawing Golden spiral sections.
+ if (d->drawGoldenSpiralSection)
+ {
+ p.drawLine( R1.topRight(), R1.bottomRight() );
+ p.drawLine( R2.topLeft(), R2.topRight() );
+ p.drawLine( R3.topLeft(), R3.bottomLeft() );
+ p.drawLine( R4.bottomLeft(), R4.bottomRight() );
+ p.drawLine( R5.topRight(), R5.bottomRight() );
+ p.drawLine( R6.topLeft(), R6.topRight() );
+ p.drawLine( R7.topLeft(), R7.bottomLeft() );
+ }
+
+ // Drawing Golden Spiral.
+ if (d->drawGoldenSpiral)
+ {
+ p.drawArc ( R1.left(),
+ R1.top() - R1.height(),
+ 2*R1.width(), 2*R1.height(),
+ 180*16, 90*16);
+
+ p.drawArc ( R2.right() - 2*R2.width(),
+ R1.bottom() - 2*R2.height(),
+ 2*R2.width(), 2*R2.height(),
+ 270*16, 90*16);
+
+ p.drawArc ( R2.right() - 2*R3.width(),
+ R3.top(),
+ 2*R3.width(), 2*R3.height(),
+ 0, 90*16);
+
+ p.drawArc ( R4.left(),
+ R4.top(),
+ 2*R4.width(), 2*R4.height(),
+ 90*16, 90*16);
+
+ p.drawArc ( R5.left(),
+ R5.top()-R5.height(),
+ 2*R5.width(), 2*R5.height(),
+ 180*16, 90*16);
+
+ p.drawArc ( R6.left()-R6.width(),
+ R6.top()-R6.height(),
+ 2*R6.width(), 2*R6.height(),
+ 270*16, 90*16);
+
+ p.drawArc ( R7.left()-R7.width(),
+ R7.top(),
+ 2*R7.width(), 2*R7.height(),
+ 0, 90*16);
+ }
+
+ break;
+ }
+ }
+
+ p.setClipping(false);
+
+ p.end();
+}
+
+void ImageSelectionWidget::paintEvent( TQPaintEvent * )
+{
+ bitBlt(this, 0, 0, d->pixmap);
+}
+
+TQPoint ImageSelectionWidget::opposite()
+{
+ TQPoint opp;
+
+ switch(d->currentResizing)
+ {
+ case ImageSelectionWidgetPriv::ResizingTopRight:
+ opp = d->regionSelection.bottomLeft();
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingBottomLeft:
+ opp = d->regionSelection.topRight();
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingBottomRight:
+ opp = d->regionSelection.topLeft();
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingTopLeft:
+ default:
+ opp = d->regionSelection.bottomRight();
+ break;
+ }
+
+ return opp;
+}
+
+float ImageSelectionWidget::distance(TQPoint a, TQPoint b)
+{
+ return sqrt(pow(a.x() - b.x(), 2) + pow(a.y() - b.y(), 2));
+}
+
+void ImageSelectionWidget::setCursorResizing()
+{
+ switch(d->currentResizing)
+ {
+ case ImageSelectionWidgetPriv::ResizingTopLeft:
+ setCursor( KCursor::sizeFDiagCursor() );
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingTopRight:
+ setCursor( KCursor::sizeBDiagCursor() );
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingBottomLeft:
+ setCursor( KCursor::sizeBDiagCursor() );
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingBottomRight:
+ setCursor( KCursor::sizeFDiagCursor() );
+ break;
+ }
+}
+
+void ImageSelectionWidget::placeSelection(TQPoint pm, bool symmetric, TQPoint center)
+{
+ // Set orientation
+ if ( d->autoOrientation )
+ {
+ TQPoint rel = pm - opposite();
+
+ if ( abs(rel.x()) > abs(rel.y()) )
+ {
+ if ( d->currentOrientation == Portrait )
+ {
+ d->currentOrientation = Landscape;
+ reverseRatioValues();
+ emit signalSelectionOrientationChanged( d->currentOrientation );
+ }
+ }
+ else
+ {
+ if ( d->currentOrientation == Landscape )
+ {
+ d->currentOrientation = Portrait;
+ reverseRatioValues();
+ emit signalSelectionOrientationChanged( d->currentOrientation );
+ }
+ }
+ }
+
+ // Place the corner at the mouse
+ // If a symmetric selection is wanted, place opposite corner to
+ // the center, double selection size and move it to old center after
+ // computing aspect ratio.
+ switch(d->currentResizing)
+ {
+ case ImageSelectionWidgetPriv::ResizingTopLeft:
+ // Place corners to the proper position
+ d->regionSelection.setTopLeft(pm);
+ if ( symmetric )
+ d->regionSelection.setBottomRight(center);
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingTopRight:
+ d->regionSelection.setTopRight(pm);
+ if ( symmetric )
+ d->regionSelection.setBottomLeft(center);
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingBottomLeft:
+ d->regionSelection.setBottomLeft(pm);
+ if ( symmetric )
+ d->regionSelection.setTopRight(center);
+ break;
+
+ case ImageSelectionWidgetPriv::ResizingBottomRight:
+ d->regionSelection.setBottomRight(pm);
+ if ( symmetric )
+ d->regionSelection.setTopLeft(center);
+ break;
+ }
+
+ if ( symmetric )
+ d->regionSelection.setSize(d->regionSelection.size()*2);
+ applyAspectRatio(d->currentOrientation == Portrait, false);
+ if ( symmetric )
+ d->regionSelection.moveCenter(center);
+
+ // Repaint
+ updatePixmap();
+ repaint(false);
+}
+
+void ImageSelectionWidget::mousePressEvent ( TQMouseEvent * e )
+{
+ if ( e->button() == TQt::LeftButton )
+ {
+ TQPoint pm = TQPoint(e->x(), e->y());
+ TQPoint pmVirtual = convertPoint(pm);
+ d->moving = false;
+
+ if ( (e->state() & TQt::ShiftButton) == TQt::ShiftButton )
+ {
+ bool symmetric = (e->state() & TQt::ControlButton ) == TQt::ControlButton;
+ TQPoint center = d->regionSelection.center();
+
+ // Find the closest corner
+
+ TQPoint points[] = { d->regionSelection.topLeft(),
+ d->regionSelection.topRight(),
+ d->regionSelection.bottomLeft(),
+ d->regionSelection.bottomRight() };
+ int resizings[] = { ImageSelectionWidgetPriv::ResizingTopLeft,
+ ImageSelectionWidgetPriv::ResizingTopRight,
+ ImageSelectionWidgetPriv::ResizingBottomLeft,
+ ImageSelectionWidgetPriv::ResizingBottomRight };
+ float dist = -1;
+ for (int i = 0 ; i < 4 ; i++)
+ {
+ TQPoint point = points[i];
+ float dist2 = distance(pmVirtual, point);
+ if (dist2 < dist || d->currentResizing == ImageSelectionWidgetPriv::ResizingNone)
+ {
+ dist = dist2;
+ d->currentResizing = resizings[i];
+ }
+ }
+
+ setCursorResizing();
+
+ placeSelection(pmVirtual, symmetric, center);
+ }
+ else
+ {
+ if ( d->localTopLeftCorner.contains( pm ) )
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingTopLeft;
+ else if ( d->localTopRightCorner.contains( pm ) )
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingTopRight;
+ else if ( d->localBottomLeftCorner.contains( pm ) )
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingBottomLeft;
+ else if ( d->localBottomRightCorner.contains( pm ) )
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingBottomRight;
+ else
+ {
+ d->lastPos = pmVirtual;
+ setCursor( KCursor::sizeAllCursor() );
+
+ if (d->regionSelection.contains( pmVirtual ) )
+ {
+ d->moving = true;
+ }
+ else
+ {
+ d->regionSelection.moveCenter( pmVirtual );
+ normalizeRegion();
+ updatePixmap();
+ repaint(false);
+ }
+ }
+ }
+ }
+}
+
+void ImageSelectionWidget::mouseReleaseEvent ( TQMouseEvent * )
+{
+ if ( d->currentResizing != ImageSelectionWidgetPriv::ResizingNone )
+ {
+ setCursor( KCursor::arrowCursor() );
+ regionSelectionChanged();
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingNone;
+ }
+ else if ( d->regionSelection.contains( d->lastPos ) )
+ {
+ setCursor( KCursor::handCursor() );
+ regionSelectionMoved();
+ }
+ else
+ {
+ setCursor( KCursor::arrowCursor() );
+ regionSelectionMoved();
+ }
+}
+
+void ImageSelectionWidget::mouseMoveEvent ( TQMouseEvent * e )
+{
+ if ( ( e->state() & TQt::LeftButton ) == TQt::LeftButton )
+ {
+ if ( d->moving )
+ {
+ setCursor( KCursor::sizeAllCursor() );
+ TQPoint newPos = convertPoint(e->x(), e->y());
+
+ d->regionSelection.moveBy( newPos.x() - d->lastPos.x(),
+ newPos.y() - d->lastPos.y() );
+
+ d->lastPos = newPos;
+
+ normalizeRegion();
+
+ updatePixmap();
+ repaint(false);
+ }
+ else
+ {
+ TQPoint pmVirtual = convertPoint(e->x(), e->y());
+
+ if ( d->currentResizing == ImageSelectionWidgetPriv::ResizingNone )
+ {
+ d->regionSelection.setTopLeft( pmVirtual );
+ d->regionSelection.setBottomRight( pmVirtual );
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingTopLeft; // set to anything
+ }
+
+ TQPoint center = d->regionSelection.center();
+ bool symmetric = (e->state() & TQt::ControlButton ) == TQt::ControlButton;
+
+ // Change resizing mode
+
+ TQPoint opp = symmetric ? center : opposite();
+ TQPoint dir = pmVirtual - opp;
+
+ if ( dir.x() > 0 && dir.y() > 0 && d->currentResizing != ImageSelectionWidgetPriv::ResizingBottomRight)
+ {
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingBottomRight;
+ d->regionSelection.setTopLeft( opp );
+ setCursor( KCursor::sizeFDiagCursor() );
+ }
+ else if ( dir.x() > 0 && dir.y() < 0 && d->currentResizing != ImageSelectionWidgetPriv::ResizingTopRight)
+ {
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingTopRight;
+ d->regionSelection.setBottomLeft( opp );
+ setCursor( KCursor::sizeBDiagCursor() );
+ }
+ else if ( dir.x() < 0 && dir.y() > 0 && d->currentResizing != ImageSelectionWidgetPriv::ResizingBottomLeft)
+ {
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingBottomLeft;
+ d->regionSelection.setTopRight( opp );
+ setCursor( KCursor::sizeBDiagCursor() );
+ }
+ else if ( dir.x() < 0 && dir.y() < 0 && d->currentResizing != ImageSelectionWidgetPriv::ResizingTopLeft)
+ {
+ d->currentResizing = ImageSelectionWidgetPriv::ResizingTopLeft;
+ d->regionSelection.setBottomRight( opp );
+ setCursor( KCursor::sizeFDiagCursor() );
+ }
+ else
+ {
+ if ( dir.x() == 0 && dir.y() == 0 )
+ setCursor( KCursor::sizeAllCursor() );
+ else if ( dir.x() == 0 )
+ setCursor( KCursor::sizeHorCursor() );
+ else if ( dir.y() == 0 )
+ setCursor( KCursor::sizeVerCursor() );
+ }
+
+ placeSelection(pmVirtual, symmetric, center);
+ }
+ }
+ else
+ {
+ if ( d->localTopLeftCorner.contains( e->x(), e->y() ) ||
+ d->localBottomRightCorner.contains( e->x(), e->y() ) )
+ setCursor( KCursor::sizeFDiagCursor() );
+ else if ( d->localTopRightCorner.contains( e->x(), e->y() ) ||
+ d->localBottomLeftCorner.contains( e->x(), e->y() ) )
+ setCursor( KCursor::sizeBDiagCursor() );
+ else if ( d->localRegionSelection.contains( e->x(), e->y() ) )
+ setCursor( KCursor::handCursor() );
+ else
+ setCursor( KCursor::arrowCursor() );
+ }
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/ratiocrop/imageselectionwidget.h b/src/imageplugins/coreplugin/ratiocrop/imageselectionwidget.h
new file mode 100644
index 00000000..0d2bd4fd
--- /dev/null
+++ b/src/imageplugins/coreplugin/ratiocrop/imageselectionwidget.h
@@ -0,0 +1,176 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-09
+ * Description : image selection widget used by ratio crop tool.
+ *
+ * Copyright (C) 2007 by Jaromir Malenko <malenko at email.cz>
+ * Copyright (C) 2008 by Roberto Castagnola <roberto dot castagnola at gmail dot com>
+ * Copyright (C) 2004-2009 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGESELECTIONWIDGET_H
+#define IMAGESELECTIONWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqrect.h>
+#include <tqcolor.h>
+
+namespace Digikam
+{
+class ImageIface;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageSelectionWidgetPriv;
+
+class ImageSelectionWidget : public TQWidget
+{
+
+TQ_OBJECT
+
+
+public:
+
+ enum RatioAspect // Constrained Aspect Ratio list.
+ {
+ RATIOCUSTOM=0, // Custom aspect ratio.
+ RATIO01X01, // 1:1
+ RATIO02x03, // 2:3
+ RATIO03X04, // 3:4
+ RATIO04X05, // 4:5
+ RATIO05x07, // 5:7
+ RATIO07x10, // 7:10
+ RATIOGOLDEN, // Golden ratio : 1:1.618
+ RATIONONE // No aspect ratio.
+ };
+
+ enum Orient
+ {
+ Landscape = 0,
+ Portrait
+ };
+
+ enum CenterType
+ {
+ CenterWidth = 0, // Center selection to the center of image width.
+ CenterHeight, // Center selection to the center of image height.
+ CenterImage // Center selection to the center of image.
+ };
+
+ // Proportion : Golden Ratio and Rule of Thirds. More information at this url:
+ // http://photoinf.com/General/Robert_Berdan/Composition_and_the_Elements_of_Visual_Design.htm
+
+ enum GuideLineType
+ {
+ RulesOfThirds = 0, // Line guides position to 1/3 width and height.
+ DiagonalMethod, // Diagonal Method to improve composition.
+ HarmoniousTriangles, // Harmonious Triangle to improve composition.
+ GoldenMean, // Guides tools using Phi ratio (1.618).
+ GuideNone // No guide line.
+ };
+
+public:
+
+ ImageSelectionWidget(int width, int height, TQWidget *parent=0,
+ int widthRatioValue=1, int heightRatioValue=1,
+ int aspectRatio=RATIO01X01, int orient=Landscape,
+ int guideLinesType=GuideNone);
+ ~ImageSelectionWidget();
+
+ void setCenterSelection(int centerType=CenterImage);
+ void setSelectionX(int x);
+ void setSelectionY(int y);
+ void setSelectionWidth(int w);
+ void setSelectionHeight(int h);
+ void setSelectionOrientation(int orient);
+ void setPreciseCrop(bool precise);
+ void setAutoOrientation(bool orientation);
+ void setSelectionAspectRatioType(int aspectRatioType);
+ void setSelectionAspectRatioValue(int widthRatioValue, int heightRatioValue);
+ void setGoldenGuideTypes(bool drawGoldenSection, bool drawGoldenSpiralSection,
+ bool drawGoldenSpiral, bool drawGoldenTriangle,
+ bool flipHorGoldenGuide, bool flipVerGoldenGuide);
+
+ int getOriginalImageWidth();
+ int getOriginalImageHeight();
+ TQRect getRegionSelection();
+
+ int getMinWidthRange();
+ int getMinHeightRange();
+ int getMaxWidthRange();
+ int getMaxHeightRange();
+ int getWidthStep();
+ int getHeightStep();
+
+ bool preciseCropAvailable();
+
+ void resetSelection();
+ void maxAspectSelection();
+
+ Digikam::ImageIface* imageIface();
+
+public slots:
+
+ void slotGuideLines(int guideLinesType);
+ void slotChangeGuideColor(const TQColor &color);
+ void slotChangeGuideSize(int size);
+
+signals:
+
+ void signalSelectionMoved( TQRect rect );
+ void signalSelectionChanged( TQRect rect );
+ void signalSelectionOrientationChanged( int newOrientation );
+
+protected:
+
+ void paintEvent( TQPaintEvent *e );
+ void mousePressEvent ( TQMouseEvent * e );
+ void mouseReleaseEvent ( TQMouseEvent * e );
+ void mouseMoveEvent ( TQMouseEvent * e );
+ void resizeEvent(TQResizeEvent * e);
+
+private:
+
+ // Recalculate the target selection position and emit 'signalSelectionMoved'.
+ void regionSelectionMoved();
+
+ void regionSelectionChanged();
+ TQPoint convertPoint(const TQPoint pm, bool localToReal=true);
+ TQPoint convertPoint(int x, int y, bool localToReal=true);
+ void normalizeRegion();
+ void reverseRatioValues();
+ int computePreciseSize(int size, int step);
+ void applyAspectRatio(bool useHeight, bool repaintWidget=true);
+ void updatePixmap();
+ TQPoint opposite();
+ float distance(TQPoint a, TQPoint b);
+ void placeSelection(TQPoint pm, bool symetric, TQPoint center);
+ void setCursorResizing();
+
+private:
+
+ ImageSelectionWidgetPriv* d;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGESELECTIONWIDGET_H */
diff --git a/src/imageplugins/coreplugin/ratiocrop/ratiocroptool.cpp b/src/imageplugins/coreplugin/ratiocrop/ratiocroptool.cpp
new file mode 100644
index 00000000..ed0e670e
--- /dev/null
+++ b/src/imageplugins/coreplugin/ratiocrop/ratiocroptool.cpp
@@ -0,0 +1,853 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-06
+ * Description : digiKam image editor Ratio Crop tool
+ *
+ * Copyright (C) 2007 by Jaromir Malenko <malenko at email dot cz>
+ * Copyright (C) 2008 by Roberto Castagnola <roberto dot castagnola at gmail dot com>
+ * Copyright (C) 2004-2009 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqframe.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqrect.h>
+#include <tqspinbox.h>
+#include <tqtimer.h>
+#include <tqtoolbutton.h>
+#include <tqtooltip.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <kcolorbutton.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kpushbutton.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Digikam includes.
+
+#include "editortoolsettings.h"
+#include "imageiface.h"
+#include "imageselectionwidget.h"
+
+// Local includes.
+
+#include "ratiocroptool.h"
+#include "ratiocroptool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+RatioCropTool::RatioCropTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("aspectratiocrop");
+ setToolName(i18n("Aspect Ratio Crop"));
+ setToolIcon(SmallIcon("ratiocrop"));
+ setToolHelp("ratiocroptool.anchor");
+
+ // -------------------------------------------------------------
+
+ m_imageSelectionWidget = new ImageSelectionWidget(480, 320);
+ TQWhatsThis::add(m_imageSelectionWidget,
+ i18n("<p>Here you can see the aspect ratio selection preview "
+ "used for cropping. You can use the mouse to move and "
+ "resize the crop area. "
+ "Press and hold the CTRL key to move the opposite corner too. "
+ "Press and hold the SHIFT key to move the closest corner to the "
+ "mouse pointer."));
+
+ m_originalIsLandscape = ((m_imageSelectionWidget->getOriginalImageWidth()) >
+ (m_imageSelectionWidget->getOriginalImageHeight()));
+
+ setToolView(m_imageSelectionWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Try|
+ EditorToolSettings::Cancel);
+
+ // -------------------------------------------------------------
+
+ // need to set the button to a KStdGuiItem that has no icon
+ m_gboxSettings->button(EditorToolSettings::Try)->setGuiItem(KStdGuiItem::Test);
+ // now we can set the correct text for the button
+ m_gboxSettings->button(EditorToolSettings::Try)->setText(i18n("Max. Aspect"));
+
+ TQToolTip::add(m_gboxSettings->button(EditorToolSettings::Try),
+ i18n("<p>Set selection area to the maximum size according "
+ "to the current ratio."));
+
+ // -------------------------------------------------------------
+
+ TQGridLayout *gboxLayout = new TQGridLayout(m_gboxSettings->plainPage(), 3, 2);
+
+ TQFrame *cropSelection = new TQFrame(m_gboxSettings->plainPage());
+ cropSelection->setFrameStyle(TQFrame::Panel | TQFrame::Sunken);
+
+ TQGridLayout* grid = new TQGridLayout(cropSelection, 7, 5);
+
+ TQLabel *label = new TQLabel(i18n("Ratio:"), cropSelection);
+ m_ratioCB = new RComboBox(cropSelection);
+ m_ratioCB->setDefaultItem(ImageSelectionWidget::RATIO03X04);
+ setRatioCBText(ImageSelectionWidget::Landscape);
+ TQWhatsThis::add( m_ratioCB, i18n("<p>Select your constrained aspect ratio for cropping. "
+ "Aspect Ratio Crop tool uses a relative ratio. That means it "
+ "is the same if you use centimeters or inches and it doesn't "
+ "specify the physical size.<p>"
+ "You can see below a correspondence list of traditional photographic "
+ "paper sizes and aspect ratio crop:<p>"
+ "<b>2:3</b>: 10x15cm, 20x30cm, 30x45cm, 4x6\", 8x12\", "
+ "12x18\", 16x24\", 20x30\"<p>"
+ "<b>3:4</b>: 6x8cm, 15x20cm, 18x24cm, 30x40cm, 3.75x5\", 4.5x6\", "
+ "6x8\", 7.5x10\", 9x12\"<p>"
+ "<b>4:5</b>: 20x25cm, 40x50cm, 8x10\", 16x20\"<p>"
+ "<b>5:7</b>: 15x21cm, 30x42cm, 5x7\"<p>"
+ "<b>7:10</b>: 21x30cm, 42x60cm, 3.5x5\"<p>"
+ "The <b>Golden Ratio</b> is 1:1.618. A composition following this rule "
+ "is considered visually harmonious but can be unadapted to print on "
+ "standard photographic paper."));
+
+ m_preciseCrop = new TQCheckBox(i18n("Exact"), cropSelection);
+ TQWhatsThis::add( m_preciseCrop, i18n("<p>Enable this option to force exact aspect ratio crop."));
+
+ m_orientLabel = new TQLabel(i18n("Orientation:"), cropSelection);
+ m_orientCB = new RComboBox(cropSelection);
+ m_orientCB->insertItem( i18n("Landscape"));
+ m_orientCB->insertItem( i18n("Portrait"));
+ m_orientCB->setDefaultItem(ImageSelectionWidget::Landscape);
+ TQWhatsThis::add( m_orientCB, i18n("<p>Select constrained aspect ratio orientation."));
+
+ m_autoOrientation = new TQCheckBox(i18n("Auto"), cropSelection);
+ TQWhatsThis::add( m_autoOrientation, i18n("<p>Enable this option to automatically set the orientation."));
+
+ // -------------------------------------------------------------
+
+ m_customLabel1 = new TQLabel(i18n("Custom:"), cropSelection);
+ m_customLabel1->setAlignment(AlignLeft|AlignVCenter);
+ m_customRatioNInput = new RIntNumInput(cropSelection);
+ m_customRatioNInput->input()->setRange(1, 10000, 1, false);
+ m_customRatioNInput->setDefaultValue(1);
+ TQWhatsThis::add( m_customRatioNInput, i18n("<p>Set here the desired custom aspect numerator value."));
+
+ m_customLabel2 = new TQLabel(" : ", cropSelection);
+ m_customLabel2->setAlignment(AlignCenter|AlignVCenter);
+ m_customRatioDInput = new RIntNumInput(cropSelection);
+ m_customRatioDInput->input()->setRange(1, 10000, 1, false);
+ m_customRatioDInput->setDefaultValue(1);
+ TQWhatsThis::add( m_customRatioDInput, i18n("<p>Set here the desired custom aspect denominator value."));
+
+ // -------------------------------------------------------------
+
+ m_xInput = new RIntNumInput(cropSelection);
+ m_xInput->input()->setLabel(i18n("X:"), AlignLeft|AlignVCenter);
+ m_xInput->setRange(0, m_imageSelectionWidget->getOriginalImageWidth(), 1);
+ m_xInput->setDefaultValue(50);
+ TQWhatsThis::add( m_xInput, i18n("<p>Set here the top left selection corner position for cropping."));
+
+ m_widthInput = new RIntNumInput(cropSelection);
+ m_widthInput->input()->setLabel(i18n("Width:"), AlignLeft|AlignVCenter);
+ m_widthInput->setRange(m_imageSelectionWidget->getMinWidthRange(),
+ m_imageSelectionWidget->getMaxWidthRange(),
+ m_imageSelectionWidget->getWidthStep());
+ m_widthInput->setDefaultValue(800);
+ TQWhatsThis::add( m_widthInput, i18n("<p>Set here the width selection for cropping."));
+
+ m_centerWidth = new TQToolButton(cropSelection);
+ TDEGlobal::dirs()->addResourceType("centerwidth", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("centerwidth", "centerwidth.png");
+ m_centerWidth->setPixmap(TQPixmap(directory + "centerwidth.png"));
+ TQWhatsThis::add(m_centerWidth, i18n("<p>Set width position to center."));
+
+ // -------------------------------------------------------------
+
+ m_yInput = new RIntNumInput(cropSelection);
+ m_yInput->input()->setLabel(i18n("Y:"), AlignLeft | AlignVCenter);
+ m_yInput->setRange(0, m_imageSelectionWidget->getOriginalImageHeight(), 1);
+ m_yInput->setDefaultValue(50);
+ TQWhatsThis::add(m_yInput, i18n("<p>Set here the top left selection corner position for cropping."));
+
+ m_heightInput = new RIntNumInput(cropSelection);
+ m_heightInput->input()->setLabel(i18n("Height:"), AlignLeft | AlignVCenter);
+ m_heightInput->setRange(m_imageSelectionWidget->getMinHeightRange(),
+ m_imageSelectionWidget->getMaxHeightRange(),
+ m_imageSelectionWidget->getHeightStep());
+ m_heightInput->setDefaultValue(600);
+ TQWhatsThis::add( m_heightInput, i18n("<p>Set here the height selection for cropping."));
+
+ m_centerHeight = new TQToolButton(cropSelection);
+ TDEGlobal::dirs()->addResourceType("centerheight", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("centerheight", "centerheight.png");
+ m_centerHeight->setPixmap(TQPixmap(directory + "centerheight.png"));
+ TQWhatsThis::add(m_centerHeight, i18n("<p>Set height position to center."));
+
+ grid->addMultiCellWidget(label, 0, 0, 0, 0);
+ grid->addMultiCellWidget(m_ratioCB, 0, 0, 1, 3);
+ grid->addMultiCellWidget(m_preciseCrop, 0, 0, 4, 4);
+ grid->addMultiCellWidget(m_customLabel1, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_customRatioNInput, 1, 1, 1, 1);
+ grid->addMultiCellWidget(m_customLabel2, 1, 1, 2, 2);
+ grid->addMultiCellWidget(m_customRatioDInput, 1, 1, 3, 3);
+ grid->addMultiCellWidget(m_orientLabel, 2, 2, 0, 0);
+ grid->addMultiCellWidget(m_orientCB, 2, 2, 1, 3);
+ grid->addMultiCellWidget(m_autoOrientation, 2, 2, 4, 4);
+ grid->addMultiCellWidget(m_xInput, 3, 3, 0, 3);
+ grid->addMultiCellWidget(m_widthInput, 4, 4, 0, 3);
+ grid->addMultiCellWidget(m_centerWidth, 4, 4, 4, 4);
+ grid->addMultiCellWidget(m_yInput, 5, 5, 0, 3);
+ grid->addMultiCellWidget(m_heightInput, 6, 6, 0, 3);
+ grid->addMultiCellWidget(m_centerHeight, 6, 6, 4, 4);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ // -------------------------------------------------------------
+
+ TQFrame* compositionGuide = new TQFrame(m_gboxSettings->plainPage());
+ TQGridLayout* grid2 = new TQGridLayout(compositionGuide, 8, 3);
+ compositionGuide->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+
+ TQLabel *labelGuideLines = new TQLabel(i18n("Composition guide:"), compositionGuide);
+ m_guideLinesCB = new RComboBox(compositionGuide);
+ m_guideLinesCB->insertItem( i18n("Rules of Thirds"));
+ m_guideLinesCB->insertItem( i18n("Diagonal Method"));
+ m_guideLinesCB->insertItem( i18n("Harmonious Triangles"));
+ m_guideLinesCB->insertItem( i18n("Golden Mean"));
+ m_guideLinesCB->insertItem( i18n("None"));
+ m_guideLinesCB->setDefaultItem(ImageSelectionWidget::GuideNone);
+ TQWhatsThis::add( m_guideLinesCB, i18n("<p>With this option, you can display guide lines "
+ "which help you to compose your photograph."));
+
+ m_goldenSectionBox = new TQCheckBox(i18n("Golden sections"), compositionGuide);
+ TQWhatsThis::add( m_goldenSectionBox, i18n("<p>Enable this option to show golden sections."));
+
+ m_goldenSpiralSectionBox = new TQCheckBox(i18n("Golden spiral sections"), compositionGuide);
+ TQWhatsThis::add( m_goldenSpiralSectionBox, i18n("<p>Enable this option to show golden spiral sections."));
+
+ m_goldenSpiralBox = new TQCheckBox(i18n("Golden spiral"), compositionGuide);
+ TQWhatsThis::add( m_goldenSpiralBox, i18n("<p>Enable this option to show golden spiral guide."));
+
+ m_goldenTriangleBox = new TQCheckBox(i18n("Golden triangles"), compositionGuide);
+ TQWhatsThis::add( m_goldenTriangleBox, i18n("<p>Enable this option to show golden triangles."));
+
+ m_flipHorBox = new TQCheckBox(i18n("Flip horizontally"), compositionGuide);
+ TQWhatsThis::add( m_flipHorBox, i18n("<p>Enable this option to flip horizontally guidelines."));
+
+ m_flipVerBox = new TQCheckBox(i18n("Flip vertically"), compositionGuide);
+ TQWhatsThis::add( m_flipVerBox, i18n("<p>Enable this option to flip vertically guidelines."));
+
+ m_colorGuideLabel = new TQLabel(i18n("Color and width:"), compositionGuide);
+ m_guideColorBt = new KColorButton(TQColor(250, 250, 255), compositionGuide);
+ m_guideSize = new RIntNumInput(compositionGuide);
+ m_guideSize->input()->setRange(1, 5, 1, false);
+ m_guideSize->setDefaultValue(1);
+ TQWhatsThis::add( m_guideColorBt, i18n("<p>Set here the color used to draw composition guides."));
+ TQWhatsThis::add( m_guideSize, i18n("<p>Set here the width in pixels used to draw composition guides."));
+
+ grid2->addMultiCellWidget(labelGuideLines, 0, 0, 0, 0);
+ grid2->addMultiCellWidget(m_guideLinesCB, 0, 0, 1, 2);
+ grid2->addMultiCellWidget(m_goldenSectionBox, 1, 1, 0, 2);
+ grid2->addMultiCellWidget(m_goldenSpiralSectionBox, 2, 2, 0, 2);
+ grid2->addMultiCellWidget(m_goldenSpiralBox, 3, 3, 0, 2);
+ grid2->addMultiCellWidget(m_goldenTriangleBox, 4, 4, 0, 2);
+ grid2->addMultiCellWidget(m_flipHorBox, 5, 5, 0, 2);
+ grid2->addMultiCellWidget(m_flipVerBox, 6, 6, 0, 2);
+ grid2->addMultiCellWidget(m_colorGuideLabel, 7, 7, 0, 0);
+ grid2->addMultiCellWidget(m_guideColorBt, 7, 7, 1, 1);
+ grid2->addMultiCellWidget(m_guideSize, 7, 7, 2, 2);
+ grid2->setMargin(m_gboxSettings->spacingHint());
+ grid2->setSpacing(m_gboxSettings->spacingHint());
+
+
+ // -------------------------------------------------------------
+
+ gboxLayout->addMultiCellWidget(cropSelection, 0, 0, 0, 1);
+ gboxLayout->addMultiCellWidget(compositionGuide, 1, 1, 0, 1);
+ gboxLayout->setRowStretch(2, 10);
+ gboxLayout->setMargin(m_gboxSettings->spacingHint());
+ gboxLayout->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_ratioCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotRatioChanged(int)));
+
+ connect(m_preciseCrop, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotPreciseCropChanged(bool)));
+
+ connect(m_orientCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotOrientChanged(int)));
+
+ connect(m_autoOrientation, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotAutoOrientChanged(bool)));
+
+ connect(m_xInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotXChanged(int)));
+
+ connect(m_yInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotYChanged(int)));
+
+ connect(m_customRatioNInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotCustomNRatioChanged(int)));
+
+ connect(m_customRatioDInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotCustomDRatioChanged(int)));
+
+ connect(m_guideLinesCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotGuideTypeChanged(int)));
+
+ connect(m_goldenSectionBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_goldenSpiralSectionBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_goldenSpiralBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_goldenTriangleBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_flipHorBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_flipVerBox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotGoldenGuideTypeChanged()));
+
+ connect(m_guideColorBt, TQ_SIGNAL(changed(const TQColor&)),
+ m_imageSelectionWidget, TQ_SLOT(slotChangeGuideColor(const TQColor&)));
+
+ connect(m_guideSize, TQ_SIGNAL(valueChanged(int)),
+ m_imageSelectionWidget, TQ_SLOT(slotChangeGuideSize(int)));
+
+ connect(m_widthInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotWidthChanged(int)));
+
+ connect(m_heightInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotHeightChanged(int)));
+
+ connect(m_imageSelectionWidget, TQ_SIGNAL(signalSelectionChanged(TQRect)),
+ this, TQ_SLOT(slotSelectionChanged(TQRect)));
+
+ connect(m_imageSelectionWidget, TQ_SIGNAL(signalSelectionMoved(TQRect)),
+ this, TQ_SLOT(slotSelectionChanged(TQRect)));
+
+ connect(m_imageSelectionWidget, TQ_SIGNAL(signalSelectionOrientationChanged(int)),
+ this, TQ_SLOT(slotSelectionOrientationChanged(int)));
+
+ connect(m_centerWidth, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotCenterWidth()));
+
+ connect(m_centerHeight, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotCenterHeight()));
+
+ // we need to disconnect the standard connection of the Try button first
+ disconnect(m_gboxSettings, TQ_SIGNAL(signalTryClicked()),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_gboxSettings, TQ_SIGNAL(signalTryClicked()),
+ this, TQ_SLOT(slotMaxAspectRatio()));
+
+ // -------------------------------------------------------------
+
+ // Sets current region selection
+ slotSelectionChanged(m_imageSelectionWidget->getRegionSelection());
+}
+
+RatioCropTool::~RatioCropTool()
+{
+}
+
+void RatioCropTool::readSettings()
+{
+ TQColor defaultGuideColor(250, 250, 255);
+ TDEConfig *config = kapp->config();
+ config->setGroup("aspectratiocrop Tool");
+
+ // No guide lines per default.
+ m_guideLinesCB->setCurrentItem(config->readNumEntry("Guide Lines Type", ImageSelectionWidget::GuideNone));
+ m_goldenSectionBox->setChecked(config->readBoolEntry("Golden Section", true));
+ m_goldenSpiralSectionBox->setChecked(config->readBoolEntry("Golden Spiral Section", false));
+ m_goldenSpiralBox->setChecked(config->readBoolEntry("Golden Spiral", false));
+ m_goldenTriangleBox->setChecked(config->readBoolEntry("Golden Triangle", false));
+ m_flipHorBox->setChecked(config->readBoolEntry("Golden Flip Horizontal", false));
+ m_flipVerBox->setChecked(config->readBoolEntry("Golden Flip Vertical", false));
+ m_guideColorBt->setColor(config->readColorEntry("Guide Color", &defaultGuideColor));
+ m_guideSize->setValue(config->readNumEntry("Guide Width", m_guideSize->defaultValue()));
+ m_imageSelectionWidget->slotGuideLines(m_guideLinesCB->currentItem());
+ m_imageSelectionWidget->slotChangeGuideColor(m_guideColorBt->color());
+
+ m_preciseCrop->setChecked(config->readBoolEntry("Precise Aspect Ratio Crop", false));
+ m_imageSelectionWidget->setPreciseCrop(m_preciseCrop->isChecked());
+
+ // Empty selection so it can be moved w/out size constraint
+ m_widthInput->setValue(0);
+ m_heightInput->setValue(0);
+
+ m_xInput->setValue(config->readNumEntry("Hor.Oriented Custom Aspect Ratio Xpos",
+ m_xInput->defaultValue()));
+ m_yInput->setValue(config->readNumEntry("Hor.Oriented Custom Aspect Ratio Ypos",
+ m_yInput->defaultValue()));
+
+ m_widthInput->setValue(config->readNumEntry("Hor.Oriented Custom Aspect Ratio Width",
+ m_widthInput->defaultValue()));
+ m_heightInput->setValue(config->readNumEntry("Hor.Oriented Custom Aspect Ratio Height",
+ m_heightInput->defaultValue()));
+
+ m_imageSelectionWidget->setSelectionOrientation(m_orientCB->currentItem());
+
+ m_customRatioNInput->setValue(config->readNumEntry("Hor.Oriented Custom Aspect Ratio Num",
+ m_customRatioNInput->defaultValue()));
+ m_customRatioDInput->setValue(config->readNumEntry("Hor.Oriented Custom Aspect Ratio Den",
+ m_customRatioDInput->defaultValue()));
+
+ m_ratioCB->setCurrentItem(config->readNumEntry("Hor.Oriented Aspect Ratio",
+ m_ratioCB->defaultItem()));
+
+ if (m_originalIsLandscape)
+ {
+ m_orientCB->setCurrentItem(config->readNumEntry("Hor.Oriented Aspect Ratio Orientation",
+ ImageSelectionWidget::Landscape));
+ m_orientCB->setDefaultItem(ImageSelectionWidget::Landscape);
+ }
+ else
+ {
+ m_orientCB->setCurrentItem(config->readNumEntry("Ver.Oriented Aspect Ratio Orientation",
+ ImageSelectionWidget::Portrait));
+ m_orientCB->setDefaultItem(ImageSelectionWidget::Portrait);
+ }
+
+ applyRatioChanges(m_ratioCB->currentItem());
+
+ m_autoOrientation->setChecked( config->readBoolEntry("Auto Orientation", false) );
+ slotAutoOrientChanged( m_autoOrientation->isChecked() );
+}
+
+void RatioCropTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("aspectratiocrop Tool");
+
+ if (m_originalIsLandscape)
+ {
+ config->writeEntry("Hor.Oriented Aspect Ratio", m_ratioCB->currentItem());
+ config->writeEntry("Hor.Oriented Aspect Ratio Orientation", m_orientCB->currentItem());
+ config->writeEntry("Hor.Oriented Custom Aspect Ratio Num", m_customRatioNInput->value());
+ config->writeEntry("Hor.Oriented Custom Aspect Ratio Den", m_customRatioDInput->value());
+
+ config->writeEntry("Hor.Oriented Custom Aspect Ratio Xpos", m_xInput->value());
+ config->writeEntry("Hor.Oriented Custom Aspect Ratio Ypos", m_yInput->value());
+ config->writeEntry("Hor.Oriented Custom Aspect Ratio Width", m_widthInput->value());
+ config->writeEntry("Hor.Oriented Custom Aspect Ratio Height", m_heightInput->value());
+ }
+ else
+ {
+ config->writeEntry("Ver.Oriented Aspect Ratio", m_ratioCB->currentItem());
+ config->writeEntry("Ver.Oriented Aspect Ratio Orientation", m_orientCB->currentItem());
+ config->writeEntry("Ver.Oriented Custom Aspect Ratio Num", m_customRatioNInput->value());
+ config->writeEntry("Ver.Oriented Custom Aspect Ratio Den", m_customRatioDInput->value());
+
+ config->writeEntry("Ver.Oriented Custom Aspect Ratio Xpos", m_xInput->value());
+ config->writeEntry("Ver.Oriented Custom Aspect Ratio Ypos", m_yInput->value());
+ config->writeEntry("Ver.Oriented Custom Aspect Ratio Width", m_widthInput->value());
+ config->writeEntry("Ver.Oriented Custom Aspect Ratio Height", m_heightInput->value());
+ }
+
+ config->writeEntry("Precise Aspect Ratio Crop", m_preciseCrop->isChecked());
+ config->writeEntry("Auto Orientation", m_autoOrientation->isChecked());
+ config->writeEntry("Guide Lines Type", m_guideLinesCB->currentItem());
+ config->writeEntry("Golden Section", m_goldenSectionBox->isChecked());
+ config->writeEntry("Golden Spiral Section", m_goldenSpiralSectionBox->isChecked());
+ config->writeEntry("Golden Spiral", m_goldenSpiralBox->isChecked());
+ config->writeEntry("Golden Triangle", m_goldenTriangleBox->isChecked());
+ config->writeEntry("Golden Flip Horizontal", m_flipHorBox->isChecked());
+ config->writeEntry("Golden Flip Vertical", m_flipVerBox->isChecked());
+ config->writeEntry("Guide Color", m_guideColorBt->color());
+ config->writeEntry("Guide Width", m_guideSize->value());
+ config->sync();
+}
+
+void RatioCropTool::slotResetSettings()
+{
+ m_imageSelectionWidget->resetSelection();
+}
+
+void RatioCropTool::slotMaxAspectRatio()
+{
+ m_imageSelectionWidget->maxAspectSelection();
+}
+
+void RatioCropTool::slotCenterWidth()
+{
+ m_imageSelectionWidget->setCenterSelection(ImageSelectionWidget::CenterWidth);
+}
+
+void RatioCropTool::slotCenterHeight()
+{
+ m_imageSelectionWidget->setCenterSelection(ImageSelectionWidget::CenterHeight);
+}
+
+void RatioCropTool::slotSelectionChanged(TQRect rect)
+{
+ m_xInput->blockSignals(true);
+ m_yInput->blockSignals(true);
+ m_widthInput->blockSignals(true);
+ m_heightInput->blockSignals(true);
+
+ m_xInput->setRange(0, m_imageSelectionWidget->getOriginalImageWidth() - rect.width(), 1);
+ m_yInput->setRange(0, m_imageSelectionWidget->getOriginalImageHeight() - rect.height(), 1);
+
+ m_widthInput->setRange(m_imageSelectionWidget->getMinWidthRange(),
+ m_imageSelectionWidget->getMaxWidthRange(),
+ m_imageSelectionWidget->getWidthStep());
+
+ m_heightInput->setRange(m_imageSelectionWidget->getMinHeightRange(),
+ m_imageSelectionWidget->getMaxHeightRange(),
+ m_imageSelectionWidget->getHeightStep());
+
+ m_xInput->setValue(rect.x());
+ m_yInput->setValue(rect.y());
+ m_widthInput->setValue(rect.width());
+ m_heightInput->setValue(rect.height());
+
+ m_gboxSettings->enableButton(EditorToolSettings::Ok, rect.isValid());
+ m_preciseCrop->setEnabled(m_imageSelectionWidget->preciseCropAvailable());
+
+ m_xInput->blockSignals(false);
+ m_yInput->blockSignals(false);
+ m_widthInput->blockSignals(false);
+ m_heightInput->blockSignals(false);
+}
+
+void RatioCropTool::setRatioCBText(int orientation)
+{
+ int item = m_ratioCB->currentItem();
+
+ m_ratioCB->blockSignals(true);
+ m_ratioCB->combo()->clear();
+ m_ratioCB->insertItem(i18n("Custom"));
+ m_ratioCB->insertItem("1:1");
+ if (orientation == ImageSelectionWidget::Landscape)
+ {
+ m_ratioCB->insertItem("3:2");
+ m_ratioCB->insertItem("4:3");
+ m_ratioCB->insertItem("5:4");
+ m_ratioCB->insertItem("7:5");
+ m_ratioCB->insertItem("10:7");
+ }
+ else
+ {
+ m_ratioCB->insertItem("2:3");
+ m_ratioCB->insertItem("3:4");
+ m_ratioCB->insertItem("4:5");
+ m_ratioCB->insertItem("5:7");
+ m_ratioCB->insertItem("7:10");
+ }
+ m_ratioCB->insertItem(i18n("Golden Ratio"));
+ m_ratioCB->insertItem(i18n("None"));
+ m_ratioCB->setCurrentItem(item);
+ m_ratioCB->blockSignals(false);
+}
+
+void RatioCropTool::slotSelectionOrientationChanged(int newOrientation)
+{
+ // Change text for Aspect ratio ComboBox
+
+ setRatioCBText(newOrientation);
+
+ // Change Orientation ComboBox
+
+ m_orientCB->setCurrentItem(newOrientation);
+
+ // Reverse custom values
+
+ if ( ( m_customRatioNInput->value() < m_customRatioDInput->value() &&
+ newOrientation == ImageSelectionWidget::Landscape) ||
+ ( m_customRatioNInput->value() > m_customRatioDInput->value() &&
+ newOrientation == ImageSelectionWidget::Portrait))
+ {
+ m_customRatioNInput->blockSignals(true);
+ m_customRatioDInput->blockSignals(true);
+
+ int tmp = m_customRatioNInput->value();
+ m_customRatioNInput->setValue(m_customRatioDInput->value());
+ m_customRatioDInput->setValue(tmp);
+
+ m_customRatioNInput->blockSignals(false);
+ m_customRatioDInput->blockSignals(false);
+ }
+}
+
+void RatioCropTool::slotXChanged(int x)
+{
+ m_imageSelectionWidget->setSelectionX(x);
+}
+
+void RatioCropTool::slotYChanged(int y)
+{
+ m_imageSelectionWidget->setSelectionY(y);
+}
+
+void RatioCropTool::slotWidthChanged(int w)
+{
+ m_imageSelectionWidget->setSelectionWidth(w);
+}
+
+void RatioCropTool::slotHeightChanged(int h)
+{
+ m_imageSelectionWidget->setSelectionHeight(h);
+}
+
+void RatioCropTool::slotPreciseCropChanged(bool a)
+{
+ m_imageSelectionWidget->setPreciseCrop(a);
+}
+
+void RatioCropTool::slotOrientChanged(int o)
+{
+ m_imageSelectionWidget->setSelectionOrientation(o);
+
+ // Reset selection area.
+ slotResetSettings();
+}
+
+void RatioCropTool::slotAutoOrientChanged(bool a)
+{
+ m_orientCB->setEnabled(!a /*|| m_ratioCB->currentItem() == ImageSelectionWidget::RATIONONE*/);
+ m_imageSelectionWidget->setAutoOrientation(a);
+}
+
+void RatioCropTool::slotRatioChanged(int a)
+{
+ applyRatioChanges(a);
+
+ // Reset selection area.
+ slotResetSettings();
+}
+
+void RatioCropTool::applyRatioChanges(int a)
+{
+ m_imageSelectionWidget->setSelectionAspectRatioType(a);
+
+ if (a == ImageSelectionWidget::RATIOCUSTOM)
+ {
+ m_customLabel1->setEnabled(true);
+ m_customLabel2->setEnabled(true);
+ m_customRatioNInput->setEnabled(true);
+ m_customRatioDInput->setEnabled(true);
+ m_orientLabel->setEnabled(true);
+ m_orientCB->setEnabled(!m_autoOrientation->isChecked());
+ m_autoOrientation->setEnabled(true);
+ slotCustomRatioChanged();
+ }
+ else if (a == ImageSelectionWidget::RATIONONE)
+ {
+ m_orientLabel->setEnabled(false);
+ m_orientCB->setEnabled(false);
+ m_autoOrientation->setEnabled(false);
+ m_customLabel1->setEnabled(false);
+ m_customLabel2->setEnabled(false);
+ m_customRatioNInput->setEnabled(false);
+ m_customRatioDInput->setEnabled(false);
+ }
+ else // Pre-config ratio selected.
+ {
+ m_orientLabel->setEnabled(true);
+ m_orientCB->setEnabled(!m_autoOrientation->isChecked());
+ m_autoOrientation->setEnabled(true);
+ m_customLabel1->setEnabled(false);
+ m_customLabel2->setEnabled(false);
+ m_customRatioNInput->setEnabled(false);
+ m_customRatioDInput->setEnabled(false);
+ }
+}
+
+void RatioCropTool::slotGuideTypeChanged(int t)
+{
+ if (t == ImageSelectionWidget::GuideNone)
+ {
+ m_goldenSectionBox->setEnabled(false);
+ m_goldenSpiralSectionBox->setEnabled(false);
+ m_goldenSpiralBox->setEnabled(false);
+ m_goldenTriangleBox->setEnabled(false);
+ m_flipHorBox->setEnabled(false);
+ m_flipVerBox->setEnabled(false);
+ m_colorGuideLabel->setEnabled(false);
+ m_guideColorBt->setEnabled(false);
+ m_guideSize->setEnabled(false);
+ }
+ else if (t == ImageSelectionWidget::RulesOfThirds)
+ {
+ m_goldenSectionBox->setEnabled(false);
+ m_goldenSpiralSectionBox->setEnabled(false);
+ m_goldenSpiralBox->setEnabled(false);
+ m_goldenTriangleBox->setEnabled(false);
+ m_flipHorBox->setEnabled(false);
+ m_flipVerBox->setEnabled(false);
+ m_colorGuideLabel->setEnabled(true);
+ m_guideColorBt->setEnabled(true);
+ m_guideSize->setEnabled(true);
+ }
+ else if (t == ImageSelectionWidget::DiagonalMethod)
+ {
+ m_goldenSectionBox->setEnabled(false);
+ m_goldenSpiralSectionBox->setEnabled(false);
+ m_goldenSpiralBox->setEnabled(false);
+ m_goldenTriangleBox->setEnabled(false);
+ m_flipHorBox->setEnabled(false);
+ m_flipVerBox->setEnabled(false);
+ m_colorGuideLabel->setEnabled(true);
+ m_guideColorBt->setEnabled(true);
+ m_guideSize->setEnabled(true);
+ }
+ else if (t == ImageSelectionWidget::HarmoniousTriangles)
+ {
+ m_goldenSectionBox->setEnabled(false);
+ m_goldenSpiralSectionBox->setEnabled(false);
+ m_goldenSpiralBox->setEnabled(false);
+ m_goldenTriangleBox->setEnabled(false);
+ m_flipHorBox->setEnabled(true);
+ m_flipVerBox->setEnabled(true);
+ m_colorGuideLabel->setEnabled(true);
+ m_guideColorBt->setEnabled(true);
+ m_guideSize->setEnabled(true);
+ }
+ else
+ {
+ m_goldenSectionBox->setEnabled(true);
+ m_goldenSpiralSectionBox->setEnabled(true);
+ m_goldenSpiralBox->setEnabled(true);
+ m_goldenTriangleBox->setEnabled(true);
+ m_flipHorBox->setEnabled(true);
+ m_flipVerBox->setEnabled(true);
+ m_colorGuideLabel->setEnabled(true);
+ m_guideColorBt->setEnabled(true);
+ m_guideSize->setEnabled(true);
+ }
+
+ m_imageSelectionWidget->setGoldenGuideTypes(m_goldenSectionBox->isChecked(),
+ m_goldenSpiralSectionBox->isChecked(),
+ m_goldenSpiralBox->isChecked(),
+ m_goldenTriangleBox->isChecked(),
+ m_flipHorBox->isChecked(),
+ m_flipVerBox->isChecked());
+ m_imageSelectionWidget->slotGuideLines(t);
+}
+
+void RatioCropTool::slotGoldenGuideTypeChanged()
+{
+ slotGuideTypeChanged(m_guideLinesCB->currentItem());
+}
+
+void RatioCropTool::slotCustomNRatioChanged(int a)
+{
+ if ( ! m_autoOrientation->isChecked() )
+ {
+ if ( ( m_orientCB->currentItem() == ImageSelectionWidget::Portrait &&
+ m_customRatioDInput->value() < a) ||
+ ( m_orientCB->currentItem() == ImageSelectionWidget::Landscape &&
+ m_customRatioDInput->value() > a))
+ {
+ m_customRatioDInput->blockSignals(true);
+ m_customRatioDInput->setValue(a);
+ m_customRatioDInput->blockSignals(false);
+ }
+ }
+
+ slotCustomRatioChanged();
+}
+
+void RatioCropTool::slotCustomDRatioChanged(int a)
+{
+ if ( ! m_autoOrientation->isChecked() )
+ {
+ if ( ( m_orientCB->currentItem() == ImageSelectionWidget::Landscape &&
+ m_customRatioNInput->value() < a) ||
+ ( m_orientCB->currentItem() == ImageSelectionWidget::Portrait &&
+ m_customRatioNInput->value() > a))
+ {
+ m_customRatioNInput->blockSignals(true);
+ m_customRatioNInput->setValue(a);
+ m_customRatioNInput->blockSignals(false);
+ }
+ }
+
+ slotCustomRatioChanged();
+}
+
+void RatioCropTool::slotCustomRatioChanged()
+{
+ m_imageSelectionWidget->setSelectionAspectRatioValue(m_customRatioNInput->value(),
+ m_customRatioDInput->value());
+
+ // Reset selection area.
+ slotResetSettings();
+}
+
+void RatioCropTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ TQRect currentRegion = m_imageSelectionWidget->getRegionSelection();
+ ImageIface* iface = m_imageSelectionWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool a = iface->originalHasAlpha();
+ bool sb = iface->originalSixteenBit();
+
+ TQRect normalizedRegion = currentRegion.normalize();
+ if (normalizedRegion.right() > w)
+ normalizedRegion.setRight(w);
+
+ if (normalizedRegion.bottom() > h)
+ normalizedRegion.setBottom(h);
+
+ DImg imOrg(w, h, sb, a, data);
+ delete [] data;
+ imOrg.crop(normalizedRegion);
+
+ iface->putOriginalImage(i18n("Aspect Ratio Crop"), imOrg.bits(), imOrg.width(), imOrg.height());
+
+ kapp->restoreOverrideCursor();
+ writeSettings();
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/ratiocrop/ratiocroptool.h b/src/imageplugins/coreplugin/ratiocrop/ratiocroptool.h
new file mode 100644
index 00000000..833677da
--- /dev/null
+++ b/src/imageplugins/coreplugin/ratiocrop/ratiocroptool.h
@@ -0,0 +1,135 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-06
+ * Description : digiKam image editor Ratio Crop tool
+ *
+ * Copyright (C) 2007 by Jaromir Malenko <malenko at email dot cz>
+ * Copyright (C) 2008 by Roberto Castagnola <roberto dot castagnola at gmail dot com>
+ * Copyright (C) 2004-2009 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef RATIOCROPTOOL_H
+#define RATIOCROPTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQCheckBox;
+class TQLabel;
+class TQToolButton;
+
+class KColorButton;
+
+namespace KDcrawIface
+{
+class RComboBox;
+class RIntNumInput;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageSelectionWidget;
+
+class RatioCropTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ RatioCropTool(TQObject *parent);
+ ~RatioCropTool();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+
+ void applyRatioChanges(int a);
+ void setRatioCBText(int orientation);
+
+private slots:
+
+ void slotMaxAspectRatio();
+ void slotResetSettings();
+
+ void slotCenterWidth();
+ void slotCenterHeight();
+ void slotXChanged(int x);
+ void slotYChanged(int y);
+ void slotWidthChanged(int w);
+ void slotHeightChanged(int h);
+ void slotCustomRatioChanged();
+ void slotCustomNRatioChanged(int a);
+ void slotCustomDRatioChanged(int a);
+ void slotPreciseCropChanged(bool a);
+ void slotOrientChanged(int o);
+ void slotAutoOrientChanged(bool a);
+ void slotRatioChanged(int a);
+ void slotSelectionChanged(TQRect rect );
+ void slotSelectionOrientationChanged(int);
+ void slotGuideTypeChanged(int t);
+ void slotGoldenGuideTypeChanged();
+
+private:
+
+ bool m_originalIsLandscape;
+
+ TQLabel *m_customLabel1;
+ TQLabel *m_customLabel2;
+ TQLabel *m_orientLabel;
+ TQLabel *m_colorGuideLabel;
+
+
+ TQToolButton *m_centerWidth;
+ TQToolButton *m_centerHeight;
+
+ TQCheckBox *m_goldenSectionBox;
+ TQCheckBox *m_goldenSpiralSectionBox;
+ TQCheckBox *m_goldenSpiralBox;
+ TQCheckBox *m_goldenTriangleBox;
+ TQCheckBox *m_flipHorBox;
+ TQCheckBox *m_flipVerBox;
+ TQCheckBox *m_autoOrientation;
+ TQCheckBox *m_preciseCrop;
+
+ KDcrawIface::RComboBox *m_guideLinesCB;
+ KDcrawIface::RComboBox *m_orientCB;
+ KDcrawIface::RComboBox *m_ratioCB;
+
+ KDcrawIface::RIntNumInput *m_customRatioDInput;
+ KDcrawIface::RIntNumInput *m_customRatioNInput;
+ KDcrawIface::RIntNumInput *m_guideSize;
+ KDcrawIface::RIntNumInput *m_heightInput;
+ KDcrawIface::RIntNumInput *m_widthInput;
+ KDcrawIface::RIntNumInput *m_xInput;
+ KDcrawIface::RIntNumInput *m_yInput;
+
+ KColorButton *m_guideColorBt;
+
+ ImageSelectionWidget *m_imageSelectionWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* RATIOCROPTOOL_H */
diff --git a/src/imageplugins/coreplugin/redeyetool.cpp b/src/imageplugins/coreplugin/redeyetool.cpp
new file mode 100644
index 00000000..5b5af7e7
--- /dev/null
+++ b/src/imageplugins/coreplugin/redeyetool.cpp
@@ -0,0 +1,587 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-06
+ * Description : Red eyes correction tool for image editor
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqhbox.h>
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqvbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqcombobox.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <kcolordialog.h>
+#include <kcolordialog.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// Digikam includes.
+
+#include "bcgmodifier.h"
+#include "colorgradientwidget.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "redeyetool.h"
+#include "redeyetool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+RedEyeTool::RedEyeTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("redeye");
+ setToolName(i18n("Red Eye"));
+ setToolIcon(SmallIcon("redeyes"));
+ setToolHelp("redeyecorrectiontool.anchor");
+
+ m_destinationPreviewData = 0;
+
+ m_previewWidget = new ImageWidget("redeye Tool", 0,
+ i18n("<p>Here you can see the image selection preview with "
+ "red eye reduction applied."),
+ true, ImageGuideWidget::PickColorMode, true, true);
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ EditorToolSettings *gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings->plainPage(), 11, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings->plainPage());
+ label1->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+ m_channelCB = new TQComboBox(false, gboxSettings->plainPage());
+ m_channelCB->insertItem(i18n("Luminosity"));
+ m_channelCB->insertItem(i18n("Red"));
+ m_channelCB->insertItem(i18n("Green"));
+ m_channelCB->insertItem(i18n("Blue"));
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image channel values.<p>"
+ "<b>Green</b>: display the green image channel values.<p>"
+ "<b>Blue</b>: display the blue image channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin(0);
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximum counts are small, you can use the linear scale.<p>"
+ "The logarithmic scale can be used when the maximal counts are big "
+ "to show all values (small and large) on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(linHistoButton, i18n("<p>Linear"));
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap(TQPixmap(directory + "histogram-lin.png"));
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(logHistoButton, i18n("<p>Logarithmic"));
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap(TQPixmap(directory + "histogram-log.png"));
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram "
+ "of the selected image channel. It is "
+ "updated upon setting changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal, 10, histoBox);
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ // -------------------------------------------------------------
+
+ m_thresholdLabel = new TQLabel(i18n("Sensitivity:"), gboxSettings->plainPage());
+ m_redThreshold = new RIntNumInput(gboxSettings->plainPage());
+ m_redThreshold->setRange(10, 90, 1);
+ m_redThreshold->setDefaultValue(20);
+ TQWhatsThis::add(m_redThreshold, i18n("<p>Sets the red color pixels selection threshold. "
+ "Low values will select more red color pixels (agressive correction), high "
+ "values less (mild correction). Use low value if eye have been selected "
+ "exactly. Use high value if other parts of the face are also selected."));
+
+ m_smoothLabel = new TQLabel(i18n("Smooth:"), gboxSettings->plainPage());
+ m_smoothLevel = new RIntNumInput(gboxSettings->plainPage());
+ m_smoothLevel->setRange(0, 5, 1);
+ m_smoothLevel->setDefaultValue(1);
+ TQWhatsThis::add(m_smoothLevel, i18n("<p>Sets the smoothness value when blurring the border "
+ "of the changed pixels. "
+ "This leads to a more naturally looking pupil."));
+
+ TQLabel *label3 = new TQLabel(i18n("Coloring Tint:"), gboxSettings->plainPage());
+ m_HSSelector = new KHSSelector(gboxSettings->plainPage());
+ m_VSelector = new KValueSelector(gboxSettings->plainPage());
+ m_HSSelector->setMinimumSize(200, 142);
+ m_VSelector->setMinimumSize(26, 142);
+ TQWhatsThis::add(m_HSSelector, i18n("<p>Sets a custom color to re-colorize the eyes."));
+
+ TQLabel *label4 = new TQLabel(i18n("Tint Level:"), gboxSettings->plainPage());
+ m_tintLevel = new RIntNumInput(gboxSettings->plainPage());
+ m_tintLevel->setRange(1, 200, 1);
+ m_tintLevel->setDefaultValue(128);
+ TQWhatsThis::add(m_tintLevel, i18n("<p>Set the tint level to adjust the luminosity of "
+ "the new color of the pupil."));
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+ gridSettings->addMultiCellWidget(m_thresholdLabel, 3, 3, 0, 4);
+ gridSettings->addMultiCellWidget(m_redThreshold, 4, 4, 0, 4);
+ gridSettings->addMultiCellWidget(m_smoothLabel, 5, 5, 0, 4);
+ gridSettings->addMultiCellWidget(m_smoothLevel, 6, 6, 0, 4);
+ gridSettings->addMultiCellWidget(label3, 7, 7, 0, 4);
+ gridSettings->addMultiCellWidget(m_HSSelector, 8, 8, 0, 3);
+ gridSettings->addMultiCellWidget(m_VSelector, 8, 8, 4, 4);
+ gridSettings->addMultiCellWidget(label4, 9, 9, 0, 4);
+ gridSettings->addMultiCellWidget(m_tintLevel, 10, 10, 0, 4);
+ gridSettings->setRowStretch(11, 10);
+ gridSettings->setColStretch(3, 10);
+
+ setToolSettings(gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotColorSelectedFromTarget(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_redThreshold, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_smoothLevel, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_HSSelector, TQ_SIGNAL(valueChanged(int, int)),
+ this, TQ_SLOT(slotHSChanged(int, int)));
+
+ connect(m_VSelector, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_tintLevel, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+RedEyeTool::~RedEyeTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void RedEyeTool::slotHSChanged(int h, int s)
+{
+ m_VSelector->blockSignals(true);
+ m_VSelector->setHue(h);
+ m_VSelector->setSaturation(s);
+ m_VSelector->updateContents();
+ m_VSelector->repaint(false);
+ m_VSelector->blockSignals(false);
+ slotTimer();
+}
+
+void RedEyeTool::slotChannelChanged(int channel)
+{
+ switch (channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("red"));
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("green"));
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("blue"));
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void RedEyeTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void RedEyeTool::slotColorSelectedFromTarget(const DColor& color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void RedEyeTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("redeye Tool");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+ m_redThreshold->setValue(config->readNumEntry("RedThreshold", m_redThreshold->defaultValue()));
+ m_smoothLevel->setValue(config->readNumEntry("SmoothLevel", m_smoothLevel->defaultValue()));
+ m_HSSelector->setXValue(config->readNumEntry("HueColoringTint", 0));
+ m_HSSelector->setYValue(config->readNumEntry("SatColoringTint", 0));
+ m_VSelector->setValue(config->readNumEntry("ValColoringTint", 0));
+ m_tintLevel->setValue(config->readNumEntry("TintLevel", m_tintLevel->defaultValue()));
+
+ slotHSChanged(m_HSSelector->xValue(), m_HSSelector->yValue());
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void RedEyeTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("redeye Tool");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("RedThreshold", m_redThreshold->value());
+ config->writeEntry("SmoothLevel", m_smoothLevel->value());
+ config->writeEntry("HueColoringTint", m_HSSelector->xValue());
+ config->writeEntry("SatColoringTint", m_HSSelector->yValue());
+ config->writeEntry("ValColoringTint", m_VSelector->value());
+ config->writeEntry("TintLevel", m_tintLevel->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void RedEyeTool::slotResetSettings()
+{
+ m_redThreshold->blockSignals(true);
+ m_HSSelector->blockSignals(true);
+ m_VSelector->blockSignals(true);
+ m_tintLevel->blockSignals(true);
+
+ m_redThreshold->slotReset();
+ m_smoothLevel->slotReset();
+
+ // Black color by default
+ m_HSSelector->setXValue(0);
+ m_HSSelector->setYValue(0);
+ m_VSelector->setValue(0);
+
+ m_tintLevel->slotReset();
+
+ m_redThreshold->blockSignals(false);
+ m_HSSelector->blockSignals(false);
+ m_VSelector->blockSignals(false);
+ m_tintLevel->blockSignals(false);
+}
+
+void RedEyeTool::slotEffect()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ // Here, we need to use the real selection image data because we will apply
+ // a Gaussian blur filter on pixels and we cannot use directly the preview scaled image
+ // else the blur radius will not give the same result between preview and final rendering.
+ ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getImageSelection();
+ int w = iface->selectedWidth();
+ int h = iface->selectedHeight();
+ bool sb = iface->originalSixteenBit();
+ bool a = iface->originalHasAlpha();
+ DImg selection(w, h, sb, a, m_destinationPreviewData);
+
+ redEyeFilter(selection);
+
+ DImg preview = selection.smoothScale(iface->previewWidth(), iface->previewHeight());
+
+ iface->putPreviewImage(preview.bits());
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, selection.bits(), selection.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void RedEyeTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getImageSelection();
+ int w = iface->selectedWidth();
+ int h = iface->selectedHeight();
+ bool sixteenBit = iface->originalSixteenBit();
+ bool hasAlpha = iface->originalHasAlpha();
+ DImg selection(w, h, sixteenBit, hasAlpha, data);
+ delete [] data;
+
+ redEyeFilter(selection);
+
+ iface->putImageSelection(i18n("Red Eyes Correction"), selection.bits());
+
+ kapp->restoreOverrideCursor();
+}
+
+void RedEyeTool::redEyeFilter(DImg& selection)
+{
+ DImg mask(selection.width(), selection.height(), selection.sixteenBit(), true,
+ selection.bits(), true);
+
+ selection = mask.copy();
+ float redThreshold = m_redThreshold->value()/10.0;
+ int hue = m_HSSelector->xValue();
+ int sat = m_HSSelector->yValue();
+ int val = m_VSelector->value();
+ KColor coloring;
+ coloring.setHsv(hue, sat, val);
+
+ struct channel
+ {
+ float red_gain;
+ float green_gain;
+ float blue_gain;
+ };
+
+ channel red_chan, green_chan, blue_chan;
+
+ red_chan.red_gain = 0.1;
+ red_chan.green_gain = 0.6;
+ red_chan.blue_gain = 0.3;
+
+ green_chan.red_gain = 0.0;
+ green_chan.green_gain = 1.0;
+ green_chan.blue_gain = 0.0;
+
+ blue_chan.red_gain = 0.0;
+ blue_chan.green_gain = 0.0;
+ blue_chan.blue_gain = 1.0;
+
+ float red_norm, green_norm, blue_norm;
+ int level = 201 - m_tintLevel->value();
+
+ red_norm = 1.0 / (red_chan.red_gain + red_chan.green_gain + red_chan.blue_gain);
+ green_norm = 1.0 / (green_chan.red_gain + green_chan.green_gain + green_chan.blue_gain);
+ blue_norm = 1.0 / (blue_chan.red_gain + blue_chan.green_gain + blue_chan.blue_gain);
+
+ red_norm *= coloring.red() / level;
+ green_norm *= coloring.green() / level;
+ blue_norm *= coloring.blue() / level;
+
+ // Perform a red color pixels detection in selection image and create a correction mask using an alpha channel.
+
+ if (!selection.sixteenBit()) // 8 bits image.
+ {
+ uchar* ptr = selection.bits();
+ uchar* mptr = mask.bits();
+ uchar r, g, b, r1, g1, b1;
+
+ for (uint i = 0 ; i < selection.width() * selection.height() ; i++)
+ {
+ b = ptr[0];
+ g = ptr[1];
+ r = ptr[2];
+ mptr[3] = 255;
+
+ if (r >= ( redThreshold * g))
+ {
+ r1 = TQMIN(255, (int)(red_norm * (red_chan.red_gain * r +
+ red_chan.green_gain * g +
+ red_chan.blue_gain * b)));
+
+ g1 = TQMIN(255, (int)(green_norm * (green_chan.red_gain * r +
+ green_chan.green_gain * g +
+ green_chan.blue_gain * b)));
+
+ b1 = TQMIN(255, (int)(blue_norm * (blue_chan.red_gain * r +
+ blue_chan.green_gain * g +
+ blue_chan.blue_gain * b)));
+
+ mptr[0] = b1;
+ mptr[1] = g1;
+ mptr[2] = r1;
+ mptr[3] = TQMIN( (int)((r-g) / 150.0 * 255.0), 255);
+ }
+
+ ptr += 4;
+ mptr+= 4;
+ }
+ }
+ else // 16 bits image.
+ {
+ unsigned short* ptr = (unsigned short*)selection.bits();
+ unsigned short* mptr = (unsigned short*)mask.bits();
+ unsigned short r, g, b, r1, g1, b1;
+
+ for (uint i = 0 ; i < selection.width() * selection.height() ; i++)
+ {
+ b = ptr[0];
+ g = ptr[1];
+ r = ptr[2];
+ mptr[3] = 65535;
+
+ if (r >= ( redThreshold * g))
+ {
+ r1 = TQMIN(65535, (int)(red_norm * (red_chan.red_gain * r +
+ red_chan.green_gain * g +
+ red_chan.blue_gain * b)));
+
+ g1 = TQMIN(65535, (int)(green_norm * (green_chan.red_gain * r +
+ green_chan.green_gain * g +
+ green_chan.blue_gain * b)));
+
+ b1 = TQMIN(65535, (int)(blue_norm * (blue_chan.red_gain * r +
+ blue_chan.green_gain * g +
+ blue_chan.blue_gain * b)));
+
+ mptr[0] = b1;
+ mptr[1] = g1;
+ mptr[2] = r1;
+ mptr[3] = TQMIN( (int)((r-g) / 38400.0 * 65535.0), 65535);;
+ }
+
+ ptr += 4;
+ mptr+= 4;
+ }
+ }
+
+ // Now, we will blur only the transparency pixels from the mask.
+
+ DImg mask2 = mask.copy();
+ DImgImageFilters filter;
+ filter.gaussianBlurImage(mask2.bits(), mask2.width(), mask2.height(),
+ mask2.sixteenBit(), m_smoothLevel->value());
+
+ if (!selection.sixteenBit()) // 8 bits image.
+ {
+ uchar* mptr = mask.bits();
+ uchar* mptr2 = mask2.bits();
+
+ for (uint i = 0 ; i < mask2.width() * mask2.height() ; i++)
+ {
+ if (mptr2[3] < 255)
+ {
+ mptr[0] = mptr2[0];
+ mptr[1] = mptr2[1];
+ mptr[2] = mptr2[2];
+ mptr[3] = mptr2[3];
+ }
+
+ mptr += 4;
+ mptr2+= 4;
+ }
+ }
+ else // 16 bits image.
+ {
+ unsigned short* mptr = (unsigned short*)mask.bits();
+ unsigned short* mptr2 = (unsigned short*)mask2.bits();
+
+ for (uint i = 0 ; i < mask2.width() * mask2.height() ; i++)
+ {
+ if (mptr2[3] < 65535)
+ {
+ mptr[0] = mptr2[0];
+ mptr[1] = mptr2[1];
+ mptr[2] = mptr2[2];
+ mptr[3] = mptr2[3];
+ }
+
+ mptr += 4;
+ mptr2+= 4;
+ }
+ }
+
+ // - Perform pixels blending using alpha channel between the mask and the selection.
+
+ DColorComposer *composer = DColorComposer::getComposer(DColorComposer::PorterDuffSrcOver);
+
+ // NOTE: 'mask' is the Source image, 'selection' is the Destination image.
+
+ selection.bitBlendImage(composer, &mask,
+ 0, 0, mask.width(), mask.height(),
+ 0, 0);
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/redeyetool.h b/src/imageplugins/coreplugin/redeyetool.h
new file mode 100644
index 00000000..eb614fd3
--- /dev/null
+++ b/src/imageplugins/coreplugin/redeyetool.h
@@ -0,0 +1,157 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-06-06
+ * Description : Red eyes correction tool for image editor
+ *
+ * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+
+#ifndef REDEYETOOL_H
+#define REDEYETOOL_H
+
+// KDE includes.
+
+#include <kpassivepopup.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQLabel;
+class TQComboBox;
+class TQHButtonGroup;
+
+class KHSSelector;
+class KValueSelector;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+class DImg;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class RedEyePassivePopup : public KPassivePopup
+{
+public:
+
+ RedEyePassivePopup(TQWidget* parent)
+ : KPassivePopup(parent), m_parent(parent)
+ {
+ }
+
+protected:
+
+ virtual void positionSelf()
+ {
+ move(m_parent->x() + 30, m_parent->y() + 30);
+ }
+
+private:
+
+ TQWidget* m_parent;
+};
+
+// ----------------------------------------------------------------
+
+class RedEyeTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ RedEyeTool(TQObject *parent);
+ ~RedEyeTool();
+
+private slots:
+
+ void slotEffect();
+ void slotResetSettings();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+ void slotHSChanged(int h, int s);
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+ void redEyeFilter(Digikam::DImg& selection);
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum RedThresold
+ {
+ Mild=0,
+ Aggressive
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQLabel *m_thresholdLabel;
+ TQLabel *m_smoothLabel;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ KDcrawIface::RIntNumInput *m_tintLevel;
+ KDcrawIface::RIntNumInput *m_redThreshold;
+ KDcrawIface::RIntNumInput *m_smoothLevel;
+
+ KHSSelector *m_HSSelector;
+ KValueSelector *m_VSelector;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* REDEYETOOL_H */
diff --git a/src/imageplugins/coreplugin/rgbtool.cpp b/src/imageplugins/coreplugin/rgbtool.cpp
new file mode 100644
index 00000000..e27e396e
--- /dev/null
+++ b/src/imageplugins/coreplugin/rgbtool.cpp
@@ -0,0 +1,440 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-11
+ * Description : digiKam image editor Color Balance tool.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqframe.h>
+#include <tqgroupbox.h>
+#include <tqhbuttongroup.h>
+#include <tqhgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqslider.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Digikam includes.
+
+#include "colorgradientwidget.h"
+#include "colormodifier.h"
+#include "dimg.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+
+// Local includes.
+
+#include "rgbtool.h"
+#include "rgbtool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+RGBTool::RGBTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("colorbalance");
+ setToolName(i18n("Color Balance"));
+ setToolIcon(SmallIcon("adjustrgb"));
+
+ m_destinationPreviewData = 0;
+
+ m_previewWidget = new ImageWidget("colorbalance Tool", 0,
+ i18n("<p>Here you can see the image "
+ "color-balance adjustments preview. "
+ "You can pick color on image "
+ "to see the color level corresponding on histogram."));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* gridSettings = new TQGridLayout(m_gboxSettings->plainPage(), 7, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), m_gboxSettings->plainPage());
+ label1->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+ m_channelCB = new TQComboBox(false, m_gboxSettings->plainPage());
+ m_channelCB->insertItem(i18n("Luminosity"));
+ m_channelCB->insertItem(i18n("Red"));
+ m_channelCB->insertItem(i18n("Green"));
+ m_channelCB->insertItem(i18n("Blue"));
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin(0);
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(linHistoButton, i18n("<p>Linear"));
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap(TQPixmap(directory + "histogram-lin.png"));
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton(m_scaleBG);
+ TQToolTip::add(logHistoButton, i18n("<p>Logarithmic"));
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap(TQPixmap(directory + "histogram-log.png"));
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ gridSettings->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(m_gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram drawing "
+ "of the selected image channel. This one is re-computed at any "
+ "settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget(ColorGradientWidget::Horizontal, 10, histoBox);
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+
+ gridSettings->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQLabel *labelLeft = new TQLabel(i18n("Cyan"), m_gboxSettings->plainPage());
+ labelLeft->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_rSlider = new TQSlider(-100, 100, 1, 0, TQt::Horizontal, m_gboxSettings->plainPage(), "m_rSlider");
+ m_rSlider->setTickmarks(TQSlider::Below);
+ m_rSlider->setTickInterval(20);
+ TQWhatsThis::add( m_rSlider, i18n("<p>Set here the cyan/red color adjustment of the image."));
+ TQLabel *labelRight = new TQLabel(i18n("Red"), m_gboxSettings->plainPage());
+ labelRight->setAlignment ( TQt::AlignLeft | TQt::AlignVCenter );
+ m_rInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_rInput->setDefaultValue(0);
+ m_rInput->input()->setRange(-100, 100, 1, false);
+
+ gridSettings->addMultiCellWidget(labelLeft, 3, 3, 0, 0);
+ gridSettings->addMultiCellWidget(m_rSlider, 3, 3, 1, 1);
+ gridSettings->addMultiCellWidget(labelRight, 3, 3, 2, 2);
+ gridSettings->addMultiCellWidget(m_rInput, 3, 3, 3, 3);
+
+ // -------------------------------------------------------------
+
+ labelLeft = new TQLabel(i18n("Magenta"), m_gboxSettings->plainPage());
+ labelLeft->setAlignment(TQt::AlignRight | TQt::AlignVCenter);
+ m_gSlider = new TQSlider(-100, 100, 1, 0, TQt::Horizontal, m_gboxSettings->plainPage(), "m_gSlider");
+ m_gSlider->setTickmarks(TQSlider::Below);
+ m_gSlider->setTickInterval(20);
+ TQWhatsThis::add( m_gSlider, i18n("<p>Set here the magenta/green color adjustment of the image."));
+ labelRight = new TQLabel(i18n("Green"), m_gboxSettings->plainPage());
+ labelRight->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ m_gInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_gInput->setDefaultValue(0);
+ m_gInput->input()->setRange(-100, 100, 1, false);
+
+ gridSettings->addMultiCellWidget(labelLeft, 4, 4, 0, 0);
+ gridSettings->addMultiCellWidget(m_gSlider, 4, 4, 1, 1);
+ gridSettings->addMultiCellWidget(labelRight, 4, 4, 2, 2);
+ gridSettings->addMultiCellWidget(m_gInput, 4, 4, 3, 3);
+
+ // -------------------------------------------------------------
+
+ labelLeft = new TQLabel(i18n("Yellow"), m_gboxSettings->plainPage());
+ labelLeft->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_bSlider = new TQSlider(-100, 100, 1, 0, TQt::Horizontal, m_gboxSettings->plainPage(), "m_bSlider");
+ m_bSlider->setTickmarks(TQSlider::Below);
+ m_bSlider->setTickInterval(20);
+ TQWhatsThis::add( m_bSlider, i18n("<p>Set here the yellow/blue color adjustment of the image."));
+ labelRight = new TQLabel(i18n("Blue"), m_gboxSettings->plainPage());
+ labelRight->setAlignment(TQt::AlignLeft | TQt::AlignVCenter);
+ m_bInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_bInput->setDefaultValue(0);
+ m_bInput->input()->setRange(-100, 100, 1, false);
+
+ gridSettings->addMultiCellWidget(labelLeft, 5, 5, 0, 0);
+ gridSettings->addMultiCellWidget(m_bSlider, 5, 5, 1, 1);
+ gridSettings->addMultiCellWidget(labelRight, 5, 5, 2, 2);
+ gridSettings->addMultiCellWidget(m_bInput, 5, 5, 3, 3);
+
+ m_rInput->setValue(0);
+ m_gInput->setValue(0);
+ m_bInput->setValue(0);
+
+ gridSettings->setRowStretch(6, 10);
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_rSlider, TQ_SIGNAL(valueChanged(int)),
+ m_rInput, TQ_SLOT(setValue(int)));
+ connect(m_rInput, TQ_SIGNAL(valueChanged (int)),
+ m_rSlider, TQ_SLOT(setValue(int)));
+ connect(m_rInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gSlider, TQ_SIGNAL(valueChanged(int)),
+ m_gInput, TQ_SLOT(setValue(int)));
+ connect(m_gInput, TQ_SIGNAL(valueChanged (int)),
+ m_gSlider, TQ_SLOT(setValue(int)));
+ connect(m_gInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_bSlider, TQ_SIGNAL(valueChanged(int)),
+ m_bInput, TQ_SLOT(setValue(int)));
+ connect(m_bInput, TQ_SIGNAL(valueChanged (int)),
+ m_bSlider, TQ_SLOT(setValue(int)));
+ connect(m_bInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings->enableButton(EditorToolSettings::Ok, false);
+}
+
+RGBTool::~RGBTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void RGBTool::slotChannelChanged(int channel)
+{
+ switch (channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("white"));
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("red"));
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("green"));
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors(TQColor("black"), TQColor("blue"));
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void RGBTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void RGBTool::slotColorSelectedFromTarget(const DColor &color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void RGBTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("colorbalance Tool");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+ int r = config->readNumEntry("RedAjustment", m_rInput->defaultValue());
+ int g = config->readNumEntry("GreenAjustment", m_gInput->defaultValue());
+ int b = config->readNumEntry("BlueAjustment", m_bInput->defaultValue());
+ adjustSliders(r, g, b);
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void RGBTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("colorbalance Tool");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+ config->writeEntry("RedAjustment", m_rSlider->value());
+ config->writeEntry("GreenAjustment", m_gInput->value());
+ config->writeEntry("BlueAjustment", m_bInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void RGBTool::slotResetSettings()
+{
+ int r = m_rInput->defaultValue();
+ int g = m_gInput->defaultValue();
+ int b = m_bInput->defaultValue();
+
+ adjustSliders(r, g, b);
+}
+
+void RGBTool::adjustSliders(int r, int g, int b)
+{
+ m_rSlider->blockSignals(true);
+ m_gSlider->blockSignals(true);
+ m_bSlider->blockSignals(true);
+ m_rInput->blockSignals(true);
+ m_gInput->blockSignals(true);
+ m_bInput->blockSignals(true);
+
+ m_rSlider->setValue(r);
+ m_gSlider->setValue(g);
+ m_bSlider->setValue(b);
+ m_rInput->setValue(r);
+ m_gInput->setValue(g);
+ m_bInput->setValue(b);
+
+ m_rSlider->blockSignals(false);
+ m_gSlider->blockSignals(false);
+ m_bSlider->blockSignals(false);
+ m_rInput->blockSignals(false);
+ m_gInput->blockSignals(false);
+ m_bInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void RGBTool::slotEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ m_gboxSettings->enableButton(EditorToolSettings::Ok,
+ (m_rInput->value() != 0 ||
+ m_gInput->value() != 0 ||
+ m_bInput->value() != 0));
+
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ m_destinationPreviewData = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool alpha = iface->previewHasAlpha();
+ bool sixteenBit = iface->previewSixteenBit();
+
+ double r = ((double) m_rInput->value() + 100.0) / 100.0;
+ double g = ((double) m_gInput->value() + 100.0) / 100.0;
+ double b = ((double) m_bInput->value() + 100.0) / 100.0;
+ double a = 1.0;
+
+ DImg preview(w, h, sixteenBit, alpha, m_destinationPreviewData);
+ ColorModifier cmod;
+ cmod.applyColorModifier(preview, r, g, b, a);
+ iface->putPreviewImage(preview.bits());
+
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+
+ memcpy(m_destinationPreviewData, preview.bits(), preview.numBytes());
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sixteenBit, 0, 0, 0, false);
+
+ kapp->restoreOverrideCursor();
+}
+
+void RGBTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ double r = ((double) m_rInput->value() + 100.0) / 100.0;
+ double g = ((double) m_gInput->value() + 100.0) / 100.0;
+ double b = ((double) m_bInput->value() + 100.0) / 100.0;
+ double a = 1.0;
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool alpha = iface->originalHasAlpha();
+ bool sixteenBit = iface->originalSixteenBit();
+ DImg original(w, h, sixteenBit, alpha, data);
+ delete [] data;
+
+ ColorModifier cmod;
+ cmod.applyColorModifier(original, r, g, b, a);
+
+ iface->putOriginalImage(i18n("Color Balance"), original.bits());
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/rgbtool.h b/src/imageplugins/coreplugin/rgbtool.h
new file mode 100644
index 00000000..dadb6a0e
--- /dev/null
+++ b/src/imageplugins/coreplugin/rgbtool.h
@@ -0,0 +1,119 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-11
+ * Description : digiKam image editor Color Balance tool.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef RGBTOOL_H
+#define RGBTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQComboBox;
+class TQHButtonGroup;
+
+class TQSlider;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class RGBTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ RGBTool(TQObject *parent);
+ ~RGBTool();
+
+private:
+
+ void writeSettings();
+ void readSettings();
+ void adjustSliders(int r, int g, int b);
+ void finalRendering();
+
+private slots:
+
+ void slotEffect();
+ void slotResetSettings();
+ void slotChannelChanged(int channel);
+ void slotScaleChanged(int scale);
+ void slotColorSelectedFromTarget( const Digikam::DColor &color );
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ uchar *m_destinationPreviewData;
+
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ KDcrawIface::RIntNumInput *m_rInput;
+ KDcrawIface::RIntNumInput *m_gInput;
+ KDcrawIface::RIntNumInput *m_bInput;
+
+ TQSlider *m_rSlider;
+ TQSlider *m_gSlider;
+ TQSlider *m_bSlider;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* RGBTOOL_H */
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/Makefile.am b/src/imageplugins/coreplugin/sharpnesseditor/Makefile.am
new file mode 100644
index 00000000..c02087ee
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/Makefile.am
@@ -0,0 +1,32 @@
+SUBDIRS = clapack
+COMPILE_FIRST = clapack
+
+noinst_LTLIBRARIES = libsharpnesseditor.la
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/imageplugins/coreplugin/sharpnesseditor/clapack \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+libsharpnesseditor_la_LIBADD = $(top_builddir)/src/imageplugins/coreplugin/sharpnesseditor/clapack/liblapack.la
+
+libsharpnesseditor_la_SOURCES = sharpentool.cpp unsharp.cpp matrix.cpp refocus.cpp
+
+libsharpnesseditor_la_LDFLAGS = $(all_libraries)
+
+noinst_HEADERS = sharpentool.h unsharp.h matrix.h refocus.h
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/LICENCE b/src/imageplugins/coreplugin/sharpnesseditor/clapack/LICENCE
new file mode 100644
index 00000000..a338f860
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/LICENCE
@@ -0,0 +1,12 @@
+REDISTRIBUTABLE
+
+LAPACK is a freely-available software package. It is available from netlib via anonymous ftp and the World Wide Web.
+Thus, it can be included in commercial software packages (and has been). We only ask that proper credit be given to the authors.
+
+Like all software, it is copyrighted. It is not trademarked, but we do ask the following:
+
+If you modify the source for these routines we ask that you change the name of the routine
+and comment the changes made to the original.
+
+We will gladly answer any questions regarding the software. If a modification is done, however,
+it is the responsibility of the person who modified the routine to provide support.
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/Makefile.am b/src/imageplugins/coreplugin/sharpnesseditor/clapack/Makefile.am
new file mode 100644
index 00000000..bf478556
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/Makefile.am
@@ -0,0 +1,7 @@
+noinst_LTLIBRARIES = liblapack.la
+
+liblapack_la_CFLAGS = -w
+
+noinst_HEADERS = blaswrap.h clapack.h f2c.h fio.h fmt.h fp.h
+
+liblapack_la_SOURCES = abort_.c dgesv.c dlaswp.c endfile.c idamax.c open.c sig_die.c wref.c close.c dgetf2.c dscal.c err.c ieeeck.c s_cmp.c s_stop.c wrtfmt.c dgemm.c dgetrf.c dswap.c fmt.c ilaenv.c s_copy.c wsfe.c dger.c dgetrs.c dtrsm.c fmtlib.c lsame.c sfe.c util.c xerbla.c
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/README b/src/imageplugins/coreplugin/sharpnesseditor/clapack/README
new file mode 100644
index 00000000..530f73ee
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/README
@@ -0,0 +1,2 @@
+The sources in this directory were copied from the CLAPACK
+distribution (see http://www.netlib.org/clapack).
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/abort_.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/abort_.c
new file mode 100644
index 00000000..67278e93
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/abort_.c
@@ -0,0 +1,10 @@
+#include "stdio.h"
+#include "f2c.h"
+
+extern void sig_die(char*,int);
+
+int abort_(void)
+{
+sig_die("Fortran abort routine called", 1);
+return 0; /* not reached */
+}
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/blaswrap.h b/src/imageplugins/coreplugin/sharpnesseditor/clapack/blaswrap.h
new file mode 100644
index 00000000..84c08d30
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/blaswrap.h
@@ -0,0 +1,158 @@
+/* CLAPACK 3.0 BLAS wrapper macros
+ * Feb 5, 2000
+ */
+
+#ifndef __BLASWRAP_H
+#define __BLASWRAP_H
+
+#ifndef NO_BLAS_WRAP
+
+/* BLAS1 routines */
+#define srotg_ f2c_srotg
+#define drotg_ f2c_drotg
+#define srotmg_ f2c_srotmg
+#define drotmg_ f2c_drotmg
+#define srot_ f2c_srot
+#define drot_ f2c_drot
+#define srotm_ f2c_srotm
+#define drotm_ f2c_drotm
+#define sswap_ f2c_sswap
+#define dswap_ f2c_dswap
+#define cswap_ f2c_cswap
+#define zswap_ f2c_zswap
+#define sscal_ f2c_sscal
+#define dscal_ f2c_dscal
+#define cscal_ f2c_cscal
+#define zscal_ f2c_zscal
+#define csscal_ f2c_csscal
+#define zdscal_ f2c_zdscal
+#define scopy_ f2c_scopy
+#define dcopy_ f2c_dcopy
+#define ccopy_ f2c_ccopy
+#define zcopy_ f2c_zcopy
+#define saxpy_ f2c_saxpy
+#define daxpy_ f2c_daxpy
+#define caxpy_ f2c_caxpy
+#define zaxpy_ f2c_zaxpy
+#define sdot_ f2c_sdot
+#define ddot_ f2c_ddot
+#define cdotu_ f2c_cdotu
+#define zdotu_ f2c_zdotu
+#define cdotc_ f2c_cdotc
+#define zdotc_ f2c_zdotc
+#define snrm2_ f2c_snrm2
+#define dnrm2_ f2c_dnrm2
+#define scnrm2_ f2c_scnrm2
+#define dznrm2_ f2c_dznrm2
+#define sasum_ f2c_sasum
+#define dasum_ f2c_dasum
+#define scasum_ f2c_scasum
+#define dzasum_ f2c_dzasum
+#define isamax_ f2c_isamax
+#define idamax_ f2c_idamax
+#define icamax_ f2c_icamax
+#define izamax_ f2c_izamax
+
+/* BLAS2 routines */
+#define sgemv_ f2c_sgemv
+#define dgemv_ f2c_dgemv
+#define cgemv_ f2c_cgemv
+#define zgemv_ f2c_zgemv
+#define sgbmv_ f2c_sgbmv
+#define dgbmv_ f2c_dgbmv
+#define cgbmv_ f2c_cgbmv
+#define zgbmv_ f2c_zgbmv
+#define chemv_ f2c_chemv
+#define zhemv_ f2c_zhemv
+#define chbmv_ f2c_chbmv
+#define zhbmv_ f2c_zhbmv
+#define chpmv_ f2c_chpmv
+#define zhpmv_ f2c_zhpmv
+#define ssymv_ f2c_ssymv
+#define dsymv_ f2c_dsymv
+#define ssbmv_ f2c_ssbmv
+#define dsbmv_ f2c_dsbmv
+#define sspmv_ f2c_sspmv
+#define dspmv_ f2c_dspmv
+#define strmv_ f2c_strmv
+#define dtrmv_ f2c_dtrmv
+#define ctrmv_ f2c_ctrmv
+#define ztrmv_ f2c_ztrmv
+#define stbmv_ f2c_stbmv
+#define dtbmv_ f2c_dtbmv
+#define ctbmv_ f2c_ctbmv
+#define ztbmv_ f2c_ztbmv
+#define stpmv_ f2c_stpmv
+#define dtpmv_ f2c_dtpmv
+#define ctpmv_ f2c_ctpmv
+#define ztpmv_ f2c_ztpmv
+#define strsv_ f2c_strsv
+#define dtrsv_ f2c_dtrsv
+#define ctrsv_ f2c_ctrsv
+#define ztrsv_ f2c_ztrsv
+#define stbsv_ f2c_stbsv
+#define dtbsv_ f2c_dtbsv
+#define ctbsv_ f2c_ctbsv
+#define ztbsv_ f2c_ztbsv
+#define stpsv_ f2c_stpsv
+#define dtpsv_ f2c_dtpsv
+#define ctpsv_ f2c_ctpsv
+#define ztpsv_ f2c_ztpsv
+#define sger_ f2c_sger
+#define dger_ f2c_dger
+#define cgeru_ f2c_cgeru
+#define zgeru_ f2c_zgeru
+#define cgerc_ f2c_cgerc
+#define zgerc_ f2c_zgerc
+#define cher_ f2c_cher
+#define zher_ f2c_zher
+#define chpr_ f2c_chpr
+#define zhpr_ f2c_zhpr
+#define cher2_ f2c_cher2
+#define zher2_ f2c_zher2
+#define chpr2_ f2c_chpr2
+#define zhpr2_ f2c_zhpr2
+#define ssyr_ f2c_ssyr
+#define dsyr_ f2c_dsyr
+#define sspr_ f2c_sspr
+#define dspr_ f2c_dspr
+#define ssyr2_ f2c_ssyr2
+#define dsyr2_ f2c_dsyr2
+#define sspr2_ f2c_sspr2
+#define dspr2_ f2c_dspr2
+
+/* BLAS3 routines */
+#define sgemm_ f2c_sgemm
+#define dgemm_ f2c_dgemm
+#define cgemm_ f2c_cgemm
+#define zgemm_ f2c_zgemm
+#define ssymm_ f2c_ssymm
+#define dsymm_ f2c_dsymm
+#define csymm_ f2c_csymm
+#define zsymm_ f2c_zsymm
+#define chemm_ f2c_chemm
+#define zhemm_ f2c_zhemm
+#define ssyrk_ f2c_ssyrk
+#define dsyrk_ f2c_dsyrk
+#define csyrk_ f2c_csyrk
+#define zsyrk_ f2c_zsyrk
+#define cherk_ f2c_cherk
+#define zherk_ f2c_zherk
+#define ssyr2k_ f2c_ssyr2k
+#define dsyr2k_ f2c_dsyr2k
+#define csyr2k_ f2c_csyr2k
+#define zsyr2k_ f2c_zsyr2k
+#define cher2k_ f2c_cher2k
+#define zher2k_ f2c_zher2k
+#define strmm_ f2c_strmm
+#define dtrmm_ f2c_dtrmm
+#define ctrmm_ f2c_ctrmm
+#define ztrmm_ f2c_ztrmm
+#define strsm_ f2c_strsm
+#define dtrsm_ f2c_dtrsm
+#define ctrsm_ f2c_ctrsm
+#define ztrsm_ f2c_ztrsm
+
+#endif /* NO_BLAS_WRAP */
+
+#endif /* __BLASWRAP_H */
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/clapack.h b/src/imageplugins/coreplugin/sharpnesseditor/clapack/clapack.h
new file mode 100644
index 00000000..cad9a4c2
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/clapack.h
@@ -0,0 +1,5079 @@
+#ifndef __CLAPACK_H
+#define __CLAPACK_H
+
+/* Subroutine */ int cbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+ nru, integer *ncc, real *d__, real *e, complex *vt, integer *ldvt,
+ complex *u, integer *ldu, complex *c__, integer *ldc, real *rwork,
+ integer *info);
+
+/* Subroutine */ int cgbbrd_(char *vect, integer *m, integer *n, integer *ncc,
+ integer *kl, integer *ku, complex *ab, integer *ldab, real *d__,
+ real *e, complex *q, integer *ldq, complex *pt, integer *ldpt,
+ complex *c__, integer *ldc, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgbcon_(char *norm, integer *n, integer *kl, integer *ku,
+ complex *ab, integer *ldab, integer *ipiv, real *anorm, real *rcond,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgbequ_(integer *m, integer *n, integer *kl, integer *ku,
+ complex *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real
+ *colcnd, real *amax, integer *info);
+
+/* Subroutine */ int cgbrfs_(char *trans, integer *n, integer *kl, integer *
+ ku, integer *nrhs, complex *ab, integer *ldab, complex *afb, integer *
+ ldafb, integer *ipiv, complex *b, integer *ldb, complex *x, integer *
+ ldx, real *ferr, real *berr, complex *work, real *rwork, integer *
+ info);
+
+/* Subroutine */ int cgbsv_(integer *n, integer *kl, integer *ku, integer *
+ nrhs, complex *ab, integer *ldab, integer *ipiv, complex *b, integer *
+ ldb, integer *info);
+
+/* Subroutine */ int cgbsvx_(char *fact, char *trans, integer *n, integer *kl,
+ integer *ku, integer *nrhs, complex *ab, integer *ldab, complex *afb,
+ integer *ldafb, integer *ipiv, char *equed, real *r__, real *c__,
+ complex *b, integer *ldb, complex *x, integer *ldx, real *rcond, real
+ *ferr, real *berr, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgbtf2_(integer *m, integer *n, integer *kl, integer *ku,
+ complex *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int cgbtrf_(integer *m, integer *n, integer *kl, integer *ku,
+ complex *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int cgbtrs_(char *trans, integer *n, integer *kl, integer *
+ ku, integer *nrhs, complex *ab, integer *ldab, integer *ipiv, complex
+ *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cgebak_(char *job, char *side, integer *n, integer *ilo,
+ integer *ihi, real *scale, integer *m, complex *v, integer *ldv,
+ integer *info);
+
+/* Subroutine */ int cgebal_(char *job, integer *n, complex *a, integer *lda,
+ integer *ilo, integer *ihi, real *scale, integer *info);
+
+/* Subroutine */ int cgebd2_(integer *m, integer *n, complex *a, integer *lda,
+ real *d__, real *e, complex *tauq, complex *taup, complex *work,
+ integer *info);
+
+/* Subroutine */ int cgebrd_(integer *m, integer *n, complex *a, integer *lda,
+ real *d__, real *e, complex *tauq, complex *taup, complex *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int cgecon_(char *norm, integer *n, complex *a, integer *lda,
+ real *anorm, real *rcond, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgeequ_(integer *m, integer *n, complex *a, integer *lda,
+ real *r__, real *c__, real *rowcnd, real *colcnd, real *amax,
+ integer *info);
+
+/* Subroutine */ int cgees_(char *jobvs, char *sort, L_fp select, integer *n,
+ complex *a, integer *lda, integer *sdim, complex *w, complex *vs,
+ integer *ldvs, complex *work, integer *lwork, real *rwork, logical *
+ bwork, integer *info);
+
+/* Subroutine */ int cgeesx_(char *jobvs, char *sort, L_fp select, char *
+ sense, integer *n, complex *a, integer *lda, integer *sdim, complex *
+ w, complex *vs, integer *ldvs, real *rconde, real *rcondv, complex *
+ work, integer *lwork, real *rwork, logical *bwork, integer *info);
+
+/* Subroutine */ int cgeev_(char *jobvl, char *jobvr, integer *n, complex *a,
+ integer *lda, complex *w, complex *vl, integer *ldvl, complex *vr,
+ integer *ldvr, complex *work, integer *lwork, real *rwork, integer *
+ info);
+
+/* Subroutine */ int cgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+ sense, integer *n, complex *a, integer *lda, complex *w, complex *vl,
+ integer *ldvl, complex *vr, integer *ldvr, integer *ilo, integer *ihi,
+ real *scale, real *abnrm, real *rconde, real *rcondv, complex *work,
+ integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int cgegs_(char *jobvsl, char *jobvsr, integer *n, complex *
+ a, integer *lda, complex *b, integer *ldb, complex *alpha, complex *
+ beta, complex *vsl, integer *ldvsl, complex *vsr, integer *ldvsr,
+ complex *work, integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int cgegv_(char *jobvl, char *jobvr, integer *n, complex *a,
+ integer *lda, complex *b, integer *ldb, complex *alpha, complex *beta,
+ complex *vl, integer *ldvl, complex *vr, integer *ldvr, complex *
+ work, integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int cgehd2_(integer *n, integer *ilo, integer *ihi, complex *
+ a, integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgehrd_(integer *n, integer *ilo, integer *ihi, complex *
+ a, integer *lda, complex *tau, complex *work, integer *lwork, integer
+ *info);
+
+/* Subroutine */ int cgelq2_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgelqf_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgels_(char *trans, integer *m, integer *n, integer *
+ nrhs, complex *a, integer *lda, complex *b, integer *ldb, complex *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgelsx_(integer *m, integer *n, integer *nrhs, complex *
+ a, integer *lda, complex *b, integer *ldb, integer *jpvt, real *rcond,
+ integer *rank, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgelsy_(integer *m, integer *n, integer *nrhs, complex *
+ a, integer *lda, complex *b, integer *ldb, integer *jpvt, real *rcond,
+ integer *rank, complex *work, integer *lwork, real *rwork, integer *
+ info);
+
+/* Subroutine */ int cgeql2_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgeqlf_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgeqp3_(integer *m, integer *n, complex *a, integer *lda,
+ integer *jpvt, complex *tau, complex *work, integer *lwork, real *
+ rwork, integer *info);
+
+/* Subroutine */ int cgeqpf_(integer *m, integer *n, complex *a, integer *lda,
+ integer *jpvt, complex *tau, complex *work, real *rwork, integer *
+ info);
+
+/* Subroutine */ int cgeqr2_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgeqrf_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgerfs_(char *trans, integer *n, integer *nrhs, complex *
+ a, integer *lda, complex *af, integer *ldaf, integer *ipiv, complex *
+ b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgerq2_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cgerqf_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgesc2_(integer *n, complex *a, integer *lda, complex *
+ rhs, integer *ipiv, integer *jpiv, real *scale);
+
+/* Subroutine */ int cgesv_(integer *n, integer *nrhs, complex *a, integer *
+ lda, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cgesvx_(char *fact, char *trans, integer *n, integer *
+ nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+ ipiv, char *equed, real *r__, real *c__, complex *b, integer *ldb,
+ complex *x, integer *ldx, real *rcond, real *ferr, real *berr,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgetc2_(integer *n, complex *a, integer *lda, integer *
+ ipiv, integer *jpiv, integer *info);
+
+/* Subroutine */ int cgetf2_(integer *m, integer *n, complex *a, integer *lda,
+ integer *ipiv, integer *info);
+
+/* Subroutine */ int cgetrf_(integer *m, integer *n, complex *a, integer *lda,
+ integer *ipiv, integer *info);
+
+/* Subroutine */ int cgetri_(integer *n, complex *a, integer *lda, integer *
+ ipiv, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgetrs_(char *trans, integer *n, integer *nrhs, complex *
+ a, integer *lda, integer *ipiv, complex *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int cggbak_(char *job, char *side, integer *n, integer *ilo,
+ integer *ihi, real *lscale, real *rscale, integer *m, complex *v,
+ integer *ldv, integer *info);
+
+/* Subroutine */ int cggbal_(char *job, integer *n, complex *a, integer *lda,
+ complex *b, integer *ldb, integer *ilo, integer *ihi, real *lscale,
+ real *rscale, real *work, integer *info);
+
+/* Subroutine */ int cgges_(char *jobvsl, char *jobvsr, char *sort, L_fp
+ selctg, integer *n, complex *a, integer *lda, complex *b, integer *
+ ldb, integer *sdim, complex *alpha, complex *beta, complex *vsl,
+ integer *ldvsl, complex *vsr, integer *ldvsr, complex *work, integer *
+ lwork, real *rwork, logical *bwork, integer *info);
+
+/* Subroutine */ int cggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp
+ selctg, char *sense, integer *n, complex *a, integer *lda, complex *b,
+ integer *ldb, integer *sdim, complex *alpha, complex *beta, complex *
+ vsl, integer *ldvsl, complex *vsr, integer *ldvsr, real *rconde, real
+ *rcondv, complex *work, integer *lwork, real *rwork, integer *iwork,
+ integer *liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int cggev_(char *jobvl, char *jobvr, integer *n, complex *a,
+ integer *lda, complex *b, integer *ldb, complex *alpha, complex *beta,
+ complex *vl, integer *ldvl, complex *vr, integer *ldvr, complex *
+ work, integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int cggevx_(char *balanc, char *jobvl, char *jobvr, char *
+ sense, integer *n, complex *a, integer *lda, complex *b, integer *ldb,
+ complex *alpha, complex *beta, complex *vl, integer *ldvl, complex *
+ vr, integer *ldvr, integer *ilo, integer *ihi, real *lscale, real *
+ rscale, real *abnrm, real *bbnrm, real *rconde, real *rcondv, complex
+ *work, integer *lwork, real *rwork, integer *iwork, logical *bwork,
+ integer *info);
+
+/* Subroutine */ int cggglm_(integer *n, integer *m, integer *p, complex *a,
+ integer *lda, complex *b, integer *ldb, complex *d__, complex *x,
+ complex *y, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cgghrd_(char *compq, char *compz, integer *n, integer *
+ ilo, integer *ihi, complex *a, integer *lda, complex *b, integer *ldb,
+ complex *q, integer *ldq, complex *z__, integer *ldz, integer *info);
+
+/* Subroutine */ int cgglse_(integer *m, integer *n, integer *p, complex *a,
+ integer *lda, complex *b, integer *ldb, complex *c__, complex *d__,
+ complex *x, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cggqrf_(integer *n, integer *m, integer *p, complex *a,
+ integer *lda, complex *taua, complex *b, integer *ldb, complex *taub,
+ complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cggrqf_(integer *m, integer *p, integer *n, complex *a,
+ integer *lda, complex *taua, complex *b, integer *ldb, complex *taub,
+ complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cggsvd_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *n, integer *p, integer *k, integer *l, complex *a, integer *
+ lda, complex *b, integer *ldb, real *alpha, real *beta, complex *u,
+ integer *ldu, complex *v, integer *ldv, complex *q, integer *ldq,
+ complex *work, real *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int cggsvp_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *p, integer *n, complex *a, integer *lda, complex *b, integer
+ *ldb, real *tola, real *tolb, integer *k, integer *l, complex *u,
+ integer *ldu, complex *v, integer *ldv, complex *q, integer *ldq,
+ integer *iwork, real *rwork, complex *tau, complex *work, integer *
+ info);
+
+/* Subroutine */ int cgtcon_(char *norm, integer *n, complex *dl, complex *
+ d__, complex *du, complex *du2, integer *ipiv, real *anorm, real *
+ rcond, complex *work, integer *info);
+
+/* Subroutine */ int cgtrfs_(char *trans, integer *n, integer *nrhs, complex *
+ dl, complex *d__, complex *du, complex *dlf, complex *df, complex *
+ duf, complex *du2, integer *ipiv, complex *b, integer *ldb, complex *
+ x, integer *ldx, real *ferr, real *berr, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int cgtsv_(integer *n, integer *nrhs, complex *dl, complex *
+ d__, complex *du, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cgtsvx_(char *fact, char *trans, integer *n, integer *
+ nrhs, complex *dl, complex *d__, complex *du, complex *dlf, complex *
+ df, complex *duf, complex *du2, integer *ipiv, complex *b, integer *
+ ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cgttrf_(integer *n, complex *dl, complex *d__, complex *
+ du, complex *du2, integer *ipiv, integer *info);
+
+/* Subroutine */ int cgttrs_(char *trans, integer *n, integer *nrhs, complex *
+ dl, complex *d__, complex *du, complex *du2, integer *ipiv, complex *
+ b, integer *ldb, integer *info);
+
+/* Subroutine */ int cgtts2_(integer *itrans, integer *n, integer *nrhs,
+ complex *dl, complex *d__, complex *du, complex *du2, integer *ipiv,
+ complex *b, integer *ldb);
+
+/* Subroutine */ int chbev_(char *jobz, char *uplo, integer *n, integer *kd,
+ complex *ab, integer *ldab, real *w, complex *z__, integer *ldz,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chbevd_(char *jobz, char *uplo, integer *n, integer *kd,
+ complex *ab, integer *ldab, real *w, complex *z__, integer *ldz,
+ complex *work, integer *lwork, real *rwork, integer *lrwork, integer *
+ iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int chbevx_(char *jobz, char *range, char *uplo, integer *n,
+ integer *kd, complex *ab, integer *ldab, complex *q, integer *ldq,
+ real *vl, real *vu, integer *il, integer *iu, real *abstol, integer *
+ m, real *w, complex *z__, integer *ldz, complex *work, real *rwork,
+ integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int chbgst_(char *vect, char *uplo, integer *n, integer *ka,
+ integer *kb, complex *ab, integer *ldab, complex *bb, integer *ldbb,
+ complex *x, integer *ldx, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chbgv_(char *jobz, char *uplo, integer *n, integer *ka,
+ integer *kb, complex *ab, integer *ldab, complex *bb, integer *ldbb,
+ real *w, complex *z__, integer *ldz, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int chbgvx_(char *jobz, char *range, char *uplo, integer *n,
+ integer *ka, integer *kb, complex *ab, integer *ldab, complex *bb,
+ integer *ldbb, complex *q, integer *ldq, real *vl, real *vu, integer *
+ il, integer *iu, real *abstol, integer *m, real *w, complex *z__,
+ integer *ldz, complex *work, real *rwork, integer *iwork, integer *
+ ifail, integer *info);
+
+/* Subroutine */ int chbtrd_(char *vect, char *uplo, integer *n, integer *kd,
+ complex *ab, integer *ldab, real *d__, real *e, complex *q, integer *
+ ldq, complex *work, integer *info);
+
+/* Subroutine */ int checon_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *ipiv, real *anorm, real *rcond, complex *work, integer *
+ info);
+
+/* Subroutine */ int cheev_(char *jobz, char *uplo, integer *n, complex *a,
+ integer *lda, real *w, complex *work, integer *lwork, real *rwork,
+ integer *info);
+
+/* Subroutine */ int cheevd_(char *jobz, char *uplo, integer *n, complex *a,
+ integer *lda, real *w, complex *work, integer *lwork, real *rwork,
+ integer *lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int cheevr_(char *jobz, char *range, char *uplo, integer *n,
+ complex *a, integer *lda, real *vl, real *vu, integer *il, integer *
+ iu, real *abstol, integer *m, real *w, complex *z__, integer *ldz,
+ integer *isuppz, complex *work, integer *lwork, real *rwork, integer *
+ lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int cheevx_(char *jobz, char *range, char *uplo, integer *n,
+ complex *a, integer *lda, real *vl, real *vu, integer *il, integer *
+ iu, real *abstol, integer *m, real *w, complex *z__, integer *ldz,
+ complex *work, integer *lwork, real *rwork, integer *iwork, integer *
+ ifail, integer *info);
+
+/* Subroutine */ int chegs2_(integer *itype, char *uplo, integer *n, complex *
+ a, integer *lda, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int chegst_(integer *itype, char *uplo, integer *n, complex *
+ a, integer *lda, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int chegv_(integer *itype, char *jobz, char *uplo, integer *
+ n, complex *a, integer *lda, complex *b, integer *ldb, real *w,
+ complex *work, integer *lwork, real *rwork, integer *info);
+
+/* Subroutine */ int chegvd_(integer *itype, char *jobz, char *uplo, integer *
+ n, complex *a, integer *lda, complex *b, integer *ldb, real *w,
+ complex *work, integer *lwork, real *rwork, integer *lrwork, integer *
+ iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int chegvx_(integer *itype, char *jobz, char *range, char *
+ uplo, integer *n, complex *a, integer *lda, complex *b, integer *ldb,
+ real *vl, real *vu, integer *il, integer *iu, real *abstol, integer *
+ m, real *w, complex *z__, integer *ldz, complex *work, integer *lwork,
+ real *rwork, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int cherfs_(char *uplo, integer *n, integer *nrhs, complex *
+ a, integer *lda, complex *af, integer *ldaf, integer *ipiv, complex *
+ b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chesv_(char *uplo, integer *n, integer *nrhs, complex *a,
+ integer *lda, integer *ipiv, complex *b, integer *ldb, complex *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int chesvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+ ipiv, complex *b, integer *ldb, complex *x, integer *ldx, real *rcond,
+ real *ferr, real *berr, complex *work, integer *lwork, real *rwork,
+ integer *info);
+
+/* Subroutine */ int chetf2_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *ipiv, integer *info);
+
+/* Subroutine */ int chetrd_(char *uplo, integer *n, complex *a, integer *lda,
+ real *d__, real *e, complex *tau, complex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int chetrf_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *ipiv, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int chetri_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *ipiv, complex *work, integer *info);
+
+/* Subroutine */ int chetrs_(char *uplo, integer *n, integer *nrhs, complex *
+ a, integer *lda, integer *ipiv, complex *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int chgeqz_(char *job, char *compq, char *compz, integer *n,
+ integer *ilo, integer *ihi, complex *a, integer *lda, complex *b,
+ integer *ldb, complex *alpha, complex *beta, complex *q, integer *ldq,
+ complex *z__, integer *ldz, complex *work, integer *lwork, real *
+ rwork, integer *info);
+
+/* Subroutine */ int chpcon_(char *uplo, integer *n, complex *ap, integer *
+ ipiv, real *anorm, real *rcond, complex *work, integer *info);
+
+/* Subroutine */ int chpev_(char *jobz, char *uplo, integer *n, complex *ap,
+ real *w, complex *z__, integer *ldz, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int chpevd_(char *jobz, char *uplo, integer *n, complex *ap,
+ real *w, complex *z__, integer *ldz, complex *work, integer *lwork,
+ real *rwork, integer *lrwork, integer *iwork, integer *liwork,
+ integer *info);
+
+/* Subroutine */ int chpevx_(char *jobz, char *range, char *uplo, integer *n,
+ complex *ap, real *vl, real *vu, integer *il, integer *iu, real *
+ abstol, integer *m, real *w, complex *z__, integer *ldz, complex *
+ work, real *rwork, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int chpgst_(integer *itype, char *uplo, integer *n, complex *
+ ap, complex *bp, integer *info);
+
+/* Subroutine */ int chpgv_(integer *itype, char *jobz, char *uplo, integer *
+ n, complex *ap, complex *bp, real *w, complex *z__, integer *ldz,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chpgvd_(integer *itype, char *jobz, char *uplo, integer *
+ n, complex *ap, complex *bp, real *w, complex *z__, integer *ldz,
+ complex *work, integer *lwork, real *rwork, integer *lrwork, integer *
+ iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int chpgvx_(integer *itype, char *jobz, char *range, char *
+ uplo, integer *n, complex *ap, complex *bp, real *vl, real *vu,
+ integer *il, integer *iu, real *abstol, integer *m, real *w, complex *
+ z__, integer *ldz, complex *work, real *rwork, integer *iwork,
+ integer *ifail, integer *info);
+
+/* Subroutine */ int chprfs_(char *uplo, integer *n, integer *nrhs, complex *
+ ap, complex *afp, integer *ipiv, complex *b, integer *ldb, complex *x,
+ integer *ldx, real *ferr, real *berr, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int chpsv_(char *uplo, integer *n, integer *nrhs, complex *
+ ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int chpsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, complex *ap, complex *afp, integer *ipiv, complex *b, integer *
+ ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int chptrd_(char *uplo, integer *n, complex *ap, real *d__,
+ real *e, complex *tau, integer *info);
+
+/* Subroutine */ int chptrf_(char *uplo, integer *n, complex *ap, integer *
+ ipiv, integer *info);
+
+/* Subroutine */ int chptri_(char *uplo, integer *n, complex *ap, integer *
+ ipiv, complex *work, integer *info);
+
+/* Subroutine */ int chptrs_(char *uplo, integer *n, integer *nrhs, complex *
+ ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int chsein_(char *side, char *eigsrc, char *initv, logical *
+ select, integer *n, complex *h__, integer *ldh, complex *w, complex *
+ vl, integer *ldvl, complex *vr, integer *ldvr, integer *mm, integer *
+ m, complex *work, real *rwork, integer *ifaill, integer *ifailr,
+ integer *info);
+
+/* Subroutine */ int chseqr_(char *job, char *compz, integer *n, integer *ilo,
+ integer *ihi, complex *h__, integer *ldh, complex *w, complex *z__,
+ integer *ldz, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int clabrd_(integer *m, integer *n, integer *nb, complex *a,
+ integer *lda, real *d__, real *e, complex *tauq, complex *taup,
+ complex *x, integer *ldx, complex *y, integer *ldy);
+
+/* Subroutine */ int clacgv_(integer *n, complex *x, integer *incx);
+
+/* Subroutine */ int clacon_(integer *n, complex *v, complex *x, real *est,
+ integer *kase);
+
+/* Subroutine */ int clacp2_(char *uplo, integer *m, integer *n, real *a,
+ integer *lda, complex *b, integer *ldb);
+
+/* Subroutine */ int clacpy_(char *uplo, integer *m, integer *n, complex *a,
+ integer *lda, complex *b, integer *ldb);
+
+/* Subroutine */ int clacrm_(integer *m, integer *n, complex *a, integer *lda,
+ real *b, integer *ldb, complex *c__, integer *ldc, real *rwork);
+
+/* Subroutine */ int clacrt_(integer *n, complex *cx, integer *incx, complex *
+ cy, integer *incy, complex *c__, complex *s);
+
+/* Subroutine */ int claed0_(integer *qsiz, integer *n, real *d__, real *e,
+ complex *q, integer *ldq, complex *qstore, integer *ldqs, real *rwork,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int claed7_(integer *n, integer *cutpnt, integer *qsiz,
+ integer *tlvls, integer *curlvl, integer *curpbm, real *d__, complex *
+ q, integer *ldq, real *rho, integer *indxq, real *qstore, integer *
+ qptr, integer *prmptr, integer *perm, integer *givptr, integer *
+ givcol, real *givnum, complex *work, real *rwork, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int claed8_(integer *k, integer *n, integer *qsiz, complex *
+ q, integer *ldq, real *d__, real *rho, integer *cutpnt, real *z__,
+ real *dlamda, complex *q2, integer *ldq2, real *w, integer *indxp,
+ integer *indx, integer *indxq, integer *perm, integer *givptr,
+ integer *givcol, real *givnum, integer *info);
+
+/* Subroutine */ int claein_(logical *rightv, logical *noinit, integer *n,
+ complex *h__, integer *ldh, complex *w, complex *v, complex *b,
+ integer *ldb, real *rwork, real *eps3, real *smlnum, integer *info);
+
+/* Subroutine */ int claesy_(complex *a, complex *b, complex *c__, complex *
+ rt1, complex *rt2, complex *evscal, complex *cs1, complex *sn1);
+
+/* Subroutine */ int claev2_(complex *a, complex *b, complex *c__, real *rt1,
+ real *rt2, real *cs1, complex *sn1);
+
+/* Subroutine */ int clags2_(logical *upper, real *a1, complex *a2, real *a3,
+ real *b1, complex *b2, real *b3, real *csu, complex *snu, real *csv,
+ complex *snv, real *csq, complex *snq);
+
+/* Subroutine */ int clagtm_(char *trans, integer *n, integer *nrhs, real *
+ alpha, complex *dl, complex *d__, complex *du, complex *x, integer *
+ ldx, real *beta, complex *b, integer *ldb);
+
+/* Subroutine */ int clahef_(char *uplo, integer *n, integer *nb, integer *kb,
+ complex *a, integer *lda, integer *ipiv, complex *w, integer *ldw,
+ integer *info);
+
+/* Subroutine */ int clahqr_(logical *wantt, logical *wantz, integer *n,
+ integer *ilo, integer *ihi, complex *h__, integer *ldh, complex *w,
+ integer *iloz, integer *ihiz, complex *z__, integer *ldz, integer *
+ info);
+
+/* Subroutine */ int clahrd_(integer *n, integer *k, integer *nb, complex *a,
+ integer *lda, complex *tau, complex *t, integer *ldt, complex *y,
+ integer *ldy);
+
+/* Subroutine */ int claic1_(integer *job, integer *j, complex *x, real *sest,
+ complex *w, complex *gamma, real *sestpr, complex *s, complex *c__);
+
+/* Subroutine */ int clals0_(integer *icompq, integer *nl, integer *nr,
+ integer *sqre, integer *nrhs, complex *b, integer *ldb, complex *bx,
+ integer *ldbx, integer *perm, integer *givptr, integer *givcol,
+ integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
+ difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
+ rwork, integer *info);
+
+/* Subroutine */ int clalsa_(integer *icompq, integer *smlsiz, integer *n,
+ integer *nrhs, complex *b, integer *ldb, complex *bx, integer *ldbx,
+ real *u, integer *ldu, real *vt, integer *k, real *difl, real *difr,
+ real *z__, real *poles, integer *givptr, integer *givcol, integer *
+ ldgcol, integer *perm, real *givnum, real *c__, real *s, real *rwork,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int clapll_(integer *n, complex *x, integer *incx, complex *
+ y, integer *incy, real *ssmin);
+
+/* Subroutine */ int clapmt_(logical *forwrd, integer *m, integer *n, complex
+ *x, integer *ldx, integer *k);
+
+/* Subroutine */ int claqgb_(integer *m, integer *n, integer *kl, integer *ku,
+ complex *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real
+ *colcnd, real *amax, char *equed);
+
+/* Subroutine */ int claqge_(integer *m, integer *n, complex *a, integer *lda,
+ real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, char *
+ equed);
+
+/* Subroutine */ int claqhb_(char *uplo, integer *n, integer *kd, complex *ab,
+ integer *ldab, real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqhe_(char *uplo, integer *n, complex *a, integer *lda,
+ real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqhp_(char *uplo, integer *n, complex *ap, real *s,
+ real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqp2_(integer *m, integer *n, integer *offset, complex
+ *a, integer *lda, integer *jpvt, complex *tau, real *vn1, real *vn2,
+ complex *work);
+
+/* Subroutine */ int claqps_(integer *m, integer *n, integer *offset, integer
+ *nb, integer *kb, complex *a, integer *lda, integer *jpvt, complex *
+ tau, real *vn1, real *vn2, complex *auxv, complex *f, integer *ldf);
+
+/* Subroutine */ int claqsb_(char *uplo, integer *n, integer *kd, complex *ab,
+ integer *ldab, real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqsp_(char *uplo, integer *n, complex *ap, real *s,
+ real *scond, real *amax, char *equed);
+
+/* Subroutine */ int claqsy_(char *uplo, integer *n, complex *a, integer *lda,
+ real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int clar1v_(integer *n, integer *b1, integer *bn, real *
+ sigma, real *d__, real *l, real *ld, real *lld, real *gersch, complex
+ *z__, real *ztz, real *mingma, integer *r__, integer *isuppz, real *
+ work);
+
+/* Subroutine */ int clar2v_(integer *n, complex *x, complex *y, complex *z__,
+ integer *incx, real *c__, complex *s, integer *incc);
+
+/* Subroutine */ int clarcm_(integer *m, integer *n, real *a, integer *lda,
+ complex *b, integer *ldb, complex *c__, integer *ldc, real *rwork);
+
+/* Subroutine */ int clarf_(char *side, integer *m, integer *n, complex *v,
+ integer *incv, complex *tau, complex *c__, integer *ldc, complex *
+ work);
+
+/* Subroutine */ int clarfb_(char *side, char *trans, char *direct, char *
+ storev, integer *m, integer *n, integer *k, complex *v, integer *ldv,
+ complex *t, integer *ldt, complex *c__, integer *ldc, complex *work,
+ integer *ldwork);
+
+/* Subroutine */ int clarfg_(integer *n, complex *alpha, complex *x, integer *
+ incx, complex *tau);
+
+/* Subroutine */ int clarft_(char *direct, char *storev, integer *n, integer *
+ k, complex *v, integer *ldv, complex *tau, complex *t, integer *ldt);
+
+/* Subroutine */ int clarfx_(char *side, integer *m, integer *n, complex *v,
+ complex *tau, complex *c__, integer *ldc, complex *work);
+
+/* Subroutine */ int clargv_(integer *n, complex *x, integer *incx, complex *
+ y, integer *incy, real *c__, integer *incc);
+
+/* Subroutine */ int clarnv_(integer *idist, integer *iseed, integer *n,
+ complex *x);
+
+/* Subroutine */ int clarrv_(integer *n, real *d__, real *l, integer *isplit,
+ integer *m, real *w, integer *iblock, real *gersch, real *tol,
+ complex *z__, integer *ldz, integer *isuppz, real *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int clartg_(complex *f, complex *g, real *cs, complex *sn,
+ complex *r__);
+
+/* Subroutine */ int clartv_(integer *n, complex *x, integer *incx, complex *
+ y, integer *incy, real *c__, complex *s, integer *incc);
+
+/* Subroutine */ int clarz_(char *side, integer *m, integer *n, integer *l,
+ complex *v, integer *incv, complex *tau, complex *c__, integer *ldc,
+ complex *work);
+
+/* Subroutine */ int clarzb_(char *side, char *trans, char *direct, char *
+ storev, integer *m, integer *n, integer *k, integer *l, complex *v,
+ integer *ldv, complex *t, integer *ldt, complex *c__, integer *ldc,
+ complex *work, integer *ldwork);
+
+/* Subroutine */ int clarzt_(char *direct, char *storev, integer *n, integer *
+ k, complex *v, integer *ldv, complex *tau, complex *t, integer *ldt);
+
+/* Subroutine */ int clascl_(char *type__, integer *kl, integer *ku, real *
+ cfrom, real *cto, integer *m, integer *n, complex *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int claset_(char *uplo, integer *m, integer *n, complex *
+ alpha, complex *beta, complex *a, integer *lda);
+
+/* Subroutine */ int clasr_(char *side, char *pivot, char *direct, integer *m,
+ integer *n, real *c__, real *s, complex *a, integer *lda);
+
+/* Subroutine */ int classq_(integer *n, complex *x, integer *incx, real *
+ scale, real *sumsq);
+
+/* Subroutine */ int claswp_(integer *n, complex *a, integer *lda, integer *
+ k1, integer *k2, integer *ipiv, integer *incx);
+
+/* Subroutine */ int clasyf_(char *uplo, integer *n, integer *nb, integer *kb,
+ complex *a, integer *lda, integer *ipiv, complex *w, integer *ldw,
+ integer *info);
+
+/* Subroutine */ int clatbs_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, integer *kd, complex *ab, integer *ldab, complex *
+ x, real *scale, real *cnorm, integer *info);
+
+/* Subroutine */ int clatdf_(integer *ijob, integer *n, complex *z__, integer
+ *ldz, complex *rhs, real *rdsum, real *rdscal, integer *ipiv, integer
+ *jpiv);
+
+/* Subroutine */ int clatps_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, complex *ap, complex *x, real *scale, real *cnorm,
+ integer *info);
+
+/* Subroutine */ int clatrd_(char *uplo, integer *n, integer *nb, complex *a,
+ integer *lda, real *e, complex *tau, complex *w, integer *ldw);
+
+/* Subroutine */ int clatrs_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, complex *a, integer *lda, complex *x, real *scale,
+ real *cnorm, integer *info);
+
+/* Subroutine */ int clatrz_(integer *m, integer *n, integer *l, complex *a,
+ integer *lda, complex *tau, complex *work);
+
+/* Subroutine */ int clatzm_(char *side, integer *m, integer *n, complex *v,
+ integer *incv, complex *tau, complex *c1, complex *c2, integer *ldc,
+ complex *work);
+
+/* Subroutine */ int clauu2_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int clauum_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int cpbcon_(char *uplo, integer *n, integer *kd, complex *ab,
+ integer *ldab, real *anorm, real *rcond, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int cpbequ_(char *uplo, integer *n, integer *kd, complex *ab,
+ integer *ldab, real *s, real *scond, real *amax, integer *info);
+
+/* Subroutine */ int cpbrfs_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, complex *ab, integer *ldab, complex *afb, integer *ldafb,
+ complex *b, integer *ldb, complex *x, integer *ldx, real *ferr, real *
+ berr, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cpbstf_(char *uplo, integer *n, integer *kd, complex *ab,
+ integer *ldab, integer *info);
+
+/* Subroutine */ int cpbsv_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, complex *ab, integer *ldab, complex *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int cpbsvx_(char *fact, char *uplo, integer *n, integer *kd,
+ integer *nrhs, complex *ab, integer *ldab, complex *afb, integer *
+ ldafb, char *equed, real *s, complex *b, integer *ldb, complex *x,
+ integer *ldx, real *rcond, real *ferr, real *berr, complex *work,
+ real *rwork, integer *info);
+
+/* Subroutine */ int cpbtf2_(char *uplo, integer *n, integer *kd, complex *ab,
+ integer *ldab, integer *info);
+
+/* Subroutine */ int cpbtrf_(char *uplo, integer *n, integer *kd, complex *ab,
+ integer *ldab, integer *info);
+
+/* Subroutine */ int cpbtrs_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, complex *ab, integer *ldab, complex *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int cpocon_(char *uplo, integer *n, complex *a, integer *lda,
+ real *anorm, real *rcond, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cpoequ_(integer *n, complex *a, integer *lda, real *s,
+ real *scond, real *amax, integer *info);
+
+/* Subroutine */ int cporfs_(char *uplo, integer *n, integer *nrhs, complex *
+ a, integer *lda, complex *af, integer *ldaf, complex *b, integer *ldb,
+ complex *x, integer *ldx, real *ferr, real *berr, complex *work,
+ real *rwork, integer *info);
+
+/* Subroutine */ int cposv_(char *uplo, integer *n, integer *nrhs, complex *a,
+ integer *lda, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cposvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, complex *a, integer *lda, complex *af, integer *ldaf, char *
+ equed, real *s, complex *b, integer *ldb, complex *x, integer *ldx,
+ real *rcond, real *ferr, real *berr, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int cpotf2_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int cpotrf_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int cpotri_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int cpotrs_(char *uplo, integer *n, integer *nrhs, complex *
+ a, integer *lda, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cppcon_(char *uplo, integer *n, complex *ap, real *anorm,
+ real *rcond, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cppequ_(char *uplo, integer *n, complex *ap, real *s,
+ real *scond, real *amax, integer *info);
+
+/* Subroutine */ int cpprfs_(char *uplo, integer *n, integer *nrhs, complex *
+ ap, complex *afp, complex *b, integer *ldb, complex *x, integer *ldx,
+ real *ferr, real *berr, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cppsv_(char *uplo, integer *n, integer *nrhs, complex *
+ ap, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cppsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, complex *ap, complex *afp, char *equed, real *s, complex *b,
+ integer *ldb, complex *x, integer *ldx, real *rcond, real *ferr, real
+ *berr, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int cpptrf_(char *uplo, integer *n, complex *ap, integer *
+ info);
+
+/* Subroutine */ int cpptri_(char *uplo, integer *n, complex *ap, integer *
+ info);
+
+/* Subroutine */ int cpptrs_(char *uplo, integer *n, integer *nrhs, complex *
+ ap, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cptcon_(integer *n, real *d__, complex *e, real *anorm,
+ real *rcond, real *rwork, integer *info);
+
+/* Subroutine */ int cptrfs_(char *uplo, integer *n, integer *nrhs, real *d__,
+ complex *e, real *df, complex *ef, complex *b, integer *ldb, complex
+ *x, integer *ldx, real *ferr, real *berr, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int cptsv_(integer *n, integer *nrhs, real *d__, complex *e,
+ complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cptsvx_(char *fact, integer *n, integer *nrhs, real *d__,
+ complex *e, real *df, complex *ef, complex *b, integer *ldb, complex
+ *x, integer *ldx, real *rcond, real *ferr, real *berr, complex *work,
+ real *rwork, integer *info);
+
+/* Subroutine */ int cpttrf_(integer *n, real *d__, complex *e, integer *info);
+
+/* Subroutine */ int cpttrs_(char *uplo, integer *n, integer *nrhs, real *d__,
+ complex *e, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cptts2_(integer *iuplo, integer *n, integer *nrhs, real *
+ d__, complex *e, complex *b, integer *ldb);
+
+/* Subroutine */ int crot_(integer *n, complex *cx, integer *incx, complex *
+ cy, integer *incy, real *c__, complex *s);
+
+/* Subroutine */ int cspcon_(char *uplo, integer *n, complex *ap, integer *
+ ipiv, real *anorm, real *rcond, complex *work, integer *info);
+
+/* Subroutine */ int cspmv_(char *uplo, integer *n, complex *alpha, complex *
+ ap, complex *x, integer *incx, complex *beta, complex *y, integer *
+ incy);
+
+/* Subroutine */ int cspr_(char *uplo, integer *n, complex *alpha, complex *x,
+ integer *incx, complex *ap);
+
+/* Subroutine */ int csprfs_(char *uplo, integer *n, integer *nrhs, complex *
+ ap, complex *afp, integer *ipiv, complex *b, integer *ldb, complex *x,
+ integer *ldx, real *ferr, real *berr, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int cspsv_(char *uplo, integer *n, integer *nrhs, complex *
+ ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int cspsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, complex *ap, complex *afp, integer *ipiv, complex *b, integer *
+ ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int csptrf_(char *uplo, integer *n, complex *ap, integer *
+ ipiv, integer *info);
+
+/* Subroutine */ int csptri_(char *uplo, integer *n, complex *ap, integer *
+ ipiv, complex *work, integer *info);
+
+/* Subroutine */ int csptrs_(char *uplo, integer *n, integer *nrhs, complex *
+ ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int csrot_(integer *n, complex *cx, integer *incx, complex *
+ cy, integer *incy, real *c__, real *s);
+
+/* Subroutine */ int csrscl_(integer *n, real *sa, complex *sx, integer *incx);
+
+/* Subroutine */ int cstedc_(char *compz, integer *n, real *d__, real *e,
+ complex *z__, integer *ldz, complex *work, integer *lwork, real *
+ rwork, integer *lrwork, integer *iwork, integer *liwork, integer *
+ info);
+
+/* Subroutine */ int cstein_(integer *n, real *d__, real *e, integer *m, real
+ *w, integer *iblock, integer *isplit, complex *z__, integer *ldz,
+ real *work, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int csteqr_(char *compz, integer *n, real *d__, real *e,
+ complex *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int csycon_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *ipiv, real *anorm, real *rcond, complex *work, integer *
+ info);
+
+/* Subroutine */ int csymv_(char *uplo, integer *n, complex *alpha, complex *
+ a, integer *lda, complex *x, integer *incx, complex *beta, complex *y,
+ integer *incy);
+
+/* Subroutine */ int csyr_(char *uplo, integer *n, complex *alpha, complex *x,
+ integer *incx, complex *a, integer *lda);
+
+/* Subroutine */ int csyrfs_(char *uplo, integer *n, integer *nrhs, complex *
+ a, integer *lda, complex *af, integer *ldaf, integer *ipiv, complex *
+ b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int csysv_(char *uplo, integer *n, integer *nrhs, complex *a,
+ integer *lda, integer *ipiv, complex *b, integer *ldb, complex *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int csysvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+ ipiv, complex *b, integer *ldb, complex *x, integer *ldx, real *rcond,
+ real *ferr, real *berr, complex *work, integer *lwork, real *rwork,
+ integer *info);
+
+/* Subroutine */ int csytf2_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *ipiv, integer *info);
+
+/* Subroutine */ int csytrf_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *ipiv, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int csytri_(char *uplo, integer *n, complex *a, integer *lda,
+ integer *ipiv, complex *work, integer *info);
+
+/* Subroutine */ int csytrs_(char *uplo, integer *n, integer *nrhs, complex *
+ a, integer *lda, integer *ipiv, complex *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int ctbcon_(char *norm, char *uplo, char *diag, integer *n,
+ integer *kd, complex *ab, integer *ldab, real *rcond, complex *work,
+ real *rwork, integer *info);
+
+/* Subroutine */ int ctbrfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *kd, integer *nrhs, complex *ab, integer *ldab, complex *b,
+ integer *ldb, complex *x, integer *ldx, real *ferr, real *berr,
+ complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int ctbtrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *kd, integer *nrhs, complex *ab, integer *ldab, complex *b,
+ integer *ldb, integer *info);
+
+/* Subroutine */ int ctgevc_(char *side, char *howmny, logical *select,
+ integer *n, complex *a, integer *lda, complex *b, integer *ldb,
+ complex *vl, integer *ldvl, complex *vr, integer *ldvr, integer *mm,
+ integer *m, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int ctgex2_(logical *wantq, logical *wantz, integer *n,
+ complex *a, integer *lda, complex *b, integer *ldb, complex *q,
+ integer *ldq, complex *z__, integer *ldz, integer *j1, integer *info);
+
+/* Subroutine */ int ctgexc_(logical *wantq, logical *wantz, integer *n,
+ complex *a, integer *lda, complex *b, integer *ldb, complex *q,
+ integer *ldq, complex *z__, integer *ldz, integer *ifst, integer *
+ ilst, integer *info);
+
+/* Subroutine */ int ctgsen_(integer *ijob, logical *wantq, logical *wantz,
+ logical *select, integer *n, complex *a, integer *lda, complex *b,
+ integer *ldb, complex *alpha, complex *beta, complex *q, integer *ldq,
+ complex *z__, integer *ldz, integer *m, real *pl, real *pr, real *
+ dif, complex *work, integer *lwork, integer *iwork, integer *liwork,
+ integer *info);
+
+/* Subroutine */ int ctgsja_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *p, integer *n, integer *k, integer *l, complex *a, integer *
+ lda, complex *b, integer *ldb, real *tola, real *tolb, real *alpha,
+ real *beta, complex *u, integer *ldu, complex *v, integer *ldv,
+ complex *q, integer *ldq, complex *work, integer *ncycle, integer *
+ info);
+
+/* Subroutine */ int ctgsna_(char *job, char *howmny, logical *select,
+ integer *n, complex *a, integer *lda, complex *b, integer *ldb,
+ complex *vl, integer *ldvl, complex *vr, integer *ldvr, real *s, real
+ *dif, integer *mm, integer *m, complex *work, integer *lwork, integer
+ *iwork, integer *info);
+
+/* Subroutine */ int ctgsy2_(char *trans, integer *ijob, integer *m, integer *
+ n, complex *a, integer *lda, complex *b, integer *ldb, complex *c__,
+ integer *ldc, complex *d__, integer *ldd, complex *e, integer *lde,
+ complex *f, integer *ldf, real *scale, real *rdsum, real *rdscal,
+ integer *info);
+
+/* Subroutine */ int ctgsyl_(char *trans, integer *ijob, integer *m, integer *
+ n, complex *a, integer *lda, complex *b, integer *ldb, complex *c__,
+ integer *ldc, complex *d__, integer *ldd, complex *e, integer *lde,
+ complex *f, integer *ldf, real *scale, real *dif, complex *work,
+ integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int ctpcon_(char *norm, char *uplo, char *diag, integer *n,
+ complex *ap, real *rcond, complex *work, real *rwork, integer *info);
+
+/* Subroutine */ int ctprfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, complex *ap, complex *b, integer *ldb, complex *x,
+ integer *ldx, real *ferr, real *berr, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int ctptri_(char *uplo, char *diag, integer *n, complex *ap,
+ integer *info);
+
+/* Subroutine */ int ctptrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, complex *ap, complex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int ctrcon_(char *norm, char *uplo, char *diag, integer *n,
+ complex *a, integer *lda, real *rcond, complex *work, real *rwork,
+ integer *info);
+
+/* Subroutine */ int ctrevc_(char *side, char *howmny, logical *select,
+ integer *n, complex *t, integer *ldt, complex *vl, integer *ldvl,
+ complex *vr, integer *ldvr, integer *mm, integer *m, complex *work,
+ real *rwork, integer *info);
+
+/* Subroutine */ int ctrexc_(char *compq, integer *n, complex *t, integer *
+ ldt, complex *q, integer *ldq, integer *ifst, integer *ilst, integer *
+ info);
+
+/* Subroutine */ int ctrrfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, complex *a, integer *lda, complex *b, integer *ldb,
+ complex *x, integer *ldx, real *ferr, real *berr, complex *work, real
+ *rwork, integer *info);
+
+/* Subroutine */ int ctrsen_(char *job, char *compq, logical *select, integer
+ *n, complex *t, integer *ldt, complex *q, integer *ldq, complex *w,
+ integer *m, real *s, real *sep, complex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int ctrsna_(char *job, char *howmny, logical *select,
+ integer *n, complex *t, integer *ldt, complex *vl, integer *ldvl,
+ complex *vr, integer *ldvr, real *s, real *sep, integer *mm, integer *
+ m, complex *work, integer *ldwork, real *rwork, integer *info);
+
+/* Subroutine */ int ctrsyl_(char *trana, char *tranb, integer *isgn, integer
+ *m, integer *n, complex *a, integer *lda, complex *b, integer *ldb,
+ complex *c__, integer *ldc, real *scale, integer *info);
+
+/* Subroutine */ int ctrti2_(char *uplo, char *diag, integer *n, complex *a,
+ integer *lda, integer *info);
+
+/* Subroutine */ int ctrtri_(char *uplo, char *diag, integer *n, complex *a,
+ integer *lda, integer *info);
+
+/* Subroutine */ int ctrtrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, complex *a, integer *lda, complex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int ctzrqf_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, integer *info);
+
+/* Subroutine */ int ctzrzf_(integer *m, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cung2l_(integer *m, integer *n, integer *k, complex *a,
+ integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cung2r_(integer *m, integer *n, integer *k, complex *a,
+ integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cungbr_(char *vect, integer *m, integer *n, integer *k,
+ complex *a, integer *lda, complex *tau, complex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int cunghr_(integer *n, integer *ilo, integer *ihi, complex *
+ a, integer *lda, complex *tau, complex *work, integer *lwork, integer
+ *info);
+
+/* Subroutine */ int cungl2_(integer *m, integer *n, integer *k, complex *a,
+ integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cunglq_(integer *m, integer *n, integer *k, complex *a,
+ integer *lda, complex *tau, complex *work, integer *lwork, integer *
+ info);
+
+/* Subroutine */ int cungql_(integer *m, integer *n, integer *k, complex *a,
+ integer *lda, complex *tau, complex *work, integer *lwork, integer *
+ info);
+
+/* Subroutine */ int cungqr_(integer *m, integer *n, integer *k, complex *a,
+ integer *lda, complex *tau, complex *work, integer *lwork, integer *
+ info);
+
+/* Subroutine */ int cungr2_(integer *m, integer *n, integer *k, complex *a,
+ integer *lda, complex *tau, complex *work, integer *info);
+
+/* Subroutine */ int cungrq_(integer *m, integer *n, integer *k, complex *a,
+ integer *lda, complex *tau, complex *work, integer *lwork, integer *
+ info);
+
+/* Subroutine */ int cungtr_(char *uplo, integer *n, complex *a, integer *lda,
+ complex *tau, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunm2l_(char *side, char *trans, integer *m, integer *n,
+ integer *k, complex *a, integer *lda, complex *tau, complex *c__,
+ integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunm2r_(char *side, char *trans, integer *m, integer *n,
+ integer *k, complex *a, integer *lda, complex *tau, complex *c__,
+ integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunmbr_(char *vect, char *side, char *trans, integer *m,
+ integer *n, integer *k, complex *a, integer *lda, complex *tau,
+ complex *c__, integer *ldc, complex *work, integer *lwork, integer *
+ info);
+
+/* Subroutine */ int cunmhr_(char *side, char *trans, integer *m, integer *n,
+ integer *ilo, integer *ihi, complex *a, integer *lda, complex *tau,
+ complex *c__, integer *ldc, complex *work, integer *lwork, integer *
+ info);
+
+/* Subroutine */ int cunml2_(char *side, char *trans, integer *m, integer *n,
+ integer *k, complex *a, integer *lda, complex *tau, complex *c__,
+ integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunmlq_(char *side, char *trans, integer *m, integer *n,
+ integer *k, complex *a, integer *lda, complex *tau, complex *c__,
+ integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunmql_(char *side, char *trans, integer *m, integer *n,
+ integer *k, complex *a, integer *lda, complex *tau, complex *c__,
+ integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunmqr_(char *side, char *trans, integer *m, integer *n,
+ integer *k, complex *a, integer *lda, complex *tau, complex *c__,
+ integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunmr2_(char *side, char *trans, integer *m, integer *n,
+ integer *k, complex *a, integer *lda, complex *tau, complex *c__,
+ integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunmr3_(char *side, char *trans, integer *m, integer *n,
+ integer *k, integer *l, complex *a, integer *lda, complex *tau,
+ complex *c__, integer *ldc, complex *work, integer *info);
+
+/* Subroutine */ int cunmrq_(char *side, char *trans, integer *m, integer *n,
+ integer *k, complex *a, integer *lda, complex *tau, complex *c__,
+ integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cunmrz_(char *side, char *trans, integer *m, integer *n,
+ integer *k, integer *l, complex *a, integer *lda, complex *tau,
+ complex *c__, integer *ldc, complex *work, integer *lwork, integer *
+ info);
+
+/* Subroutine */ int cunmtr_(char *side, char *uplo, char *trans, integer *m,
+ integer *n, complex *a, integer *lda, complex *tau, complex *c__,
+ integer *ldc, complex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int cupgtr_(char *uplo, integer *n, complex *ap, complex *
+ tau, complex *q, integer *ldq, complex *work, integer *info);
+
+/* Subroutine */ int cupmtr_(char *side, char *uplo, char *trans, integer *m,
+ integer *n, complex *ap, complex *tau, complex *c__, integer *ldc,
+ complex *work, integer *info);
+
+/* Subroutine */ int dbdsdc_(char *uplo, char *compq, integer *n, doublereal *
+ d__, doublereal *e, doublereal *u, integer *ldu, doublereal *vt,
+ integer *ldvt, doublereal *q, integer *iq, doublereal *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+ nru, integer *ncc, doublereal *d__, doublereal *e, doublereal *vt,
+ integer *ldvt, doublereal *u, integer *ldu, doublereal *c__, integer *
+ ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int ddisna_(char *job, integer *m, integer *n, doublereal *
+ d__, doublereal *sep, integer *info);
+
+/* Subroutine */ int dgbbrd_(char *vect, integer *m, integer *n, integer *ncc,
+ integer *kl, integer *ku, doublereal *ab, integer *ldab, doublereal *
+ d__, doublereal *e, doublereal *q, integer *ldq, doublereal *pt,
+ integer *ldpt, doublereal *c__, integer *ldc, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int dgbcon_(char *norm, integer *n, integer *kl, integer *ku,
+ doublereal *ab, integer *ldab, integer *ipiv, doublereal *anorm,
+ doublereal *rcond, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dgbequ_(integer *m, integer *n, integer *kl, integer *ku,
+ doublereal *ab, integer *ldab, doublereal *r__, doublereal *c__,
+ doublereal *rowcnd, doublereal *colcnd, doublereal *amax, integer *
+ info);
+
+/* Subroutine */ int dgbrfs_(char *trans, integer *n, integer *kl, integer *
+ ku, integer *nrhs, doublereal *ab, integer *ldab, doublereal *afb,
+ integer *ldafb, integer *ipiv, doublereal *b, integer *ldb,
+ doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr,
+ doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dgbsv_(integer *n, integer *kl, integer *ku, integer *
+ nrhs, doublereal *ab, integer *ldab, integer *ipiv, doublereal *b,
+ integer *ldb, integer *info);
+
+/* Subroutine */ int dgbsvx_(char *fact, char *trans, integer *n, integer *kl,
+ integer *ku, integer *nrhs, doublereal *ab, integer *ldab,
+ doublereal *afb, integer *ldafb, integer *ipiv, char *equed,
+ doublereal *r__, doublereal *c__, doublereal *b, integer *ldb,
+ doublereal *x, integer *ldx, doublereal *rcond, doublereal *ferr,
+ doublereal *berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dgbtf2_(integer *m, integer *n, integer *kl, integer *ku,
+ doublereal *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgbtrf_(integer *m, integer *n, integer *kl, integer *ku,
+ doublereal *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgbtrs_(char *trans, integer *n, integer *kl, integer *
+ ku, integer *nrhs, doublereal *ab, integer *ldab, integer *ipiv,
+ doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dgebak_(char *job, char *side, integer *n, integer *ilo,
+ integer *ihi, doublereal *scale, integer *m, doublereal *v, integer *
+ ldv, integer *info);
+
+/* Subroutine */ int dgebal_(char *job, integer *n, doublereal *a, integer *
+ lda, integer *ilo, integer *ihi, doublereal *scale, integer *info);
+
+/* Subroutine */ int dgebd2_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *d__, doublereal *e, doublereal *tauq, doublereal *
+ taup, doublereal *work, integer *info);
+
+/* Subroutine */ int dgebrd_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *d__, doublereal *e, doublereal *tauq, doublereal *
+ taup, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgecon_(char *norm, integer *n, doublereal *a, integer *
+ lda, doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dgeequ_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, doublereal
+ *colcnd, doublereal *amax, integer *info);
+
+/* Subroutine */ int dgees_(char *jobvs, char *sort, L_fp select, integer *n,
+ doublereal *a, integer *lda, integer *sdim, doublereal *wr,
+ doublereal *wi, doublereal *vs, integer *ldvs, doublereal *work,
+ integer *lwork, logical *bwork, integer *info);
+
+/* Subroutine */ int dgeesx_(char *jobvs, char *sort, L_fp select, char *
+ sense, integer *n, doublereal *a, integer *lda, integer *sdim,
+ doublereal *wr, doublereal *wi, doublereal *vs, integer *ldvs,
+ doublereal *rconde, doublereal *rcondv, doublereal *work, integer *
+ lwork, integer *iwork, integer *liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int dgeev_(char *jobvl, char *jobvr, integer *n, doublereal *
+ a, integer *lda, doublereal *wr, doublereal *wi, doublereal *vl,
+ integer *ldvl, doublereal *vr, integer *ldvr, doublereal *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int dgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+ sense, integer *n, doublereal *a, integer *lda, doublereal *wr,
+ doublereal *wi, doublereal *vl, integer *ldvl, doublereal *vr,
+ integer *ldvr, integer *ilo, integer *ihi, doublereal *scale,
+ doublereal *abnrm, doublereal *rconde, doublereal *rcondv, doublereal
+ *work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int dgegs_(char *jobvsl, char *jobvsr, integer *n,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+ alphar, doublereal *alphai, doublereal *beta, doublereal *vsl,
+ integer *ldvsl, doublereal *vsr, integer *ldvsr, doublereal *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int dgegv_(char *jobvl, char *jobvr, integer *n, doublereal *
+ a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar,
+ doublereal *alphai, doublereal *beta, doublereal *vl, integer *ldvl,
+ doublereal *vr, integer *ldvr, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dgehd2_(integer *n, integer *ilo, integer *ihi,
+ doublereal *a, integer *lda, doublereal *tau, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int dgehrd_(integer *n, integer *ilo, integer *ihi,
+ doublereal *a, integer *lda, doublereal *tau, doublereal *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int dgelq2_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgelqf_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgels_(char *trans, integer *m, integer *n, integer *
+ nrhs, doublereal *a, integer *lda, doublereal *b, integer *ldb,
+ doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgelsd_(integer *m, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+ s, doublereal *rcond, integer *rank, doublereal *work, integer *lwork,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int dgelss_(integer *m, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+ s, doublereal *rcond, integer *rank, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dgelsx_(integer *m, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+ jpvt, doublereal *rcond, integer *rank, doublereal *work, integer *
+ info);
+
+/* Subroutine */ int dgelsy_(integer *m, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+ jpvt, doublereal *rcond, integer *rank, doublereal *work, integer *
+ lwork, integer *info);
+
+/* Subroutine */ int dgeql2_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgeqlf_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgeqp3_(integer *m, integer *n, doublereal *a, integer *
+ lda, integer *jpvt, doublereal *tau, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dgeqpf_(integer *m, integer *n, doublereal *a, integer *
+ lda, integer *jpvt, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgeqr2_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgeqrf_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgerfs_(char *trans, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, doublereal *af, integer *ldaf, integer *
+ ipiv, doublereal *b, integer *ldb, doublereal *x, integer *ldx,
+ doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int dgerq2_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dgerqf_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgesc2_(integer *n, doublereal *a, integer *lda,
+ doublereal *rhs, integer *ipiv, integer *jpiv, doublereal *scale);
+
+/* Subroutine */ int dgesdd_(char *jobz, integer *m, integer *n, doublereal *
+ a, integer *lda, doublereal *s, doublereal *u, integer *ldu,
+ doublereal *vt, integer *ldvt, doublereal *work, integer *lwork,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int dgesv_(integer *n, integer *nrhs, doublereal *a, integer
+ *lda, integer *ipiv, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dgesvd_(char *jobu, char *jobvt, integer *m, integer *n,
+ doublereal *a, integer *lda, doublereal *s, doublereal *u, integer *
+ ldu, doublereal *vt, integer *ldvt, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dgesvx_(char *fact, char *trans, integer *n, integer *
+ nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf,
+ integer *ipiv, char *equed, doublereal *r__, doublereal *c__,
+ doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+ rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dgetc2_(integer *n, doublereal *a, integer *lda, integer
+ *ipiv, integer *jpiv, integer *info);
+
+/* Subroutine */ int dgetf2_(integer *m, integer *n, doublereal *a, integer *
+ lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgetrf_(integer *m, integer *n, doublereal *a, integer *
+ lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgetri_(integer *n, doublereal *a, integer *lda, integer
+ *ipiv, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dgetrs_(char *trans, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *
+ ldb, integer *info);
+
+/* Subroutine */ int dggbak_(char *job, char *side, integer *n, integer *ilo,
+ integer *ihi, doublereal *lscale, doublereal *rscale, integer *m,
+ doublereal *v, integer *ldv, integer *info);
+
+/* Subroutine */ int dggbal_(char *job, integer *n, doublereal *a, integer *
+ lda, doublereal *b, integer *ldb, integer *ilo, integer *ihi,
+ doublereal *lscale, doublereal *rscale, doublereal *work, integer *
+ info);
+
+/* Subroutine */ int dgges_(char *jobvsl, char *jobvsr, char *sort, L_fp
+ delctg, integer *n, doublereal *a, integer *lda, doublereal *b,
+ integer *ldb, integer *sdim, doublereal *alphar, doublereal *alphai,
+ doublereal *beta, doublereal *vsl, integer *ldvsl, doublereal *vsr,
+ integer *ldvsr, doublereal *work, integer *lwork, logical *bwork,
+ integer *info);
+
+/* Subroutine */ int dggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp
+ delctg, char *sense, integer *n, doublereal *a, integer *lda,
+ doublereal *b, integer *ldb, integer *sdim, doublereal *alphar,
+ doublereal *alphai, doublereal *beta, doublereal *vsl, integer *ldvsl,
+ doublereal *vsr, integer *ldvsr, doublereal *rconde, doublereal *
+ rcondv, doublereal *work, integer *lwork, integer *iwork, integer *
+ liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int dggev_(char *jobvl, char *jobvr, integer *n, doublereal *
+ a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar,
+ doublereal *alphai, doublereal *beta, doublereal *vl, integer *ldvl,
+ doublereal *vr, integer *ldvr, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dggevx_(char *balanc, char *jobvl, char *jobvr, char *
+ sense, integer *n, doublereal *a, integer *lda, doublereal *b,
+ integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+ beta, doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr,
+ integer *ilo, integer *ihi, doublereal *lscale, doublereal *rscale,
+ doublereal *abnrm, doublereal *bbnrm, doublereal *rconde, doublereal *
+ rcondv, doublereal *work, integer *lwork, integer *iwork, logical *
+ bwork, integer *info);
+
+/* Subroutine */ int dggglm_(integer *n, integer *m, integer *p, doublereal *
+ a, integer *lda, doublereal *b, integer *ldb, doublereal *d__,
+ doublereal *x, doublereal *y, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dgghrd_(char *compq, char *compz, integer *n, integer *
+ ilo, integer *ihi, doublereal *a, integer *lda, doublereal *b,
+ integer *ldb, doublereal *q, integer *ldq, doublereal *z__, integer *
+ ldz, integer *info);
+
+/* Subroutine */ int dgglse_(integer *m, integer *n, integer *p, doublereal *
+ a, integer *lda, doublereal *b, integer *ldb, doublereal *c__,
+ doublereal *d__, doublereal *x, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dggqrf_(integer *n, integer *m, integer *p, doublereal *
+ a, integer *lda, doublereal *taua, doublereal *b, integer *ldb,
+ doublereal *taub, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dggrqf_(integer *m, integer *p, integer *n, doublereal *
+ a, integer *lda, doublereal *taua, doublereal *b, integer *ldb,
+ doublereal *taub, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dggsvd_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *n, integer *p, integer *k, integer *l, doublereal *a,
+ integer *lda, doublereal *b, integer *ldb, doublereal *alpha,
+ doublereal *beta, doublereal *u, integer *ldu, doublereal *v, integer
+ *ldv, doublereal *q, integer *ldq, doublereal *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int dggsvp_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *p, integer *n, doublereal *a, integer *lda, doublereal *b,
+ integer *ldb, doublereal *tola, doublereal *tolb, integer *k, integer
+ *l, doublereal *u, integer *ldu, doublereal *v, integer *ldv,
+ doublereal *q, integer *ldq, integer *iwork, doublereal *tau,
+ doublereal *work, integer *info);
+
+/* Subroutine */ int dgtcon_(char *norm, integer *n, doublereal *dl,
+ doublereal *d__, doublereal *du, doublereal *du2, integer *ipiv,
+ doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dgtrfs_(char *trans, integer *n, integer *nrhs,
+ doublereal *dl, doublereal *d__, doublereal *du, doublereal *dlf,
+ doublereal *df, doublereal *duf, doublereal *du2, integer *ipiv,
+ doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+ ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
+ info);
+
+/* Subroutine */ int dgtsv_(integer *n, integer *nrhs, doublereal *dl,
+ doublereal *d__, doublereal *du, doublereal *b, integer *ldb, integer
+ *info);
+
+/* Subroutine */ int dgtsvx_(char *fact, char *trans, integer *n, integer *
+ nrhs, doublereal *dl, doublereal *d__, doublereal *du, doublereal *
+ dlf, doublereal *df, doublereal *duf, doublereal *du2, integer *ipiv,
+ doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+ rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dgttrf_(integer *n, doublereal *dl, doublereal *d__,
+ doublereal *du, doublereal *du2, integer *ipiv, integer *info);
+
+/* Subroutine */ int dgttrs_(char *trans, integer *n, integer *nrhs,
+ doublereal *dl, doublereal *d__, doublereal *du, doublereal *du2,
+ integer *ipiv, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dgtts2_(integer *itrans, integer *n, integer *nrhs,
+ doublereal *dl, doublereal *d__, doublereal *du, doublereal *du2,
+ integer *ipiv, doublereal *b, integer *ldb);
+
+/* Subroutine */ int dhgeqz_(char *job, char *compq, char *compz, integer *n,
+ integer *ilo, integer *ihi, doublereal *a, integer *lda, doublereal *
+ b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+ beta, doublereal *q, integer *ldq, doublereal *z__, integer *ldz,
+ doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dhsein_(char *side, char *eigsrc, char *initv, logical *
+ select, integer *n, doublereal *h__, integer *ldh, doublereal *wr,
+ doublereal *wi, doublereal *vl, integer *ldvl, doublereal *vr,
+ integer *ldvr, integer *mm, integer *m, doublereal *work, integer *
+ ifaill, integer *ifailr, integer *info);
+
+/* Subroutine */ int dhseqr_(char *job, char *compz, integer *n, integer *ilo,
+ integer *ihi, doublereal *h__, integer *ldh, doublereal *wr,
+ doublereal *wi, doublereal *z__, integer *ldz, doublereal *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int dlabad_(doublereal *small, doublereal *large);
+
+/* Subroutine */ int dlabrd_(integer *m, integer *n, integer *nb, doublereal *
+ a, integer *lda, doublereal *d__, doublereal *e, doublereal *tauq,
+ doublereal *taup, doublereal *x, integer *ldx, doublereal *y, integer
+ *ldy);
+
+/* Subroutine */ int dlacon_(integer *n, doublereal *v, doublereal *x,
+ integer *isgn, doublereal *est, integer *kase);
+
+/* Subroutine */ int dlacpy_(char *uplo, integer *m, integer *n, doublereal *
+ a, integer *lda, doublereal *b, integer *ldb);
+
+/* Subroutine */ int dladiv_(doublereal *a, doublereal *b, doublereal *c__,
+ doublereal *d__, doublereal *p, doublereal *q);
+
+/* Subroutine */ int dlae2_(doublereal *a, doublereal *b, doublereal *c__,
+ doublereal *rt1, doublereal *rt2);
+
+/* Subroutine */ int dlaebz_(integer *ijob, integer *nitmax, integer *n,
+ integer *mmax, integer *minp, integer *nbmin, doublereal *abstol,
+ doublereal *reltol, doublereal *pivmin, doublereal *d__, doublereal *
+ e, doublereal *e2, integer *nval, doublereal *ab, doublereal *c__,
+ integer *mout, integer *nab, doublereal *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int dlaed0_(integer *icompq, integer *qsiz, integer *n,
+ doublereal *d__, doublereal *e, doublereal *q, integer *ldq,
+ doublereal *qstore, integer *ldqs, doublereal *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int dlaed1_(integer *n, doublereal *d__, doublereal *q,
+ integer *ldq, integer *indxq, doublereal *rho, integer *cutpnt,
+ doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlaed2_(integer *k, integer *n, integer *n1, doublereal *
+ d__, doublereal *q, integer *ldq, integer *indxq, doublereal *rho,
+ doublereal *z__, doublereal *dlamda, doublereal *w, doublereal *q2,
+ integer *indx, integer *indxc, integer *indxp, integer *coltyp,
+ integer *info);
+
+/* Subroutine */ int dlaed3_(integer *k, integer *n, integer *n1, doublereal *
+ d__, doublereal *q, integer *ldq, doublereal *rho, doublereal *dlamda,
+ doublereal *q2, integer *indx, integer *ctot, doublereal *w,
+ doublereal *s, integer *info);
+
+/* Subroutine */ int dlaed4_(integer *n, integer *i__, doublereal *d__,
+ doublereal *z__, doublereal *delta, doublereal *rho, doublereal *dlam,
+ integer *info);
+
+/* Subroutine */ int dlaed5_(integer *i__, doublereal *d__, doublereal *z__,
+ doublereal *delta, doublereal *rho, doublereal *dlam);
+
+/* Subroutine */ int dlaed6_(integer *kniter, logical *orgati, doublereal *
+ rho, doublereal *d__, doublereal *z__, doublereal *finit, doublereal *
+ tau, integer *info);
+
+/* Subroutine */ int dlaed7_(integer *icompq, integer *n, integer *qsiz,
+ integer *tlvls, integer *curlvl, integer *curpbm, doublereal *d__,
+ doublereal *q, integer *ldq, integer *indxq, doublereal *rho, integer
+ *cutpnt, doublereal *qstore, integer *qptr, integer *prmptr, integer *
+ perm, integer *givptr, integer *givcol, doublereal *givnum,
+ doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlaed8_(integer *icompq, integer *k, integer *n, integer
+ *qsiz, doublereal *d__, doublereal *q, integer *ldq, integer *indxq,
+ doublereal *rho, integer *cutpnt, doublereal *z__, doublereal *dlamda,
+ doublereal *q2, integer *ldq2, doublereal *w, integer *perm, integer
+ *givptr, integer *givcol, doublereal *givnum, integer *indxp, integer
+ *indx, integer *info);
+
+/* Subroutine */ int dlaed9_(integer *k, integer *kstart, integer *kstop,
+ integer *n, doublereal *d__, doublereal *q, integer *ldq, doublereal *
+ rho, doublereal *dlamda, doublereal *w, doublereal *s, integer *lds,
+ integer *info);
+
+/* Subroutine */ int dlaeda_(integer *n, integer *tlvls, integer *curlvl,
+ integer *curpbm, integer *prmptr, integer *perm, integer *givptr,
+ integer *givcol, doublereal *givnum, doublereal *q, integer *qptr,
+ doublereal *z__, doublereal *ztemp, integer *info);
+
+/* Subroutine */ int dlaein_(logical *rightv, logical *noinit, integer *n,
+ doublereal *h__, integer *ldh, doublereal *wr, doublereal *wi,
+ doublereal *vr, doublereal *vi, doublereal *b, integer *ldb,
+ doublereal *work, doublereal *eps3, doublereal *smlnum, doublereal *
+ bignum, integer *info);
+
+/* Subroutine */ int dlaev2_(doublereal *a, doublereal *b, doublereal *c__,
+ doublereal *rt1, doublereal *rt2, doublereal *cs1, doublereal *sn1);
+
+/* Subroutine */ int dlaexc_(logical *wantq, integer *n, doublereal *t,
+ integer *ldt, doublereal *q, integer *ldq, integer *j1, integer *n1,
+ integer *n2, doublereal *work, integer *info);
+
+/* Subroutine */ int dlag2_(doublereal *a, integer *lda, doublereal *b,
+ integer *ldb, doublereal *safmin, doublereal *scale1, doublereal *
+ scale2, doublereal *wr1, doublereal *wr2, doublereal *wi);
+
+/* Subroutine */ int dlags2_(logical *upper, doublereal *a1, doublereal *a2,
+ doublereal *a3, doublereal *b1, doublereal *b2, doublereal *b3,
+ doublereal *csu, doublereal *snu, doublereal *csv, doublereal *snv,
+ doublereal *csq, doublereal *snq);
+
+/* Subroutine */ int dlagtf_(integer *n, doublereal *a, doublereal *lambda,
+ doublereal *b, doublereal *c__, doublereal *tol, doublereal *d__,
+ integer *in, integer *info);
+
+/* Subroutine */ int dlagtm_(char *trans, integer *n, integer *nrhs,
+ doublereal *alpha, doublereal *dl, doublereal *d__, doublereal *du,
+ doublereal *x, integer *ldx, doublereal *beta, doublereal *b, integer
+ *ldb);
+
+/* Subroutine */ int dlagts_(integer *job, integer *n, doublereal *a,
+ doublereal *b, doublereal *c__, doublereal *d__, integer *in,
+ doublereal *y, doublereal *tol, integer *info);
+
+/* Subroutine */ int dlagv2_(doublereal *a, integer *lda, doublereal *b,
+ integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+ beta, doublereal *csl, doublereal *snl, doublereal *csr, doublereal *
+ snr);
+
+/* Subroutine */ int dlahqr_(logical *wantt, logical *wantz, integer *n,
+ integer *ilo, integer *ihi, doublereal *h__, integer *ldh, doublereal
+ *wr, doublereal *wi, integer *iloz, integer *ihiz, doublereal *z__,
+ integer *ldz, integer *info);
+
+/* Subroutine */ int dlahrd_(integer *n, integer *k, integer *nb, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *t, integer *ldt,
+ doublereal *y, integer *ldy);
+
+/* Subroutine */ int dlaic1_(integer *job, integer *j, doublereal *x,
+ doublereal *sest, doublereal *w, doublereal *gamma, doublereal *
+ sestpr, doublereal *s, doublereal *c__);
+
+/* Subroutine */ int dlaln2_(logical *ltrans, integer *na, integer *nw,
+ doublereal *smin, doublereal *ca, doublereal *a, integer *lda,
+ doublereal *d1, doublereal *d2, doublereal *b, integer *ldb,
+ doublereal *wr, doublereal *wi, doublereal *x, integer *ldx,
+ doublereal *scale, doublereal *xnorm, integer *info);
+
+/* Subroutine */ int dlals0_(integer *icompq, integer *nl, integer *nr,
+ integer *sqre, integer *nrhs, doublereal *b, integer *ldb, doublereal
+ *bx, integer *ldbx, integer *perm, integer *givptr, integer *givcol,
+ integer *ldgcol, doublereal *givnum, integer *ldgnum, doublereal *
+ poles, doublereal *difl, doublereal *difr, doublereal *z__, integer *
+ k, doublereal *c__, doublereal *s, doublereal *work, integer *info);
+
+/* Subroutine */ int dlalsa_(integer *icompq, integer *smlsiz, integer *n,
+ integer *nrhs, doublereal *b, integer *ldb, doublereal *bx, integer *
+ ldbx, doublereal *u, integer *ldu, doublereal *vt, integer *k,
+ doublereal *difl, doublereal *difr, doublereal *z__, doublereal *
+ poles, integer *givptr, integer *givcol, integer *ldgcol, integer *
+ perm, doublereal *givnum, doublereal *c__, doublereal *s, doublereal *
+ work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlalsd_(char *uplo, integer *smlsiz, integer *n, integer
+ *nrhs, doublereal *d__, doublereal *e, doublereal *b, integer *ldb,
+ doublereal *rcond, integer *rank, doublereal *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int dlamc1_(integer *beta, integer *t, logical *rnd, logical
+ *ieee1);
+
+/* Subroutine */ int dlamc2_(integer *beta, integer *t, logical *rnd,
+ doublereal *eps, integer *emin, doublereal *rmin, integer *emax,
+ doublereal *rmax);
+
+/* Subroutine */ int dlamc4_(integer *emin, doublereal *start, integer *base);
+
+/* Subroutine */ int dlamc5_(integer *beta, integer *p, integer *emin,
+ logical *ieee, integer *emax, doublereal *rmax);
+
+/* Subroutine */ int dlamrg_(integer *n1, integer *n2, doublereal *a, integer
+ *dtrd1, integer *dtrd2, integer *index);
+
+/* Subroutine */ int dlanv2_(doublereal *a, doublereal *b, doublereal *c__,
+ doublereal *d__, doublereal *rt1r, doublereal *rt1i, doublereal *rt2r,
+ doublereal *rt2i, doublereal *cs, doublereal *sn);
+
+/* Subroutine */ int dlapll_(integer *n, doublereal *x, integer *incx,
+ doublereal *y, integer *incy, doublereal *ssmin);
+
+/* Subroutine */ int dlapmt_(logical *forwrd, integer *m, integer *n,
+ doublereal *x, integer *ldx, integer *k);
+
+/* Subroutine */ int dlaqgb_(integer *m, integer *n, integer *kl, integer *ku,
+ doublereal *ab, integer *ldab, doublereal *r__, doublereal *c__,
+ doublereal *rowcnd, doublereal *colcnd, doublereal *amax, char *equed);
+
+/* Subroutine */ int dlaqge_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, doublereal
+ *colcnd, doublereal *amax, char *equed);
+
+/* Subroutine */ int dlaqp2_(integer *m, integer *n, integer *offset,
+ doublereal *a, integer *lda, integer *jpvt, doublereal *tau,
+ doublereal *vn1, doublereal *vn2, doublereal *work);
+
+/* Subroutine */ int dlaqps_(integer *m, integer *n, integer *offset, integer
+ *nb, integer *kb, doublereal *a, integer *lda, integer *jpvt,
+ doublereal *tau, doublereal *vn1, doublereal *vn2, doublereal *auxv,
+ doublereal *f, integer *ldf);
+
+/* Subroutine */ int dlaqsb_(char *uplo, integer *n, integer *kd, doublereal *
+ ab, integer *ldab, doublereal *s, doublereal *scond, doublereal *amax,
+ char *equed);
+
+/* Subroutine */ int dlaqsp_(char *uplo, integer *n, doublereal *ap,
+ doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+
+/* Subroutine */ int dlaqsy_(char *uplo, integer *n, doublereal *a, integer *
+ lda, doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+
+/* Subroutine */ int dlaqtr_(logical *ltran, logical *lreal, integer *n,
+ doublereal *t, integer *ldt, doublereal *b, doublereal *w, doublereal
+ *scale, doublereal *x, doublereal *work, integer *info);
+
+/* Subroutine */ int dlar1v_(integer *n, integer *b1, integer *bn, doublereal
+ *sigma, doublereal *d__, doublereal *l, doublereal *ld, doublereal *
+ lld, doublereal *gersch, doublereal *z__, doublereal *ztz, doublereal
+ *mingma, integer *r__, integer *isuppz, doublereal *work);
+
+/* Subroutine */ int dlar2v_(integer *n, doublereal *x, doublereal *y,
+ doublereal *z__, integer *incx, doublereal *c__, doublereal *s,
+ integer *incc);
+
+/* Subroutine */ int dlarf_(char *side, integer *m, integer *n, doublereal *v,
+ integer *incv, doublereal *tau, doublereal *c__, integer *ldc,
+ doublereal *work);
+
+/* Subroutine */ int dlarfb_(char *side, char *trans, char *direct, char *
+ storev, integer *m, integer *n, integer *k, doublereal *v, integer *
+ ldv, doublereal *t, integer *ldt, doublereal *c__, integer *ldc,
+ doublereal *work, integer *ldwork);
+
+/* Subroutine */ int dlarfg_(integer *n, doublereal *alpha, doublereal *x,
+ integer *incx, doublereal *tau);
+
+/* Subroutine */ int dlarft_(char *direct, char *storev, integer *n, integer *
+ k, doublereal *v, integer *ldv, doublereal *tau, doublereal *t,
+ integer *ldt);
+
+/* Subroutine */ int dlarfx_(char *side, integer *m, integer *n, doublereal *
+ v, doublereal *tau, doublereal *c__, integer *ldc, doublereal *work);
+
+/* Subroutine */ int dlargv_(integer *n, doublereal *x, integer *incx,
+ doublereal *y, integer *incy, doublereal *c__, integer *incc);
+
+/* Subroutine */ int dlarnv_(integer *idist, integer *iseed, integer *n,
+ doublereal *x);
+
+/* Subroutine */ int dlarrb_(integer *n, doublereal *d__, doublereal *l,
+ doublereal *ld, doublereal *lld, integer *ifirst, integer *ilast,
+ doublereal *sigma, doublereal *reltol, doublereal *w, doublereal *
+ wgap, doublereal *werr, doublereal *work, integer *iwork, integer *
+ info);
+
+/* Subroutine */ int dlarre_(integer *n, doublereal *d__, doublereal *e,
+ doublereal *tol, integer *nsplit, integer *isplit, integer *m,
+ doublereal *w, doublereal *woff, doublereal *gersch, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int dlarrf_(integer *n, doublereal *d__, doublereal *l,
+ doublereal *ld, doublereal *lld, integer *ifirst, integer *ilast,
+ doublereal *w, doublereal *dplus, doublereal *lplus, doublereal *work,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int dlarrv_(integer *n, doublereal *d__, doublereal *l,
+ integer *isplit, integer *m, doublereal *w, integer *iblock,
+ doublereal *gersch, doublereal *tol, doublereal *z__, integer *ldz,
+ integer *isuppz, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlartg_(doublereal *f, doublereal *g, doublereal *cs,
+ doublereal *sn, doublereal *r__);
+
+/* Subroutine */ int dlartv_(integer *n, doublereal *x, integer *incx,
+ doublereal *y, integer *incy, doublereal *c__, doublereal *s, integer
+ *incc);
+
+/* Subroutine */ int dlaruv_(integer *iseed, integer *n, doublereal *x);
+
+/* Subroutine */ int dlarz_(char *side, integer *m, integer *n, integer *l,
+ doublereal *v, integer *incv, doublereal *tau, doublereal *c__,
+ integer *ldc, doublereal *work);
+
+/* Subroutine */ int dlarzb_(char *side, char *trans, char *direct, char *
+ storev, integer *m, integer *n, integer *k, integer *l, doublereal *v,
+ integer *ldv, doublereal *t, integer *ldt, doublereal *c__, integer *
+ ldc, doublereal *work, integer *ldwork);
+
+/* Subroutine */ int dlarzt_(char *direct, char *storev, integer *n, integer *
+ k, doublereal *v, integer *ldv, doublereal *tau, doublereal *t,
+ integer *ldt);
+
+/* Subroutine */ int dlas2_(doublereal *f, doublereal *g, doublereal *h__,
+ doublereal *ssmin, doublereal *ssmax);
+
+/* Subroutine */ int dlascl_(char *type__, integer *kl, integer *ku,
+ doublereal *cfrom, doublereal *cto, integer *m, integer *n,
+ doublereal *a, integer *lda, integer *info);
+
+/* Subroutine */ int dlasd0_(integer *n, integer *sqre, doublereal *d__,
+ doublereal *e, doublereal *u, integer *ldu, doublereal *vt, integer *
+ ldvt, integer *smlsiz, integer *iwork, doublereal *work, integer *
+ info);
+
+/* Subroutine */ int dlasd1_(integer *nl, integer *nr, integer *sqre,
+ doublereal *d__, doublereal *alpha, doublereal *beta, doublereal *u,
+ integer *ldu, doublereal *vt, integer *ldvt, integer *idxq, integer *
+ iwork, doublereal *work, integer *info);
+
+/* Subroutine */ int dlasd2_(integer *nl, integer *nr, integer *sqre, integer
+ *k, doublereal *d__, doublereal *z__, doublereal *alpha, doublereal *
+ beta, doublereal *u, integer *ldu, doublereal *vt, integer *ldvt,
+ doublereal *dsigma, doublereal *u2, integer *ldu2, doublereal *vt2,
+ integer *ldvt2, integer *idxp, integer *idx, integer *idxc, integer *
+ idxq, integer *coltyp, integer *info);
+
+/* Subroutine */ int dlasd3_(integer *nl, integer *nr, integer *sqre, integer
+ *k, doublereal *d__, doublereal *q, integer *ldq, doublereal *dsigma,
+ doublereal *u, integer *ldu, doublereal *u2, integer *ldu2,
+ doublereal *vt, integer *ldvt, doublereal *vt2, integer *ldvt2,
+ integer *idxc, integer *ctot, doublereal *z__, integer *info);
+
+/* Subroutine */ int dlasd4_(integer *n, integer *i__, doublereal *d__,
+ doublereal *z__, doublereal *delta, doublereal *rho, doublereal *
+ sigma, doublereal *work, integer *info);
+
+/* Subroutine */ int dlasd5_(integer *i__, doublereal *d__, doublereal *z__,
+ doublereal *delta, doublereal *rho, doublereal *dsigma, doublereal *
+ work);
+
+/* Subroutine */ int dlasd6_(integer *icompq, integer *nl, integer *nr,
+ integer *sqre, doublereal *d__, doublereal *vf, doublereal *vl,
+ doublereal *alpha, doublereal *beta, integer *idxq, integer *perm,
+ integer *givptr, integer *givcol, integer *ldgcol, doublereal *givnum,
+ integer *ldgnum, doublereal *poles, doublereal *difl, doublereal *
+ difr, doublereal *z__, integer *k, doublereal *c__, doublereal *s,
+ doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlasd7_(integer *icompq, integer *nl, integer *nr,
+ integer *sqre, integer *k, doublereal *d__, doublereal *z__,
+ doublereal *zw, doublereal *vf, doublereal *vfw, doublereal *vl,
+ doublereal *vlw, doublereal *alpha, doublereal *beta, doublereal *
+ dsigma, integer *idx, integer *idxp, integer *idxq, integer *perm,
+ integer *givptr, integer *givcol, integer *ldgcol, doublereal *givnum,
+ integer *ldgnum, doublereal *c__, doublereal *s, integer *info);
+
+/* Subroutine */ int dlasd8_(integer *icompq, integer *k, doublereal *d__,
+ doublereal *z__, doublereal *vf, doublereal *vl, doublereal *difl,
+ doublereal *difr, integer *lddifr, doublereal *dsigma, doublereal *
+ work, integer *info);
+
+/* Subroutine */ int dlasd9_(integer *icompq, integer *ldu, integer *k,
+ doublereal *d__, doublereal *z__, doublereal *vf, doublereal *vl,
+ doublereal *difl, doublereal *difr, doublereal *dsigma, doublereal *
+ work, integer *info);
+
+/* Subroutine */ int dlasda_(integer *icompq, integer *smlsiz, integer *n,
+ integer *sqre, doublereal *d__, doublereal *e, doublereal *u, integer
+ *ldu, doublereal *vt, integer *k, doublereal *difl, doublereal *difr,
+ doublereal *z__, doublereal *poles, integer *givptr, integer *givcol,
+ integer *ldgcol, integer *perm, doublereal *givnum, doublereal *c__,
+ doublereal *s, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dlasdq_(char *uplo, integer *sqre, integer *n, integer *
+ ncvt, integer *nru, integer *ncc, doublereal *d__, doublereal *e,
+ doublereal *vt, integer *ldvt, doublereal *u, integer *ldu,
+ doublereal *c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dlasdt_(integer *n, integer *lvl, integer *nd, integer *
+ inode, integer *ndiml, integer *ndimr, integer *msub);
+
+/* Subroutine */ int dlaset_(char *uplo, integer *m, integer *n, doublereal *
+ alpha, doublereal *beta, doublereal *a, integer *lda);
+
+/* Subroutine */ int dlasq1_(integer *n, doublereal *d__, doublereal *e,
+ doublereal *work, integer *info);
+
+/* Subroutine */ int dlasq2_(integer *n, doublereal *z__, integer *info);
+
+/* Subroutine */ int dlasq3_(integer *i0, integer *n0, doublereal *z__,
+ integer *pp, doublereal *dmin__, doublereal *sigma, doublereal *desig,
+ doublereal *qmax, integer *nfail, integer *iter, integer *ndiv,
+ logical *ieee);
+
+/* Subroutine */ int dlasq4_(integer *i0, integer *n0, doublereal *z__,
+ integer *pp, integer *n0in, doublereal *dmin__, doublereal *dmin1,
+ doublereal *dmin2, doublereal *dn, doublereal *dn1, doublereal *dn2,
+ doublereal *tau, integer *ttype);
+
+/* Subroutine */ int dlasq5_(integer *i0, integer *n0, doublereal *z__,
+ integer *pp, doublereal *tau, doublereal *dmin__, doublereal *dmin1,
+ doublereal *dmin2, doublereal *dn, doublereal *dnm1, doublereal *dnm2,
+ logical *ieee);
+
+/* Subroutine */ int dlasq6_(integer *i0, integer *n0, doublereal *z__,
+ integer *pp, doublereal *dmin__, doublereal *dmin1, doublereal *dmin2,
+ doublereal *dn, doublereal *dnm1, doublereal *dnm2);
+
+/* Subroutine */ int dlasr_(char *side, char *pivot, char *direct, integer *m,
+ integer *n, doublereal *c__, doublereal *s, doublereal *a, integer *
+ lda);
+
+/* Subroutine */ int dlasrt_(char *id, integer *n, doublereal *d__, integer *
+ info);
+
+/* Subroutine */ int dlassq_(integer *n, doublereal *x, integer *incx,
+ doublereal *scale, doublereal *sumsq);
+
+/* Subroutine */ int dlasv2_(doublereal *f, doublereal *g, doublereal *h__,
+ doublereal *ssmin, doublereal *ssmax, doublereal *snr, doublereal *
+ csr, doublereal *snl, doublereal *csl);
+
+/* Subroutine */ int dlaswp_(integer *n, doublereal *a, integer *lda, integer
+ *k1, integer *k2, integer *ipiv, integer *incx);
+
+/* Subroutine */ int dlasy2_(logical *ltranl, logical *ltranr, integer *isgn,
+ integer *n1, integer *n2, doublereal *tl, integer *ldtl, doublereal *
+ tr, integer *ldtr, doublereal *b, integer *ldb, doublereal *scale,
+ doublereal *x, integer *ldx, doublereal *xnorm, integer *info);
+
+/* Subroutine */ int dlasyf_(char *uplo, integer *n, integer *nb, integer *kb,
+ doublereal *a, integer *lda, integer *ipiv, doublereal *w, integer *
+ ldw, integer *info);
+
+/* Subroutine */ int dlatbs_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, integer *kd, doublereal *ab, integer *ldab,
+ doublereal *x, doublereal *scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int dlatdf_(integer *ijob, integer *n, doublereal *z__,
+ integer *ldz, doublereal *rhs, doublereal *rdsum, doublereal *rdscal,
+ integer *ipiv, integer *jpiv);
+
+/* Subroutine */ int dlatps_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, doublereal *ap, doublereal *x, doublereal *scale,
+ doublereal *cnorm, integer *info);
+
+/* Subroutine */ int dlatrd_(char *uplo, integer *n, integer *nb, doublereal *
+ a, integer *lda, doublereal *e, doublereal *tau, doublereal *w,
+ integer *ldw);
+
+/* Subroutine */ int dlatrs_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, doublereal *a, integer *lda, doublereal *x,
+ doublereal *scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int dlatrz_(integer *m, integer *n, integer *l, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *work);
+
+/* Subroutine */ int dlatzm_(char *side, integer *m, integer *n, doublereal *
+ v, integer *incv, doublereal *tau, doublereal *c1, doublereal *c2,
+ integer *ldc, doublereal *work);
+
+/* Subroutine */ int dlauu2_(char *uplo, integer *n, doublereal *a, integer *
+ lda, integer *info);
+
+/* Subroutine */ int dlauum_(char *uplo, integer *n, doublereal *a, integer *
+ lda, integer *info);
+
+/* Subroutine */ int dopgtr_(char *uplo, integer *n, doublereal *ap,
+ doublereal *tau, doublereal *q, integer *ldq, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int dopmtr_(char *side, char *uplo, char *trans, integer *m,
+ integer *n, doublereal *ap, doublereal *tau, doublereal *c__, integer
+ *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dorg2l_(integer *m, integer *n, integer *k, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dorg2r_(integer *m, integer *n, integer *k, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dorgbr_(char *vect, integer *m, integer *n, integer *k,
+ doublereal *a, integer *lda, doublereal *tau, doublereal *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int dorghr_(integer *n, integer *ilo, integer *ihi,
+ doublereal *a, integer *lda, doublereal *tau, doublereal *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int dorgl2_(integer *m, integer *n, integer *k, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dorglq_(integer *m, integer *n, integer *k, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dorgql_(integer *m, integer *n, integer *k, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dorgqr_(integer *m, integer *n, integer *k, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dorgr2_(integer *m, integer *n, integer *k, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+
+/* Subroutine */ int dorgrq_(integer *m, integer *n, integer *k, doublereal *
+ a, integer *lda, doublereal *tau, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dorgtr_(char *uplo, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dorm2l_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+ c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dorm2r_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+ c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dormbr_(char *vect, char *side, char *trans, integer *m,
+ integer *n, integer *k, doublereal *a, integer *lda, doublereal *tau,
+ doublereal *c__, integer *ldc, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dormhr_(char *side, char *trans, integer *m, integer *n,
+ integer *ilo, integer *ihi, doublereal *a, integer *lda, doublereal *
+ tau, doublereal *c__, integer *ldc, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dorml2_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+ c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dormlq_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+ c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dormql_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+ c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dormqr_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+ c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dormr2_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+ c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dormr3_(char *side, char *trans, integer *m, integer *n,
+ integer *k, integer *l, doublereal *a, integer *lda, doublereal *tau,
+ doublereal *c__, integer *ldc, doublereal *work, integer *info);
+
+/* Subroutine */ int dormrq_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+ c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dormrz_(char *side, char *trans, integer *m, integer *n,
+ integer *k, integer *l, doublereal *a, integer *lda, doublereal *tau,
+ doublereal *c__, integer *ldc, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dormtr_(char *side, char *uplo, char *trans, integer *m,
+ integer *n, doublereal *a, integer *lda, doublereal *tau, doublereal *
+ c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dpbcon_(char *uplo, integer *n, integer *kd, doublereal *
+ ab, integer *ldab, doublereal *anorm, doublereal *rcond, doublereal *
+ work, integer *iwork, integer *info);
+
+/* Subroutine */ int dpbequ_(char *uplo, integer *n, integer *kd, doublereal *
+ ab, integer *ldab, doublereal *s, doublereal *scond, doublereal *amax,
+ integer *info);
+
+/* Subroutine */ int dpbrfs_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, doublereal *ab, integer *ldab, doublereal *afb, integer *ldafb,
+ doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+ ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
+ info);
+
+/* Subroutine */ int dpbstf_(char *uplo, integer *n, integer *kd, doublereal *
+ ab, integer *ldab, integer *info);
+
+/* Subroutine */ int dpbsv_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, doublereal *ab, integer *ldab, doublereal *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int dpbsvx_(char *fact, char *uplo, integer *n, integer *kd,
+ integer *nrhs, doublereal *ab, integer *ldab, doublereal *afb,
+ integer *ldafb, char *equed, doublereal *s, doublereal *b, integer *
+ ldb, doublereal *x, integer *ldx, doublereal *rcond, doublereal *ferr,
+ doublereal *berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dpbtf2_(char *uplo, integer *n, integer *kd, doublereal *
+ ab, integer *ldab, integer *info);
+
+/* Subroutine */ int dpbtrf_(char *uplo, integer *n, integer *kd, doublereal *
+ ab, integer *ldab, integer *info);
+
+/* Subroutine */ int dpbtrs_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, doublereal *ab, integer *ldab, doublereal *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int dpocon_(char *uplo, integer *n, doublereal *a, integer *
+ lda, doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dpoequ_(integer *n, doublereal *a, integer *lda,
+ doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int dporfs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, doublereal *af, integer *ldaf,
+ doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+ ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
+ info);
+
+/* Subroutine */ int dposv_(char *uplo, integer *n, integer *nrhs, doublereal
+ *a, integer *lda, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dposvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf,
+ char *equed, doublereal *s, doublereal *b, integer *ldb, doublereal *
+ x, integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *
+ berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dpotf2_(char *uplo, integer *n, doublereal *a, integer *
+ lda, integer *info);
+
+/* Subroutine */ int dpotrf_(char *uplo, integer *n, doublereal *a, integer *
+ lda, integer *info);
+
+/* Subroutine */ int dpotri_(char *uplo, integer *n, doublereal *a, integer *
+ lda, integer *info);
+
+/* Subroutine */ int dpotrs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int dppcon_(char *uplo, integer *n, doublereal *ap,
+ doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dppequ_(char *uplo, integer *n, doublereal *ap,
+ doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int dpprfs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *ap, doublereal *afp, doublereal *b, integer *ldb,
+ doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr,
+ doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dppsv_(char *uplo, integer *n, integer *nrhs, doublereal
+ *ap, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dppsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublereal *ap, doublereal *afp, char *equed, doublereal *s,
+ doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+ rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dpptrf_(char *uplo, integer *n, doublereal *ap, integer *
+ info);
+
+/* Subroutine */ int dpptri_(char *uplo, integer *n, doublereal *ap, integer *
+ info);
+
+/* Subroutine */ int dpptrs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *ap, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dptcon_(integer *n, doublereal *d__, doublereal *e,
+ doublereal *anorm, doublereal *rcond, doublereal *work, integer *info);
+
+/* Subroutine */ int dpteqr_(char *compz, integer *n, doublereal *d__,
+ doublereal *e, doublereal *z__, integer *ldz, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int dptrfs_(integer *n, integer *nrhs, doublereal *d__,
+ doublereal *e, doublereal *df, doublereal *ef, doublereal *b, integer
+ *ldb, doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr,
+ doublereal *work, integer *info);
+
+/* Subroutine */ int dptsv_(integer *n, integer *nrhs, doublereal *d__,
+ doublereal *e, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dptsvx_(char *fact, integer *n, integer *nrhs,
+ doublereal *d__, doublereal *e, doublereal *df, doublereal *ef,
+ doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+ rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+ info);
+
+/* Subroutine */ int dpttrf_(integer *n, doublereal *d__, doublereal *e,
+ integer *info);
+
+/* Subroutine */ int dpttrs_(integer *n, integer *nrhs, doublereal *d__,
+ doublereal *e, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dptts2_(integer *n, integer *nrhs, doublereal *d__,
+ doublereal *e, doublereal *b, integer *ldb);
+
+/* Subroutine */ int drscl_(integer *n, doublereal *sa, doublereal *sx,
+ integer *incx);
+
+/* Subroutine */ int dsbev_(char *jobz, char *uplo, integer *n, integer *kd,
+ doublereal *ab, integer *ldab, doublereal *w, doublereal *z__,
+ integer *ldz, doublereal *work, integer *info);
+
+/* Subroutine */ int dsbevd_(char *jobz, char *uplo, integer *n, integer *kd,
+ doublereal *ab, integer *ldab, doublereal *w, doublereal *z__,
+ integer *ldz, doublereal *work, integer *lwork, integer *iwork,
+ integer *liwork, integer *info);
+
+/* Subroutine */ int dsbevx_(char *jobz, char *range, char *uplo, integer *n,
+ integer *kd, doublereal *ab, integer *ldab, doublereal *q, integer *
+ ldq, doublereal *vl, doublereal *vu, integer *il, integer *iu,
+ doublereal *abstol, integer *m, doublereal *w, doublereal *z__,
+ integer *ldz, doublereal *work, integer *iwork, integer *ifail,
+ integer *info);
+
+/* Subroutine */ int dsbgst_(char *vect, char *uplo, integer *n, integer *ka,
+ integer *kb, doublereal *ab, integer *ldab, doublereal *bb, integer *
+ ldbb, doublereal *x, integer *ldx, doublereal *work, integer *info);
+
+/* Subroutine */ int dsbgv_(char *jobz, char *uplo, integer *n, integer *ka,
+ integer *kb, doublereal *ab, integer *ldab, doublereal *bb, integer *
+ ldbb, doublereal *w, doublereal *z__, integer *ldz, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int dsbgvd_(char *jobz, char *uplo, integer *n, integer *ka,
+ integer *kb, doublereal *ab, integer *ldab, doublereal *bb, integer *
+ ldbb, doublereal *w, doublereal *z__, integer *ldz, doublereal *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dsbgvx_(char *jobz, char *range, char *uplo, integer *n,
+ integer *ka, integer *kb, doublereal *ab, integer *ldab, doublereal *
+ bb, integer *ldbb, doublereal *q, integer *ldq, doublereal *vl,
+ doublereal *vu, integer *il, integer *iu, doublereal *abstol, integer
+ *m, doublereal *w, doublereal *z__, integer *ldz, doublereal *work,
+ integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int dsbtrd_(char *vect, char *uplo, integer *n, integer *kd,
+ doublereal *ab, integer *ldab, doublereal *d__, doublereal *e,
+ doublereal *q, integer *ldq, doublereal *work, integer *info);
+
+/* Subroutine */ int dspcon_(char *uplo, integer *n, doublereal *ap, integer *
+ ipiv, doublereal *anorm, doublereal *rcond, doublereal *work, integer
+ *iwork, integer *info);
+
+/* Subroutine */ int dspev_(char *jobz, char *uplo, integer *n, doublereal *
+ ap, doublereal *w, doublereal *z__, integer *ldz, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int dspevd_(char *jobz, char *uplo, integer *n, doublereal *
+ ap, doublereal *w, doublereal *z__, integer *ldz, doublereal *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dspevx_(char *jobz, char *range, char *uplo, integer *n,
+ doublereal *ap, doublereal *vl, doublereal *vu, integer *il, integer *
+ iu, doublereal *abstol, integer *m, doublereal *w, doublereal *z__,
+ integer *ldz, doublereal *work, integer *iwork, integer *ifail,
+ integer *info);
+
+/* Subroutine */ int dspgst_(integer *itype, char *uplo, integer *n,
+ doublereal *ap, doublereal *bp, integer *info);
+
+/* Subroutine */ int dspgv_(integer *itype, char *jobz, char *uplo, integer *
+ n, doublereal *ap, doublereal *bp, doublereal *w, doublereal *z__,
+ integer *ldz, doublereal *work, integer *info);
+
+/* Subroutine */ int dspgvd_(integer *itype, char *jobz, char *uplo, integer *
+ n, doublereal *ap, doublereal *bp, doublereal *w, doublereal *z__,
+ integer *ldz, doublereal *work, integer *lwork, integer *iwork,
+ integer *liwork, integer *info);
+
+/* Subroutine */ int dspgvx_(integer *itype, char *jobz, char *range, char *
+ uplo, integer *n, doublereal *ap, doublereal *bp, doublereal *vl,
+ doublereal *vu, integer *il, integer *iu, doublereal *abstol, integer
+ *m, doublereal *w, doublereal *z__, integer *ldz, doublereal *work,
+ integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int dsprfs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *ap, doublereal *afp, integer *ipiv, doublereal *b,
+ integer *ldb, doublereal *x, integer *ldx, doublereal *ferr,
+ doublereal *berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dspsv_(char *uplo, integer *n, integer *nrhs, doublereal
+ *ap, integer *ipiv, doublereal *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dspsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublereal *ap, doublereal *afp, integer *ipiv, doublereal *b,
+ integer *ldb, doublereal *x, integer *ldx, doublereal *rcond,
+ doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int dsptrd_(char *uplo, integer *n, doublereal *ap,
+ doublereal *d__, doublereal *e, doublereal *tau, integer *info);
+
+/* Subroutine */ int dsptrf_(char *uplo, integer *n, doublereal *ap, integer *
+ ipiv, integer *info);
+
+/* Subroutine */ int dsptri_(char *uplo, integer *n, doublereal *ap, integer *
+ ipiv, doublereal *work, integer *info);
+
+/* Subroutine */ int dsptrs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *ap, integer *ipiv, doublereal *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int dstebz_(char *range, char *order, integer *n, doublereal
+ *vl, doublereal *vu, integer *il, integer *iu, doublereal *abstol,
+ doublereal *d__, doublereal *e, integer *m, integer *nsplit,
+ doublereal *w, integer *iblock, integer *isplit, doublereal *work,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int dstedc_(char *compz, integer *n, doublereal *d__,
+ doublereal *e, doublereal *z__, integer *ldz, doublereal *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dstegr_(char *jobz, char *range, integer *n, doublereal *
+ d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il,
+ integer *iu, doublereal *abstol, integer *m, doublereal *w,
+ doublereal *z__, integer *ldz, integer *isuppz, doublereal *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dstein_(integer *n, doublereal *d__, doublereal *e,
+ integer *m, doublereal *w, integer *iblock, integer *isplit,
+ doublereal *z__, integer *ldz, doublereal *work, integer *iwork,
+ integer *ifail, integer *info);
+
+/* Subroutine */ int dsteqr_(char *compz, integer *n, doublereal *d__,
+ doublereal *e, doublereal *z__, integer *ldz, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int dsterf_(integer *n, doublereal *d__, doublereal *e,
+ integer *info);
+
+/* Subroutine */ int dstev_(char *jobz, integer *n, doublereal *d__,
+ doublereal *e, doublereal *z__, integer *ldz, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int dstevd_(char *jobz, integer *n, doublereal *d__,
+ doublereal *e, doublereal *z__, integer *ldz, doublereal *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dstevr_(char *jobz, char *range, integer *n, doublereal *
+ d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il,
+ integer *iu, doublereal *abstol, integer *m, doublereal *w,
+ doublereal *z__, integer *ldz, integer *isuppz, doublereal *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dstevx_(char *jobz, char *range, integer *n, doublereal *
+ d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il,
+ integer *iu, doublereal *abstol, integer *m, doublereal *w,
+ doublereal *z__, integer *ldz, doublereal *work, integer *iwork,
+ integer *ifail, integer *info);
+
+/* Subroutine */ int dsycon_(char *uplo, integer *n, doublereal *a, integer *
+ lda, integer *ipiv, doublereal *anorm, doublereal *rcond, doublereal *
+ work, integer *iwork, integer *info);
+
+/* Subroutine */ int dsyev_(char *jobz, char *uplo, integer *n, doublereal *a,
+ integer *lda, doublereal *w, doublereal *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int dsyevd_(char *jobz, char *uplo, integer *n, doublereal *
+ a, integer *lda, doublereal *w, doublereal *work, integer *lwork,
+ integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dsyevr_(char *jobz, char *range, char *uplo, integer *n,
+ doublereal *a, integer *lda, doublereal *vl, doublereal *vu, integer *
+ il, integer *iu, doublereal *abstol, integer *m, doublereal *w,
+ doublereal *z__, integer *ldz, integer *isuppz, doublereal *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int dsyevx_(char *jobz, char *range, char *uplo, integer *n,
+ doublereal *a, integer *lda, doublereal *vl, doublereal *vu, integer *
+ il, integer *iu, doublereal *abstol, integer *m, doublereal *w,
+ doublereal *z__, integer *ldz, doublereal *work, integer *lwork,
+ integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int dsygs2_(integer *itype, char *uplo, integer *n,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int dsygst_(integer *itype, char *uplo, integer *n,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int dsygv_(integer *itype, char *jobz, char *uplo, integer *
+ n, doublereal *a, integer *lda, doublereal *b, integer *ldb,
+ doublereal *w, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dsygvd_(integer *itype, char *jobz, char *uplo, integer *
+ n, doublereal *a, integer *lda, doublereal *b, integer *ldb,
+ doublereal *w, doublereal *work, integer *lwork, integer *iwork,
+ integer *liwork, integer *info);
+
+/* Subroutine */ int dsygvx_(integer *itype, char *jobz, char *range, char *
+ uplo, integer *n, doublereal *a, integer *lda, doublereal *b, integer
+ *ldb, doublereal *vl, doublereal *vu, integer *il, integer *iu,
+ doublereal *abstol, integer *m, doublereal *w, doublereal *z__,
+ integer *ldz, doublereal *work, integer *lwork, integer *iwork,
+ integer *ifail, integer *info);
+
+/* Subroutine */ int dsyrfs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, doublereal *af, integer *ldaf, integer *
+ ipiv, doublereal *b, integer *ldb, doublereal *x, integer *ldx,
+ doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int dsysv_(char *uplo, integer *n, integer *nrhs, doublereal
+ *a, integer *lda, integer *ipiv, doublereal *b, integer *ldb,
+ doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dsysvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf,
+ integer *ipiv, doublereal *b, integer *ldb, doublereal *x, integer *
+ ldx, doublereal *rcond, doublereal *ferr, doublereal *berr,
+ doublereal *work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int dsytd2_(char *uplo, integer *n, doublereal *a, integer *
+ lda, doublereal *d__, doublereal *e, doublereal *tau, integer *info);
+
+/* Subroutine */ int dsytf2_(char *uplo, integer *n, doublereal *a, integer *
+ lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int dsytrd_(char *uplo, integer *n, doublereal *a, integer *
+ lda, doublereal *d__, doublereal *e, doublereal *tau, doublereal *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int dsytrf_(char *uplo, integer *n, doublereal *a, integer *
+ lda, integer *ipiv, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dsytri_(char *uplo, integer *n, doublereal *a, integer *
+ lda, integer *ipiv, doublereal *work, integer *info);
+
+/* Subroutine */ int dsytrs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *
+ ldb, integer *info);
+
+/* Subroutine */ int dtbcon_(char *norm, char *uplo, char *diag, integer *n,
+ integer *kd, doublereal *ab, integer *ldab, doublereal *rcond,
+ doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dtbrfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *kd, integer *nrhs, doublereal *ab, integer *ldab, doublereal
+ *b, integer *ldb, doublereal *x, integer *ldx, doublereal *ferr,
+ doublereal *berr, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dtbtrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *kd, integer *nrhs, doublereal *ab, integer *ldab, doublereal
+ *b, integer *ldb, integer *info);
+
+/* Subroutine */ int dtgevc_(char *side, char *howmny, logical *select,
+ integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb,
+ doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, integer
+ *mm, integer *m, doublereal *work, integer *info);
+
+/* Subroutine */ int dtgex2_(logical *wantq, logical *wantz, integer *n,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+ q, integer *ldq, doublereal *z__, integer *ldz, integer *j1, integer *
+ n1, integer *n2, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dtgexc_(logical *wantq, logical *wantz, integer *n,
+ doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+ q, integer *ldq, doublereal *z__, integer *ldz, integer *ifst,
+ integer *ilst, doublereal *work, integer *lwork, integer *info);
+
+/* Subroutine */ int dtgsen_(integer *ijob, logical *wantq, logical *wantz,
+ logical *select, integer *n, doublereal *a, integer *lda, doublereal *
+ b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+ beta, doublereal *q, integer *ldq, doublereal *z__, integer *ldz,
+ integer *m, doublereal *pl, doublereal *pr, doublereal *dif,
+ doublereal *work, integer *lwork, integer *iwork, integer *liwork,
+ integer *info);
+
+/* Subroutine */ int dtgsja_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *p, integer *n, integer *k, integer *l, doublereal *a,
+ integer *lda, doublereal *b, integer *ldb, doublereal *tola,
+ doublereal *tolb, doublereal *alpha, doublereal *beta, doublereal *u,
+ integer *ldu, doublereal *v, integer *ldv, doublereal *q, integer *
+ ldq, doublereal *work, integer *ncycle, integer *info);
+
+/* Subroutine */ int dtgsna_(char *job, char *howmny, logical *select,
+ integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb,
+ doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr,
+ doublereal *s, doublereal *dif, integer *mm, integer *m, doublereal *
+ work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int dtgsy2_(char *trans, integer *ijob, integer *m, integer *
+ n, doublereal *a, integer *lda, doublereal *b, integer *ldb,
+ doublereal *c__, integer *ldc, doublereal *d__, integer *ldd,
+ doublereal *e, integer *lde, doublereal *f, integer *ldf, doublereal *
+ scale, doublereal *rdsum, doublereal *rdscal, integer *iwork, integer
+ *pq, integer *info);
+
+/* Subroutine */ int dtgsyl_(char *trans, integer *ijob, integer *m, integer *
+ n, doublereal *a, integer *lda, doublereal *b, integer *ldb,
+ doublereal *c__, integer *ldc, doublereal *d__, integer *ldd,
+ doublereal *e, integer *lde, doublereal *f, integer *ldf, doublereal *
+ scale, doublereal *dif, doublereal *work, integer *lwork, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dtpcon_(char *norm, char *uplo, char *diag, integer *n,
+ doublereal *ap, doublereal *rcond, doublereal *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int dtprfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, doublereal *ap, doublereal *b, integer *ldb,
+ doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr,
+ doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dtptri_(char *uplo, char *diag, integer *n, doublereal *
+ ap, integer *info);
+
+/* Subroutine */ int dtptrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, doublereal *ap, doublereal *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int dtrcon_(char *norm, char *uplo, char *diag, integer *n,
+ doublereal *a, integer *lda, doublereal *rcond, doublereal *work,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int dtrevc_(char *side, char *howmny, logical *select,
+ integer *n, doublereal *t, integer *ldt, doublereal *vl, integer *
+ ldvl, doublereal *vr, integer *ldvr, integer *mm, integer *m,
+ doublereal *work, integer *info);
+
+/* Subroutine */ int dtrexc_(char *compq, integer *n, doublereal *t, integer *
+ ldt, doublereal *q, integer *ldq, integer *ifst, integer *ilst,
+ doublereal *work, integer *info);
+
+/* Subroutine */ int dtrrfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, doublereal *a, integer *lda, doublereal *b, integer *
+ ldb, doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr,
+ doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int dtrsen_(char *job, char *compq, logical *select, integer
+ *n, doublereal *t, integer *ldt, doublereal *q, integer *ldq,
+ doublereal *wr, doublereal *wi, integer *m, doublereal *s, doublereal
+ *sep, doublereal *work, integer *lwork, integer *iwork, integer *
+ liwork, integer *info);
+
+/* Subroutine */ int dtrsna_(char *job, char *howmny, logical *select,
+ integer *n, doublereal *t, integer *ldt, doublereal *vl, integer *
+ ldvl, doublereal *vr, integer *ldvr, doublereal *s, doublereal *sep,
+ integer *mm, integer *m, doublereal *work, integer *ldwork, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int dtrsyl_(char *trana, char *tranb, integer *isgn, integer
+ *m, integer *n, doublereal *a, integer *lda, doublereal *b, integer *
+ ldb, doublereal *c__, integer *ldc, doublereal *scale, integer *info);
+
+/* Subroutine */ int dtrti2_(char *uplo, char *diag, integer *n, doublereal *
+ a, integer *lda, integer *info);
+
+/* Subroutine */ int dtrtri_(char *uplo, char *diag, integer *n, doublereal *
+ a, integer *lda, integer *info);
+
+/* Subroutine */ int dtrtrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, doublereal *a, integer *lda, doublereal *b, integer *
+ ldb, integer *info);
+
+/* Subroutine */ int dtzrqf_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, integer *info);
+
+/* Subroutine */ int dtzrzf_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+
+integer icmax1_(integer *n, complex *cx, integer *incx);
+
+integer ieeeck_(integer *ispec, real *zero, real *one);
+
+integer ilaenv_(integer *ispec, char *name__, char *opts, integer *n1,
+ integer *n2, integer *n3, integer *n4, ftnlen name_len, ftnlen
+ opts_len);
+
+integer izmax1_(integer *n, doublecomplex *cx, integer *incx);
+
+/* Subroutine */ int sbdsdc_(char *uplo, char *compq, integer *n, real *d__,
+ real *e, real *u, integer *ldu, real *vt, integer *ldvt, real *q,
+ integer *iq, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+ nru, integer *ncc, real *d__, real *e, real *vt, integer *ldvt, real *
+ u, integer *ldu, real *c__, integer *ldc, real *work, integer *info);
+
+/* Subroutine */ int sdisna_(char *job, integer *m, integer *n, real *d__,
+ real *sep, integer *info);
+
+/* Subroutine */ int sgbbrd_(char *vect, integer *m, integer *n, integer *ncc,
+ integer *kl, integer *ku, real *ab, integer *ldab, real *d__, real *
+ e, real *q, integer *ldq, real *pt, integer *ldpt, real *c__, integer
+ *ldc, real *work, integer *info);
+
+/* Subroutine */ int sgbcon_(char *norm, integer *n, integer *kl, integer *ku,
+ real *ab, integer *ldab, integer *ipiv, real *anorm, real *rcond,
+ real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgbequ_(integer *m, integer *n, integer *kl, integer *ku,
+ real *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real *
+ colcnd, real *amax, integer *info);
+
+/* Subroutine */ int sgbrfs_(char *trans, integer *n, integer *kl, integer *
+ ku, integer *nrhs, real *ab, integer *ldab, real *afb, integer *ldafb,
+ integer *ipiv, real *b, integer *ldb, real *x, integer *ldx, real *
+ ferr, real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgbsv_(integer *n, integer *kl, integer *ku, integer *
+ nrhs, real *ab, integer *ldab, integer *ipiv, real *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int sgbsvx_(char *fact, char *trans, integer *n, integer *kl,
+ integer *ku, integer *nrhs, real *ab, integer *ldab, real *afb,
+ integer *ldafb, integer *ipiv, char *equed, real *r__, real *c__,
+ real *b, integer *ldb, real *x, integer *ldx, real *rcond, real *ferr,
+ real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgbtf2_(integer *m, integer *n, integer *kl, integer *ku,
+ real *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int sgbtrf_(integer *m, integer *n, integer *kl, integer *ku,
+ real *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int sgbtrs_(char *trans, integer *n, integer *kl, integer *
+ ku, integer *nrhs, real *ab, integer *ldab, integer *ipiv, real *b,
+ integer *ldb, integer *info);
+
+/* Subroutine */ int sgebak_(char *job, char *side, integer *n, integer *ilo,
+ integer *ihi, real *scale, integer *m, real *v, integer *ldv, integer
+ *info);
+
+/* Subroutine */ int sgebal_(char *job, integer *n, real *a, integer *lda,
+ integer *ilo, integer *ihi, real *scale, integer *info);
+
+/* Subroutine */ int sgebd2_(integer *m, integer *n, real *a, integer *lda,
+ real *d__, real *e, real *tauq, real *taup, real *work, integer *info);
+
+/* Subroutine */ int sgebrd_(integer *m, integer *n, real *a, integer *lda,
+ real *d__, real *e, real *tauq, real *taup, real *work, integer *
+ lwork, integer *info);
+
+/* Subroutine */ int sgecon_(char *norm, integer *n, real *a, integer *lda,
+ real *anorm, real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgeequ_(integer *m, integer *n, real *a, integer *lda,
+ real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, integer
+ *info);
+
+/* Subroutine */ int sgees_(char *jobvs, char *sort, L_fp select, integer *n,
+ real *a, integer *lda, integer *sdim, real *wr, real *wi, real *vs,
+ integer *ldvs, real *work, integer *lwork, logical *bwork, integer *
+ info);
+
+/* Subroutine */ int sgeesx_(char *jobvs, char *sort, L_fp select, char *
+ sense, integer *n, real *a, integer *lda, integer *sdim, real *wr,
+ real *wi, real *vs, integer *ldvs, real *rconde, real *rcondv, real *
+ work, integer *lwork, integer *iwork, integer *liwork, logical *bwork,
+ integer *info);
+
+/* Subroutine */ int sgeev_(char *jobvl, char *jobvr, integer *n, real *a,
+ integer *lda, real *wr, real *wi, real *vl, integer *ldvl, real *vr,
+ integer *ldvr, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+ sense, integer *n, real *a, integer *lda, real *wr, real *wi, real *
+ vl, integer *ldvl, real *vr, integer *ldvr, integer *ilo, integer *
+ ihi, real *scale, real *abnrm, real *rconde, real *rcondv, real *work,
+ integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int sgegs_(char *jobvsl, char *jobvsr, integer *n, real *a,
+ integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real
+ *beta, real *vsl, integer *ldvsl, real *vsr, integer *ldvsr, real *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgegv_(char *jobvl, char *jobvr, integer *n, real *a,
+ integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real
+ *beta, real *vl, integer *ldvl, real *vr, integer *ldvr, real *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int sgehd2_(integer *n, integer *ilo, integer *ihi, real *a,
+ integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgehrd_(integer *n, integer *ilo, integer *ihi, real *a,
+ integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgelq2_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgelqf_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgels_(char *trans, integer *m, integer *n, integer *
+ nrhs, real *a, integer *lda, real *b, integer *ldb, real *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int sgelsd_(integer *m, integer *n, integer *nrhs, real *a,
+ integer *lda, real *b, integer *ldb, real *s, real *rcond, integer *
+ rank, real *work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int sgelss_(integer *m, integer *n, integer *nrhs, real *a,
+ integer *lda, real *b, integer *ldb, real *s, real *rcond, integer *
+ rank, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgelsx_(integer *m, integer *n, integer *nrhs, real *a,
+ integer *lda, real *b, integer *ldb, integer *jpvt, real *rcond,
+ integer *rank, real *work, integer *info);
+
+/* Subroutine */ int sgelsy_(integer *m, integer *n, integer *nrhs, real *a,
+ integer *lda, real *b, integer *ldb, integer *jpvt, real *rcond,
+ integer *rank, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgeql2_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgeqlf_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgeqp3_(integer *m, integer *n, real *a, integer *lda,
+ integer *jpvt, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgeqpf_(integer *m, integer *n, real *a, integer *lda,
+ integer *jpvt, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgeqr2_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgeqrf_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgerfs_(char *trans, integer *n, integer *nrhs, real *a,
+ integer *lda, real *af, integer *ldaf, integer *ipiv, real *b,
+ integer *ldb, real *x, integer *ldx, real *ferr, real *berr, real *
+ work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgerq2_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *info);
+
+/* Subroutine */ int sgerqf_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgesc2_(integer *n, real *a, integer *lda, real *rhs,
+ integer *ipiv, integer *jpiv, real *scale);
+
+/* Subroutine */ int sgesdd_(char *jobz, integer *m, integer *n, real *a,
+ integer *lda, real *s, real *u, integer *ldu, real *vt, integer *ldvt,
+ real *work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int sgesv_(integer *n, integer *nrhs, real *a, integer *lda,
+ integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sgesvd_(char *jobu, char *jobvt, integer *m, integer *n,
+ real *a, integer *lda, real *s, real *u, integer *ldu, real *vt,
+ integer *ldvt, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgesvx_(char *fact, char *trans, integer *n, integer *
+ nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv,
+ char *equed, real *r__, real *c__, real *b, integer *ldb, real *x,
+ integer *ldx, real *rcond, real *ferr, real *berr, real *work,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int sgetc2_(integer *n, real *a, integer *lda, integer *ipiv,
+ integer *jpiv, integer *info);
+
+/* Subroutine */ int sgetf2_(integer *m, integer *n, real *a, integer *lda,
+ integer *ipiv, integer *info);
+
+/* Subroutine */ int sgetrf_(integer *m, integer *n, real *a, integer *lda,
+ integer *ipiv, integer *info);
+
+/* Subroutine */ int sgetri_(integer *n, real *a, integer *lda, integer *ipiv,
+ real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgetrs_(char *trans, integer *n, integer *nrhs, real *a,
+ integer *lda, integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sggbak_(char *job, char *side, integer *n, integer *ilo,
+ integer *ihi, real *lscale, real *rscale, integer *m, real *v,
+ integer *ldv, integer *info);
+
+/* Subroutine */ int sggbal_(char *job, integer *n, real *a, integer *lda,
+ real *b, integer *ldb, integer *ilo, integer *ihi, real *lscale, real
+ *rscale, real *work, integer *info);
+
+/* Subroutine */ int sgges_(char *jobvsl, char *jobvsr, char *sort, L_fp
+ selctg, integer *n, real *a, integer *lda, real *b, integer *ldb,
+ integer *sdim, real *alphar, real *alphai, real *beta, real *vsl,
+ integer *ldvsl, real *vsr, integer *ldvsr, real *work, integer *lwork,
+ logical *bwork, integer *info);
+
+/* Subroutine */ int sggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp
+ selctg, char *sense, integer *n, real *a, integer *lda, real *b,
+ integer *ldb, integer *sdim, real *alphar, real *alphai, real *beta,
+ real *vsl, integer *ldvsl, real *vsr, integer *ldvsr, real *rconde,
+ real *rcondv, real *work, integer *lwork, integer *iwork, integer *
+ liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int sggev_(char *jobvl, char *jobvr, integer *n, real *a,
+ integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real
+ *beta, real *vl, integer *ldvl, real *vr, integer *ldvr, real *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int sggevx_(char *balanc, char *jobvl, char *jobvr, char *
+ sense, integer *n, real *a, integer *lda, real *b, integer *ldb, real
+ *alphar, real *alphai, real *beta, real *vl, integer *ldvl, real *vr,
+ integer *ldvr, integer *ilo, integer *ihi, real *lscale, real *rscale,
+ real *abnrm, real *bbnrm, real *rconde, real *rcondv, real *work,
+ integer *lwork, integer *iwork, logical *bwork, integer *info);
+
+/* Subroutine */ int sggglm_(integer *n, integer *m, integer *p, real *a,
+ integer *lda, real *b, integer *ldb, real *d__, real *x, real *y,
+ real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sgghrd_(char *compq, char *compz, integer *n, integer *
+ ilo, integer *ihi, real *a, integer *lda, real *b, integer *ldb, real
+ *q, integer *ldq, real *z__, integer *ldz, integer *info);
+
+/* Subroutine */ int sgglse_(integer *m, integer *n, integer *p, real *a,
+ integer *lda, real *b, integer *ldb, real *c__, real *d__, real *x,
+ real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sggqrf_(integer *n, integer *m, integer *p, real *a,
+ integer *lda, real *taua, real *b, integer *ldb, real *taub, real *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int sggrqf_(integer *m, integer *p, integer *n, real *a,
+ integer *lda, real *taua, real *b, integer *ldb, real *taub, real *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int sggsvd_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *n, integer *p, integer *k, integer *l, real *a, integer *lda,
+ real *b, integer *ldb, real *alpha, real *beta, real *u, integer *
+ ldu, real *v, integer *ldv, real *q, integer *ldq, real *work,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int sggsvp_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *p, integer *n, real *a, integer *lda, real *b, integer *ldb,
+ real *tola, real *tolb, integer *k, integer *l, real *u, integer *ldu,
+ real *v, integer *ldv, real *q, integer *ldq, integer *iwork, real *
+ tau, real *work, integer *info);
+
+/* Subroutine */ int sgtcon_(char *norm, integer *n, real *dl, real *d__,
+ real *du, real *du2, integer *ipiv, real *anorm, real *rcond, real *
+ work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgtrfs_(char *trans, integer *n, integer *nrhs, real *dl,
+ real *d__, real *du, real *dlf, real *df, real *duf, real *du2,
+ integer *ipiv, real *b, integer *ldb, real *x, integer *ldx, real *
+ ferr, real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sgtsv_(integer *n, integer *nrhs, real *dl, real *d__,
+ real *du, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sgtsvx_(char *fact, char *trans, integer *n, integer *
+ nrhs, real *dl, real *d__, real *du, real *dlf, real *df, real *duf,
+ real *du2, integer *ipiv, real *b, integer *ldb, real *x, integer *
+ ldx, real *rcond, real *ferr, real *berr, real *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int sgttrf_(integer *n, real *dl, real *d__, real *du, real *
+ du2, integer *ipiv, integer *info);
+
+/* Subroutine */ int sgttrs_(char *trans, integer *n, integer *nrhs, real *dl,
+ real *d__, real *du, real *du2, integer *ipiv, real *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int sgtts2_(integer *itrans, integer *n, integer *nrhs, real
+ *dl, real *d__, real *du, real *du2, integer *ipiv, real *b, integer *
+ ldb);
+
+/* Subroutine */ int shgeqz_(char *job, char *compq, char *compz, integer *n,
+ integer *ilo, integer *ihi, real *a, integer *lda, real *b, integer *
+ ldb, real *alphar, real *alphai, real *beta, real *q, integer *ldq,
+ real *z__, integer *ldz, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int shsein_(char *side, char *eigsrc, char *initv, logical *
+ select, integer *n, real *h__, integer *ldh, real *wr, real *wi, real
+ *vl, integer *ldvl, real *vr, integer *ldvr, integer *mm, integer *m,
+ real *work, integer *ifaill, integer *ifailr, integer *info);
+
+/* Subroutine */ int shseqr_(char *job, char *compz, integer *n, integer *ilo,
+ integer *ihi, real *h__, integer *ldh, real *wr, real *wi, real *z__,
+ integer *ldz, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int slabad_(real *small, real *large);
+
+/* Subroutine */ int slabrd_(integer *m, integer *n, integer *nb, real *a,
+ integer *lda, real *d__, real *e, real *tauq, real *taup, real *x,
+ integer *ldx, real *y, integer *ldy);
+
+/* Subroutine */ int slacon_(integer *n, real *v, real *x, integer *isgn,
+ real *est, integer *kase);
+
+/* Subroutine */ int slacpy_(char *uplo, integer *m, integer *n, real *a,
+ integer *lda, real *b, integer *ldb);
+
+/* Subroutine */ int sladiv_(real *a, real *b, real *c__, real *d__, real *p,
+ real *q);
+
+/* Subroutine */ int slae2_(real *a, real *b, real *c__, real *rt1, real *rt2);
+
+/* Subroutine */ int slaebz_(integer *ijob, integer *nitmax, integer *n,
+ integer *mmax, integer *minp, integer *nbmin, real *abstol, real *
+ reltol, real *pivmin, real *d__, real *e, real *e2, integer *nval,
+ real *ab, real *c__, integer *mout, integer *nab, real *work, integer
+ *iwork, integer *info);
+
+/* Subroutine */ int slaed0_(integer *icompq, integer *qsiz, integer *n, real
+ *d__, real *e, real *q, integer *ldq, real *qstore, integer *ldqs,
+ real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slaed1_(integer *n, real *d__, real *q, integer *ldq,
+ integer *indxq, real *rho, integer *cutpnt, real *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int slaed2_(integer *k, integer *n, integer *n1, real *d__,
+ real *q, integer *ldq, integer *indxq, real *rho, real *z__, real *
+ dlamda, real *w, real *q2, integer *indx, integer *indxc, integer *
+ indxp, integer *coltyp, integer *info);
+
+/* Subroutine */ int slaed3_(integer *k, integer *n, integer *n1, real *d__,
+ real *q, integer *ldq, real *rho, real *dlamda, real *q2, integer *
+ indx, integer *ctot, real *w, real *s, integer *info);
+
+/* Subroutine */ int slaed4_(integer *n, integer *i__, real *d__, real *z__,
+ real *delta, real *rho, real *dlam, integer *info);
+
+/* Subroutine */ int slaed5_(integer *i__, real *d__, real *z__, real *delta,
+ real *rho, real *dlam);
+
+/* Subroutine */ int slaed6_(integer *kniter, logical *orgati, real *rho,
+ real *d__, real *z__, real *finit, real *tau, integer *info);
+
+/* Subroutine */ int slaed7_(integer *icompq, integer *n, integer *qsiz,
+ integer *tlvls, integer *curlvl, integer *curpbm, real *d__, real *q,
+ integer *ldq, integer *indxq, real *rho, integer *cutpnt, real *
+ qstore, integer *qptr, integer *prmptr, integer *perm, integer *
+ givptr, integer *givcol, real *givnum, real *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int slaed8_(integer *icompq, integer *k, integer *n, integer
+ *qsiz, real *d__, real *q, integer *ldq, integer *indxq, real *rho,
+ integer *cutpnt, real *z__, real *dlamda, real *q2, integer *ldq2,
+ real *w, integer *perm, integer *givptr, integer *givcol, real *
+ givnum, integer *indxp, integer *indx, integer *info);
+
+/* Subroutine */ int slaed9_(integer *k, integer *kstart, integer *kstop,
+ integer *n, real *d__, real *q, integer *ldq, real *rho, real *dlamda,
+ real *w, real *s, integer *lds, integer *info);
+
+/* Subroutine */ int slaeda_(integer *n, integer *tlvls, integer *curlvl,
+ integer *curpbm, integer *prmptr, integer *perm, integer *givptr,
+ integer *givcol, real *givnum, real *q, integer *qptr, real *z__,
+ real *ztemp, integer *info);
+
+/* Subroutine */ int slaein_(logical *rightv, logical *noinit, integer *n,
+ real *h__, integer *ldh, real *wr, real *wi, real *vr, real *vi, real
+ *b, integer *ldb, real *work, real *eps3, real *smlnum, real *bignum,
+ integer *info);
+
+/* Subroutine */ int slaev2_(real *a, real *b, real *c__, real *rt1, real *
+ rt2, real *cs1, real *sn1);
+
+/* Subroutine */ int slaexc_(logical *wantq, integer *n, real *t, integer *
+ ldt, real *q, integer *ldq, integer *j1, integer *n1, integer *n2,
+ real *work, integer *info);
+
+/* Subroutine */ int slag2_(real *a, integer *lda, real *b, integer *ldb,
+ real *safmin, real *scale1, real *scale2, real *wr1, real *wr2, real *
+ wi);
+
+/* Subroutine */ int slags2_(logical *upper, real *a1, real *a2, real *a3,
+ real *b1, real *b2, real *b3, real *csu, real *snu, real *csv, real *
+ snv, real *csq, real *snq);
+
+/* Subroutine */ int slagtf_(integer *n, real *a, real *lambda, real *b, real
+ *c__, real *tol, real *d__, integer *in, integer *info);
+
+/* Subroutine */ int slagtm_(char *trans, integer *n, integer *nrhs, real *
+ alpha, real *dl, real *d__, real *du, real *x, integer *ldx, real *
+ beta, real *b, integer *ldb);
+
+/* Subroutine */ int slagts_(integer *job, integer *n, real *a, real *b, real
+ *c__, real *d__, integer *in, real *y, real *tol, integer *info);
+
+/* Subroutine */ int slagv2_(real *a, integer *lda, real *b, integer *ldb,
+ real *alphar, real *alphai, real *beta, real *csl, real *snl, real *
+ csr, real *snr);
+
+/* Subroutine */ int slahqr_(logical *wantt, logical *wantz, integer *n,
+ integer *ilo, integer *ihi, real *h__, integer *ldh, real *wr, real *
+ wi, integer *iloz, integer *ihiz, real *z__, integer *ldz, integer *
+ info);
+
+/* Subroutine */ int slahrd_(integer *n, integer *k, integer *nb, real *a,
+ integer *lda, real *tau, real *t, integer *ldt, real *y, integer *ldy);
+
+/* Subroutine */ int slaic1_(integer *job, integer *j, real *x, real *sest,
+ real *w, real *gamma, real *sestpr, real *s, real *c__);
+
+/* Subroutine */ int slaln2_(logical *ltrans, integer *na, integer *nw, real *
+ smin, real *ca, real *a, integer *lda, real *d1, real *d2, real *b,
+ integer *ldb, real *wr, real *wi, real *x, integer *ldx, real *scale,
+ real *xnorm, integer *info);
+
+/* Subroutine */ int slals0_(integer *icompq, integer *nl, integer *nr,
+ integer *sqre, integer *nrhs, real *b, integer *ldb, real *bx,
+ integer *ldbx, integer *perm, integer *givptr, integer *givcol,
+ integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
+ difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
+ work, integer *info);
+
+/* Subroutine */ int slalsa_(integer *icompq, integer *smlsiz, integer *n,
+ integer *nrhs, real *b, integer *ldb, real *bx, integer *ldbx, real *
+ u, integer *ldu, real *vt, integer *k, real *difl, real *difr, real *
+ z__, real *poles, integer *givptr, integer *givcol, integer *ldgcol,
+ integer *perm, real *givnum, real *c__, real *s, real *work, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int slalsd_(char *uplo, integer *smlsiz, integer *n, integer
+ *nrhs, real *d__, real *e, real *b, integer *ldb, real *rcond,
+ integer *rank, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slamc1_(integer *beta, integer *t, logical *rnd, logical
+ *ieee1);
+
+/* Subroutine */ int slamc2_(integer *beta, integer *t, logical *rnd, real *
+ eps, integer *emin, real *rmin, integer *emax, real *rmax);
+
+/* Subroutine */ int slamc4_(integer *emin, real *start, integer *base);
+
+/* Subroutine */ int slamc5_(integer *beta, integer *p, integer *emin,
+ logical *ieee, integer *emax, real *rmax);
+
+/* Subroutine */ int slamrg_(integer *n1, integer *n2, real *a, integer *
+ strd1, integer *strd2, integer *index);
+
+/* Subroutine */ int slanv2_(real *a, real *b, real *c__, real *d__, real *
+ rt1r, real *rt1i, real *rt2r, real *rt2i, real *cs, real *sn);
+
+/* Subroutine */ int slapll_(integer *n, real *x, integer *incx, real *y,
+ integer *incy, real *ssmin);
+
+/* Subroutine */ int slapmt_(logical *forwrd, integer *m, integer *n, real *x,
+ integer *ldx, integer *k);
+
+/* Subroutine */ int slaqgb_(integer *m, integer *n, integer *kl, integer *ku,
+ real *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real *
+ colcnd, real *amax, char *equed);
+
+/* Subroutine */ int slaqge_(integer *m, integer *n, real *a, integer *lda,
+ real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, char *
+ equed);
+
+/* Subroutine */ int slaqp2_(integer *m, integer *n, integer *offset, real *a,
+ integer *lda, integer *jpvt, real *tau, real *vn1, real *vn2, real *
+ work);
+
+/* Subroutine */ int slaqps_(integer *m, integer *n, integer *offset, integer
+ *nb, integer *kb, real *a, integer *lda, integer *jpvt, real *tau,
+ real *vn1, real *vn2, real *auxv, real *f, integer *ldf);
+
+/* Subroutine */ int slaqsb_(char *uplo, integer *n, integer *kd, real *ab,
+ integer *ldab, real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int slaqsp_(char *uplo, integer *n, real *ap, real *s, real *
+ scond, real *amax, char *equed);
+
+/* Subroutine */ int slaqsy_(char *uplo, integer *n, real *a, integer *lda,
+ real *s, real *scond, real *amax, char *equed);
+
+/* Subroutine */ int slaqtr_(logical *ltran, logical *lreal, integer *n, real
+ *t, integer *ldt, real *b, real *w, real *scale, real *x, real *work,
+ integer *info);
+
+/* Subroutine */ int slar1v_(integer *n, integer *b1, integer *bn, real *
+ sigma, real *d__, real *l, real *ld, real *lld, real *gersch, real *
+ z__, real *ztz, real *mingma, integer *r__, integer *isuppz, real *
+ work);
+
+/* Subroutine */ int slar2v_(integer *n, real *x, real *y, real *z__, integer
+ *incx, real *c__, real *s, integer *incc);
+
+/* Subroutine */ int slarf_(char *side, integer *m, integer *n, real *v,
+ integer *incv, real *tau, real *c__, integer *ldc, real *work);
+
+/* Subroutine */ int slarfb_(char *side, char *trans, char *direct, char *
+ storev, integer *m, integer *n, integer *k, real *v, integer *ldv,
+ real *t, integer *ldt, real *c__, integer *ldc, real *work, integer *
+ ldwork);
+
+/* Subroutine */ int slarfg_(integer *n, real *alpha, real *x, integer *incx,
+ real *tau);
+
+/* Subroutine */ int slarft_(char *direct, char *storev, integer *n, integer *
+ k, real *v, integer *ldv, real *tau, real *t, integer *ldt);
+
+/* Subroutine */ int slarfx_(char *side, integer *m, integer *n, real *v,
+ real *tau, real *c__, integer *ldc, real *work);
+
+/* Subroutine */ int slargv_(integer *n, real *x, integer *incx, real *y,
+ integer *incy, real *c__, integer *incc);
+
+/* Subroutine */ int slarnv_(integer *idist, integer *iseed, integer *n, real
+ *x);
+
+/* Subroutine */ int slarrb_(integer *n, real *d__, real *l, real *ld, real *
+ lld, integer *ifirst, integer *ilast, real *sigma, real *reltol, real
+ *w, real *wgap, real *werr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slarre_(integer *n, real *d__, real *e, real *tol,
+ integer *nsplit, integer *isplit, integer *m, real *w, real *woff,
+ real *gersch, real *work, integer *info);
+
+/* Subroutine */ int slarrf_(integer *n, real *d__, real *l, real *ld, real *
+ lld, integer *ifirst, integer *ilast, real *w, real *dplus, real *
+ lplus, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slarrv_(integer *n, real *d__, real *l, integer *isplit,
+ integer *m, real *w, integer *iblock, real *gersch, real *tol, real *
+ z__, integer *ldz, integer *isuppz, real *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int slartg_(real *f, real *g, real *cs, real *sn, real *r__);
+
+/* Subroutine */ int slartv_(integer *n, real *x, integer *incx, real *y,
+ integer *incy, real *c__, real *s, integer *incc);
+
+/* Subroutine */ int slaruv_(integer *iseed, integer *n, real *x);
+
+/* Subroutine */ int slarz_(char *side, integer *m, integer *n, integer *l,
+ real *v, integer *incv, real *tau, real *c__, integer *ldc, real *
+ work);
+
+/* Subroutine */ int slarzb_(char *side, char *trans, char *direct, char *
+ storev, integer *m, integer *n, integer *k, integer *l, real *v,
+ integer *ldv, real *t, integer *ldt, real *c__, integer *ldc, real *
+ work, integer *ldwork);
+
+/* Subroutine */ int slarzt_(char *direct, char *storev, integer *n, integer *
+ k, real *v, integer *ldv, real *tau, real *t, integer *ldt);
+
+/* Subroutine */ int slas2_(real *f, real *g, real *h__, real *ssmin, real *
+ ssmax);
+
+/* Subroutine */ int slascl_(char *type__, integer *kl, integer *ku, real *
+ cfrom, real *cto, integer *m, integer *n, real *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int slasd0_(integer *n, integer *sqre, real *d__, real *e,
+ real *u, integer *ldu, real *vt, integer *ldvt, integer *smlsiz,
+ integer *iwork, real *work, integer *info);
+
+/* Subroutine */ int slasd1_(integer *nl, integer *nr, integer *sqre, real *
+ d__, real *alpha, real *beta, real *u, integer *ldu, real *vt,
+ integer *ldvt, integer *idxq, integer *iwork, real *work, integer *
+ info);
+
+/* Subroutine */ int slasd2_(integer *nl, integer *nr, integer *sqre, integer
+ *k, real *d__, real *z__, real *alpha, real *beta, real *u, integer *
+ ldu, real *vt, integer *ldvt, real *dsigma, real *u2, integer *ldu2,
+ real *vt2, integer *ldvt2, integer *idxp, integer *idx, integer *idxc,
+ integer *idxq, integer *coltyp, integer *info);
+
+/* Subroutine */ int slasd3_(integer *nl, integer *nr, integer *sqre, integer
+ *k, real *d__, real *q, integer *ldq, real *dsigma, real *u, integer *
+ ldu, real *u2, integer *ldu2, real *vt, integer *ldvt, real *vt2,
+ integer *ldvt2, integer *idxc, integer *ctot, real *z__, integer *
+ info);
+
+/* Subroutine */ int slasd4_(integer *n, integer *i__, real *d__, real *z__,
+ real *delta, real *rho, real *sigma, real *work, integer *info);
+
+/* Subroutine */ int slasd5_(integer *i__, real *d__, real *z__, real *delta,
+ real *rho, real *dsigma, real *work);
+
+/* Subroutine */ int slasd6_(integer *icompq, integer *nl, integer *nr,
+ integer *sqre, real *d__, real *vf, real *vl, real *alpha, real *beta,
+ integer *idxq, integer *perm, integer *givptr, integer *givcol,
+ integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
+ difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
+ work, integer *iwork, integer *info);
+
+/* Subroutine */ int slasd7_(integer *icompq, integer *nl, integer *nr,
+ integer *sqre, integer *k, real *d__, real *z__, real *zw, real *vf,
+ real *vfw, real *vl, real *vlw, real *alpha, real *beta, real *dsigma,
+ integer *idx, integer *idxp, integer *idxq, integer *perm, integer *
+ givptr, integer *givcol, integer *ldgcol, real *givnum, integer *
+ ldgnum, real *c__, real *s, integer *info);
+
+/* Subroutine */ int slasd8_(integer *icompq, integer *k, real *d__, real *
+ z__, real *vf, real *vl, real *difl, real *difr, integer *lddifr,
+ real *dsigma, real *work, integer *info);
+
+/* Subroutine */ int slasd9_(integer *icompq, integer *ldu, integer *k, real *
+ d__, real *z__, real *vf, real *vl, real *difl, real *difr, real *
+ dsigma, real *work, integer *info);
+
+/* Subroutine */ int slasda_(integer *icompq, integer *smlsiz, integer *n,
+ integer *sqre, real *d__, real *e, real *u, integer *ldu, real *vt,
+ integer *k, real *difl, real *difr, real *z__, real *poles, integer *
+ givptr, integer *givcol, integer *ldgcol, integer *perm, real *givnum,
+ real *c__, real *s, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int slasdq_(char *uplo, integer *sqre, integer *n, integer *
+ ncvt, integer *nru, integer *ncc, real *d__, real *e, real *vt,
+ integer *ldvt, real *u, integer *ldu, real *c__, integer *ldc, real *
+ work, integer *info);
+
+/* Subroutine */ int slasdt_(integer *n, integer *lvl, integer *nd, integer *
+ inode, integer *ndiml, integer *ndimr, integer *msub);
+
+/* Subroutine */ int slaset_(char *uplo, integer *m, integer *n, real *alpha,
+ real *beta, real *a, integer *lda);
+
+/* Subroutine */ int slasq1_(integer *n, real *d__, real *e, real *work,
+ integer *info);
+
+/* Subroutine */ int slasq2_(integer *n, real *z__, integer *info);
+
+/* Subroutine */ int slasq3_(integer *i0, integer *n0, real *z__, integer *pp,
+ real *dmin__, real *sigma, real *desig, real *qmax, integer *nfail,
+ integer *iter, integer *ndiv, logical *ieee);
+
+/* Subroutine */ int slasq4_(integer *i0, integer *n0, real *z__, integer *pp,
+ integer *n0in, real *dmin__, real *dmin1, real *dmin2, real *dn,
+ real *dn1, real *dn2, real *tau, integer *ttype);
+
+/* Subroutine */ int slasq5_(integer *i0, integer *n0, real *z__, integer *pp,
+ real *tau, real *dmin__, real *dmin1, real *dmin2, real *dn, real *
+ dnm1, real *dnm2, logical *ieee);
+
+/* Subroutine */ int slasq6_(integer *i0, integer *n0, real *z__, integer *pp,
+ real *dmin__, real *dmin1, real *dmin2, real *dn, real *dnm1, real *
+ dnm2);
+
+/* Subroutine */ int slasr_(char *side, char *pivot, char *direct, integer *m,
+ integer *n, real *c__, real *s, real *a, integer *lda);
+
+/* Subroutine */ int slasrt_(char *id, integer *n, real *d__, integer *info);
+
+/* Subroutine */ int slassq_(integer *n, real *x, integer *incx, real *scale,
+ real *sumsq);
+
+/* Subroutine */ int slasv2_(real *f, real *g, real *h__, real *ssmin, real *
+ ssmax, real *snr, real *csr, real *snl, real *csl);
+
+/* Subroutine */ int slaswp_(integer *n, real *a, integer *lda, integer *k1,
+ integer *k2, integer *ipiv, integer *incx);
+
+/* Subroutine */ int slasy2_(logical *ltranl, logical *ltranr, integer *isgn,
+ integer *n1, integer *n2, real *tl, integer *ldtl, real *tr, integer *
+ ldtr, real *b, integer *ldb, real *scale, real *x, integer *ldx, real
+ *xnorm, integer *info);
+
+/* Subroutine */ int slasyf_(char *uplo, integer *n, integer *nb, integer *kb,
+ real *a, integer *lda, integer *ipiv, real *w, integer *ldw, integer
+ *info);
+
+/* Subroutine */ int slatbs_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, integer *kd, real *ab, integer *ldab, real *x,
+ real *scale, real *cnorm, integer *info);
+
+/* Subroutine */ int slatdf_(integer *ijob, integer *n, real *z__, integer *
+ ldz, real *rhs, real *rdsum, real *rdscal, integer *ipiv, integer *
+ jpiv);
+
+/* Subroutine */ int slatps_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, real *ap, real *x, real *scale, real *cnorm,
+ integer *info);
+
+/* Subroutine */ int slatrd_(char *uplo, integer *n, integer *nb, real *a,
+ integer *lda, real *e, real *tau, real *w, integer *ldw);
+
+/* Subroutine */ int slatrs_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, real *a, integer *lda, real *x, real *scale, real
+ *cnorm, integer *info);
+
+/* Subroutine */ int slatrz_(integer *m, integer *n, integer *l, real *a,
+ integer *lda, real *tau, real *work);
+
+/* Subroutine */ int slatzm_(char *side, integer *m, integer *n, real *v,
+ integer *incv, real *tau, real *c1, real *c2, integer *ldc, real *
+ work);
+
+/* Subroutine */ int slauu2_(char *uplo, integer *n, real *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int slauum_(char *uplo, integer *n, real *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int sopgtr_(char *uplo, integer *n, real *ap, real *tau,
+ real *q, integer *ldq, real *work, integer *info);
+
+/* Subroutine */ int sopmtr_(char *side, char *uplo, char *trans, integer *m,
+ integer *n, real *ap, real *tau, real *c__, integer *ldc, real *work,
+ integer *info);
+
+/* Subroutine */ int sorg2l_(integer *m, integer *n, integer *k, real *a,
+ integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sorg2r_(integer *m, integer *n, integer *k, real *a,
+ integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sorgbr_(char *vect, integer *m, integer *n, integer *k,
+ real *a, integer *lda, real *tau, real *work, integer *lwork, integer
+ *info);
+
+/* Subroutine */ int sorghr_(integer *n, integer *ilo, integer *ihi, real *a,
+ integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgl2_(integer *m, integer *n, integer *k, real *a,
+ integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sorglq_(integer *m, integer *n, integer *k, real *a,
+ integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgql_(integer *m, integer *n, integer *k, real *a,
+ integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgqr_(integer *m, integer *n, integer *k, real *a,
+ integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgr2_(integer *m, integer *n, integer *k, real *a,
+ integer *lda, real *tau, real *work, integer *info);
+
+/* Subroutine */ int sorgrq_(integer *m, integer *n, integer *k, real *a,
+ integer *lda, real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorgtr_(char *uplo, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorm2l_(char *side, char *trans, integer *m, integer *n,
+ integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+ real *work, integer *info);
+
+/* Subroutine */ int sorm2r_(char *side, char *trans, integer *m, integer *n,
+ integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+ real *work, integer *info);
+
+/* Subroutine */ int sormbr_(char *vect, char *side, char *trans, integer *m,
+ integer *n, integer *k, real *a, integer *lda, real *tau, real *c__,
+ integer *ldc, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormhr_(char *side, char *trans, integer *m, integer *n,
+ integer *ilo, integer *ihi, real *a, integer *lda, real *tau, real *
+ c__, integer *ldc, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sorml2_(char *side, char *trans, integer *m, integer *n,
+ integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+ real *work, integer *info);
+
+/* Subroutine */ int sormlq_(char *side, char *trans, integer *m, integer *n,
+ integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+ real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormql_(char *side, char *trans, integer *m, integer *n,
+ integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+ real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormqr_(char *side, char *trans, integer *m, integer *n,
+ integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+ real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormr2_(char *side, char *trans, integer *m, integer *n,
+ integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+ real *work, integer *info);
+
+/* Subroutine */ int sormr3_(char *side, char *trans, integer *m, integer *n,
+ integer *k, integer *l, real *a, integer *lda, real *tau, real *c__,
+ integer *ldc, real *work, integer *info);
+
+/* Subroutine */ int sormrq_(char *side, char *trans, integer *m, integer *n,
+ integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+ real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormrz_(char *side, char *trans, integer *m, integer *n,
+ integer *k, integer *l, real *a, integer *lda, real *tau, real *c__,
+ integer *ldc, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int sormtr_(char *side, char *uplo, char *trans, integer *m,
+ integer *n, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+ real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int spbcon_(char *uplo, integer *n, integer *kd, real *ab,
+ integer *ldab, real *anorm, real *rcond, real *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int spbequ_(char *uplo, integer *n, integer *kd, real *ab,
+ integer *ldab, real *s, real *scond, real *amax, integer *info);
+
+/* Subroutine */ int spbrfs_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, real *ab, integer *ldab, real *afb, integer *ldafb, real *b,
+ integer *ldb, real *x, integer *ldx, real *ferr, real *berr, real *
+ work, integer *iwork, integer *info);
+
+/* Subroutine */ int spbstf_(char *uplo, integer *n, integer *kd, real *ab,
+ integer *ldab, integer *info);
+
+/* Subroutine */ int spbsv_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, real *ab, integer *ldab, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int spbsvx_(char *fact, char *uplo, integer *n, integer *kd,
+ integer *nrhs, real *ab, integer *ldab, real *afb, integer *ldafb,
+ char *equed, real *s, real *b, integer *ldb, real *x, integer *ldx,
+ real *rcond, real *ferr, real *berr, real *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int spbtf2_(char *uplo, integer *n, integer *kd, real *ab,
+ integer *ldab, integer *info);
+
+/* Subroutine */ int spbtrf_(char *uplo, integer *n, integer *kd, real *ab,
+ integer *ldab, integer *info);
+
+/* Subroutine */ int spbtrs_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, real *ab, integer *ldab, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int spocon_(char *uplo, integer *n, real *a, integer *lda,
+ real *anorm, real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int spoequ_(integer *n, real *a, integer *lda, real *s, real
+ *scond, real *amax, integer *info);
+
+/* Subroutine */ int sporfs_(char *uplo, integer *n, integer *nrhs, real *a,
+ integer *lda, real *af, integer *ldaf, real *b, integer *ldb, real *x,
+ integer *ldx, real *ferr, real *berr, real *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int sposv_(char *uplo, integer *n, integer *nrhs, real *a,
+ integer *lda, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sposvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, real *a, integer *lda, real *af, integer *ldaf, char *equed,
+ real *s, real *b, integer *ldb, real *x, integer *ldx, real *rcond,
+ real *ferr, real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int spotf2_(char *uplo, integer *n, real *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int spotrf_(char *uplo, integer *n, real *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int spotri_(char *uplo, integer *n, real *a, integer *lda,
+ integer *info);
+
+/* Subroutine */ int spotrs_(char *uplo, integer *n, integer *nrhs, real *a,
+ integer *lda, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sppcon_(char *uplo, integer *n, real *ap, real *anorm,
+ real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sppequ_(char *uplo, integer *n, real *ap, real *s, real *
+ scond, real *amax, integer *info);
+
+/* Subroutine */ int spprfs_(char *uplo, integer *n, integer *nrhs, real *ap,
+ real *afp, real *b, integer *ldb, real *x, integer *ldx, real *ferr,
+ real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sppsv_(char *uplo, integer *n, integer *nrhs, real *ap,
+ real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sppsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, real *ap, real *afp, char *equed, real *s, real *b, integer *
+ ldb, real *x, integer *ldx, real *rcond, real *ferr, real *berr, real
+ *work, integer *iwork, integer *info);
+
+/* Subroutine */ int spptrf_(char *uplo, integer *n, real *ap, integer *info);
+
+/* Subroutine */ int spptri_(char *uplo, integer *n, real *ap, integer *info);
+
+/* Subroutine */ int spptrs_(char *uplo, integer *n, integer *nrhs, real *ap,
+ real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sptcon_(integer *n, real *d__, real *e, real *anorm,
+ real *rcond, real *work, integer *info);
+
+/* Subroutine */ int spteqr_(char *compz, integer *n, real *d__, real *e,
+ real *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int sptrfs_(integer *n, integer *nrhs, real *d__, real *e,
+ real *df, real *ef, real *b, integer *ldb, real *x, integer *ldx,
+ real *ferr, real *berr, real *work, integer *info);
+
+/* Subroutine */ int sptsv_(integer *n, integer *nrhs, real *d__, real *e,
+ real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sptsvx_(char *fact, integer *n, integer *nrhs, real *d__,
+ real *e, real *df, real *ef, real *b, integer *ldb, real *x, integer
+ *ldx, real *rcond, real *ferr, real *berr, real *work, integer *info);
+
+/* Subroutine */ int spttrf_(integer *n, real *d__, real *e, integer *info);
+
+/* Subroutine */ int spttrs_(integer *n, integer *nrhs, real *d__, real *e,
+ real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sptts2_(integer *n, integer *nrhs, real *d__, real *e,
+ real *b, integer *ldb);
+
+/* Subroutine */ int srscl_(integer *n, real *sa, real *sx, integer *incx);
+
+/* Subroutine */ int ssbev_(char *jobz, char *uplo, integer *n, integer *kd,
+ real *ab, integer *ldab, real *w, real *z__, integer *ldz, real *work,
+ integer *info);
+
+/* Subroutine */ int ssbevd_(char *jobz, char *uplo, integer *n, integer *kd,
+ real *ab, integer *ldab, real *w, real *z__, integer *ldz, real *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int ssbevx_(char *jobz, char *range, char *uplo, integer *n,
+ integer *kd, real *ab, integer *ldab, real *q, integer *ldq, real *vl,
+ real *vu, integer *il, integer *iu, real *abstol, integer *m, real *
+ w, real *z__, integer *ldz, real *work, integer *iwork, integer *
+ ifail, integer *info);
+
+/* Subroutine */ int ssbgst_(char *vect, char *uplo, integer *n, integer *ka,
+ integer *kb, real *ab, integer *ldab, real *bb, integer *ldbb, real *
+ x, integer *ldx, real *work, integer *info);
+
+/* Subroutine */ int ssbgv_(char *jobz, char *uplo, integer *n, integer *ka,
+ integer *kb, real *ab, integer *ldab, real *bb, integer *ldbb, real *
+ w, real *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int ssbgvd_(char *jobz, char *uplo, integer *n, integer *ka,
+ integer *kb, real *ab, integer *ldab, real *bb, integer *ldbb, real *
+ w, real *z__, integer *ldz, real *work, integer *lwork, integer *
+ iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int ssbgvx_(char *jobz, char *range, char *uplo, integer *n,
+ integer *ka, integer *kb, real *ab, integer *ldab, real *bb, integer *
+ ldbb, real *q, integer *ldq, real *vl, real *vu, integer *il, integer
+ *iu, real *abstol, integer *m, real *w, real *z__, integer *ldz, real
+ *work, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssbtrd_(char *vect, char *uplo, integer *n, integer *kd,
+ real *ab, integer *ldab, real *d__, real *e, real *q, integer *ldq,
+ real *work, integer *info);
+
+/* Subroutine */ int sspcon_(char *uplo, integer *n, real *ap, integer *ipiv,
+ real *anorm, real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sspev_(char *jobz, char *uplo, integer *n, real *ap,
+ real *w, real *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int sspevd_(char *jobz, char *uplo, integer *n, real *ap,
+ real *w, real *z__, integer *ldz, real *work, integer *lwork, integer
+ *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int sspevx_(char *jobz, char *range, char *uplo, integer *n,
+ real *ap, real *vl, real *vu, integer *il, integer *iu, real *abstol,
+ integer *m, real *w, real *z__, integer *ldz, real *work, integer *
+ iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int sspgst_(integer *itype, char *uplo, integer *n, real *ap,
+ real *bp, integer *info);
+
+/* Subroutine */ int sspgv_(integer *itype, char *jobz, char *uplo, integer *
+ n, real *ap, real *bp, real *w, real *z__, integer *ldz, real *work,
+ integer *info);
+
+/* Subroutine */ int sspgvd_(integer *itype, char *jobz, char *uplo, integer *
+ n, real *ap, real *bp, real *w, real *z__, integer *ldz, real *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int sspgvx_(integer *itype, char *jobz, char *range, char *
+ uplo, integer *n, real *ap, real *bp, real *vl, real *vu, integer *il,
+ integer *iu, real *abstol, integer *m, real *w, real *z__, integer *
+ ldz, real *work, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssprfs_(char *uplo, integer *n, integer *nrhs, real *ap,
+ real *afp, integer *ipiv, real *b, integer *ldb, real *x, integer *
+ ldx, real *ferr, real *berr, real *work, integer *iwork, integer *
+ info);
+
+/* Subroutine */ int sspsv_(char *uplo, integer *n, integer *nrhs, real *ap,
+ integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sspsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, real *ap, real *afp, integer *ipiv, real *b, integer *ldb, real
+ *x, integer *ldx, real *rcond, real *ferr, real *berr, real *work,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int ssptrd_(char *uplo, integer *n, real *ap, real *d__,
+ real *e, real *tau, integer *info);
+
+/* Subroutine */ int ssptrf_(char *uplo, integer *n, real *ap, integer *ipiv,
+ integer *info);
+
+/* Subroutine */ int ssptri_(char *uplo, integer *n, real *ap, integer *ipiv,
+ real *work, integer *info);
+
+/* Subroutine */ int ssptrs_(char *uplo, integer *n, integer *nrhs, real *ap,
+ integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int sstebz_(char *range, char *order, integer *n, real *vl,
+ real *vu, integer *il, integer *iu, real *abstol, real *d__, real *e,
+ integer *m, integer *nsplit, real *w, integer *iblock, integer *
+ isplit, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int sstedc_(char *compz, integer *n, real *d__, real *e,
+ real *z__, integer *ldz, real *work, integer *lwork, integer *iwork,
+ integer *liwork, integer *info);
+
+/* Subroutine */ int sstegr_(char *jobz, char *range, integer *n, real *d__,
+ real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol,
+ integer *m, real *w, real *z__, integer *ldz, integer *isuppz, real *
+ work, integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int sstein_(integer *n, real *d__, real *e, integer *m, real
+ *w, integer *iblock, integer *isplit, real *z__, integer *ldz, real *
+ work, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssteqr_(char *compz, integer *n, real *d__, real *e,
+ real *z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int ssterf_(integer *n, real *d__, real *e, integer *info);
+
+/* Subroutine */ int sstev_(char *jobz, integer *n, real *d__, real *e, real *
+ z__, integer *ldz, real *work, integer *info);
+
+/* Subroutine */ int sstevd_(char *jobz, integer *n, real *d__, real *e, real
+ *z__, integer *ldz, real *work, integer *lwork, integer *iwork,
+ integer *liwork, integer *info);
+
+/* Subroutine */ int sstevr_(char *jobz, char *range, integer *n, real *d__,
+ real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol,
+ integer *m, real *w, real *z__, integer *ldz, integer *isuppz, real *
+ work, integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int sstevx_(char *jobz, char *range, integer *n, real *d__,
+ real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol,
+ integer *m, real *w, real *z__, integer *ldz, real *work, integer *
+ iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssycon_(char *uplo, integer *n, real *a, integer *lda,
+ integer *ipiv, real *anorm, real *rcond, real *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int ssyev_(char *jobz, char *uplo, integer *n, real *a,
+ integer *lda, real *w, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int ssyevd_(char *jobz, char *uplo, integer *n, real *a,
+ integer *lda, real *w, real *work, integer *lwork, integer *iwork,
+ integer *liwork, integer *info);
+
+/* Subroutine */ int ssyevr_(char *jobz, char *range, char *uplo, integer *n,
+ real *a, integer *lda, real *vl, real *vu, integer *il, integer *iu,
+ real *abstol, integer *m, real *w, real *z__, integer *ldz, integer *
+ isuppz, real *work, integer *lwork, integer *iwork, integer *liwork,
+ integer *info);
+
+/* Subroutine */ int ssyevx_(char *jobz, char *range, char *uplo, integer *n,
+ real *a, integer *lda, real *vl, real *vu, integer *il, integer *iu,
+ real *abstol, integer *m, real *w, real *z__, integer *ldz, real *
+ work, integer *lwork, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssygs2_(integer *itype, char *uplo, integer *n, real *a,
+ integer *lda, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int ssygst_(integer *itype, char *uplo, integer *n, real *a,
+ integer *lda, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int ssygv_(integer *itype, char *jobz, char *uplo, integer *
+ n, real *a, integer *lda, real *b, integer *ldb, real *w, real *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int ssygvd_(integer *itype, char *jobz, char *uplo, integer *
+ n, real *a, integer *lda, real *b, integer *ldb, real *w, real *work,
+ integer *lwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int ssygvx_(integer *itype, char *jobz, char *range, char *
+ uplo, integer *n, real *a, integer *lda, real *b, integer *ldb, real *
+ vl, real *vu, integer *il, integer *iu, real *abstol, integer *m,
+ real *w, real *z__, integer *ldz, real *work, integer *lwork, integer
+ *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int ssyrfs_(char *uplo, integer *n, integer *nrhs, real *a,
+ integer *lda, real *af, integer *ldaf, integer *ipiv, real *b,
+ integer *ldb, real *x, integer *ldx, real *ferr, real *berr, real *
+ work, integer *iwork, integer *info);
+
+/* Subroutine */ int ssysv_(char *uplo, integer *n, integer *nrhs, real *a,
+ integer *lda, integer *ipiv, real *b, integer *ldb, real *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int ssysvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv,
+ real *b, integer *ldb, real *x, integer *ldx, real *rcond, real *ferr,
+ real *berr, real *work, integer *lwork, integer *iwork, integer *
+ info);
+
+/* Subroutine */ int ssytd2_(char *uplo, integer *n, real *a, integer *lda,
+ real *d__, real *e, real *tau, integer *info);
+
+/* Subroutine */ int ssytf2_(char *uplo, integer *n, real *a, integer *lda,
+ integer *ipiv, integer *info);
+
+/* Subroutine */ int ssytrd_(char *uplo, integer *n, real *a, integer *lda,
+ real *d__, real *e, real *tau, real *work, integer *lwork, integer *
+ info);
+
+/* Subroutine */ int ssytrf_(char *uplo, integer *n, real *a, integer *lda,
+ integer *ipiv, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int ssytri_(char *uplo, integer *n, real *a, integer *lda,
+ integer *ipiv, real *work, integer *info);
+
+/* Subroutine */ int ssytrs_(char *uplo, integer *n, integer *nrhs, real *a,
+ integer *lda, integer *ipiv, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int stbcon_(char *norm, char *uplo, char *diag, integer *n,
+ integer *kd, real *ab, integer *ldab, real *rcond, real *work,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int stbrfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *kd, integer *nrhs, real *ab, integer *ldab, real *b, integer
+ *ldb, real *x, integer *ldx, real *ferr, real *berr, real *work,
+ integer *iwork, integer *info);
+
+/* Subroutine */ int stbtrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *kd, integer *nrhs, real *ab, integer *ldab, real *b, integer
+ *ldb, integer *info);
+
+/* Subroutine */ int stgevc_(char *side, char *howmny, logical *select,
+ integer *n, real *a, integer *lda, real *b, integer *ldb, real *vl,
+ integer *ldvl, real *vr, integer *ldvr, integer *mm, integer *m, real
+ *work, integer *info);
+
+/* Subroutine */ int stgex2_(logical *wantq, logical *wantz, integer *n, real
+ *a, integer *lda, real *b, integer *ldb, real *q, integer *ldq, real *
+ z__, integer *ldz, integer *j1, integer *n1, integer *n2, real *work,
+ integer *lwork, integer *info);
+
+/* Subroutine */ int stgexc_(logical *wantq, logical *wantz, integer *n, real
+ *a, integer *lda, real *b, integer *ldb, real *q, integer *ldq, real *
+ z__, integer *ldz, integer *ifst, integer *ilst, real *work, integer *
+ lwork, integer *info);
+
+/* Subroutine */ int stgsen_(integer *ijob, logical *wantq, logical *wantz,
+ logical *select, integer *n, real *a, integer *lda, real *b, integer *
+ ldb, real *alphar, real *alphai, real *beta, real *q, integer *ldq,
+ real *z__, integer *ldz, integer *m, real *pl, real *pr, real *dif,
+ real *work, integer *lwork, integer *iwork, integer *liwork, integer *
+ info);
+
+/* Subroutine */ int stgsja_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *p, integer *n, integer *k, integer *l, real *a, integer *lda,
+ real *b, integer *ldb, real *tola, real *tolb, real *alpha, real *
+ beta, real *u, integer *ldu, real *v, integer *ldv, real *q, integer *
+ ldq, real *work, integer *ncycle, integer *info);
+
+/* Subroutine */ int stgsna_(char *job, char *howmny, logical *select,
+ integer *n, real *a, integer *lda, real *b, integer *ldb, real *vl,
+ integer *ldvl, real *vr, integer *ldvr, real *s, real *dif, integer *
+ mm, integer *m, real *work, integer *lwork, integer *iwork, integer *
+ info);
+
+/* Subroutine */ int stgsy2_(char *trans, integer *ijob, integer *m, integer *
+ n, real *a, integer *lda, real *b, integer *ldb, real *c__, integer *
+ ldc, real *d__, integer *ldd, real *e, integer *lde, real *f, integer
+ *ldf, real *scale, real *rdsum, real *rdscal, integer *iwork, integer
+ *pq, integer *info);
+
+/* Subroutine */ int stgsyl_(char *trans, integer *ijob, integer *m, integer *
+ n, real *a, integer *lda, real *b, integer *ldb, real *c__, integer *
+ ldc, real *d__, integer *ldd, real *e, integer *lde, real *f, integer
+ *ldf, real *scale, real *dif, real *work, integer *lwork, integer *
+ iwork, integer *info);
+
+/* Subroutine */ int stpcon_(char *norm, char *uplo, char *diag, integer *n,
+ real *ap, real *rcond, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int stprfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, real *ap, real *b, integer *ldb, real *x, integer *ldx,
+ real *ferr, real *berr, real *work, integer *iwork, integer *info);
+
+/* Subroutine */ int stptri_(char *uplo, char *diag, integer *n, real *ap,
+ integer *info);
+
+/* Subroutine */ int stptrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, real *ap, real *b, integer *ldb, integer *info);
+
+/* Subroutine */ int strcon_(char *norm, char *uplo, char *diag, integer *n,
+ real *a, integer *lda, real *rcond, real *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int strevc_(char *side, char *howmny, logical *select,
+ integer *n, real *t, integer *ldt, real *vl, integer *ldvl, real *vr,
+ integer *ldvr, integer *mm, integer *m, real *work, integer *info);
+
+/* Subroutine */ int strexc_(char *compq, integer *n, real *t, integer *ldt,
+ real *q, integer *ldq, integer *ifst, integer *ilst, real *work,
+ integer *info);
+
+/* Subroutine */ int strrfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, real *a, integer *lda, real *b, integer *ldb, real *x,
+ integer *ldx, real *ferr, real *berr, real *work, integer *iwork,
+ integer *info);
+
+/* Subroutine */ int strsen_(char *job, char *compq, logical *select, integer
+ *n, real *t, integer *ldt, real *q, integer *ldq, real *wr, real *wi,
+ integer *m, real *s, real *sep, real *work, integer *lwork, integer *
+ iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int strsna_(char *job, char *howmny, logical *select,
+ integer *n, real *t, integer *ldt, real *vl, integer *ldvl, real *vr,
+ integer *ldvr, real *s, real *sep, integer *mm, integer *m, real *
+ work, integer *ldwork, integer *iwork, integer *info);
+
+/* Subroutine */ int strsyl_(char *trana, char *tranb, integer *isgn, integer
+ *m, integer *n, real *a, integer *lda, real *b, integer *ldb, real *
+ c__, integer *ldc, real *scale, integer *info);
+
+/* Subroutine */ int strti2_(char *uplo, char *diag, integer *n, real *a,
+ integer *lda, integer *info);
+
+/* Subroutine */ int strtri_(char *uplo, char *diag, integer *n, real *a,
+ integer *lda, integer *info);
+
+/* Subroutine */ int strtrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, real *a, integer *lda, real *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int stzrqf_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, integer *info);
+
+/* Subroutine */ int stzrzf_(integer *m, integer *n, real *a, integer *lda,
+ real *tau, real *work, integer *lwork, integer *info);
+
+/* Subroutine */ int xerbla_(char *srname, integer *info);
+
+/* Subroutine */ int zbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+ nru, integer *ncc, doublereal *d__, doublereal *e, doublecomplex *vt,
+ integer *ldvt, doublecomplex *u, integer *ldu, doublecomplex *c__,
+ integer *ldc, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zdrot_(integer *n, doublecomplex *cx, integer *incx,
+ doublecomplex *cy, integer *incy, doublereal *c__, doublereal *s);
+
+/* Subroutine */ int zdrscl_(integer *n, doublereal *sa, doublecomplex *sx,
+ integer *incx);
+
+/* Subroutine */ int zgbbrd_(char *vect, integer *m, integer *n, integer *ncc,
+ integer *kl, integer *ku, doublecomplex *ab, integer *ldab,
+ doublereal *d__, doublereal *e, doublecomplex *q, integer *ldq,
+ doublecomplex *pt, integer *ldpt, doublecomplex *c__, integer *ldc,
+ doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgbcon_(char *norm, integer *n, integer *kl, integer *ku,
+ doublecomplex *ab, integer *ldab, integer *ipiv, doublereal *anorm,
+ doublereal *rcond, doublecomplex *work, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int zgbequ_(integer *m, integer *n, integer *kl, integer *ku,
+ doublecomplex *ab, integer *ldab, doublereal *r__, doublereal *c__,
+ doublereal *rowcnd, doublereal *colcnd, doublereal *amax, integer *
+ info);
+
+/* Subroutine */ int zgbrfs_(char *trans, integer *n, integer *kl, integer *
+ ku, integer *nrhs, doublecomplex *ab, integer *ldab, doublecomplex *
+ afb, integer *ldafb, integer *ipiv, doublecomplex *b, integer *ldb,
+ doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr,
+ doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgbsv_(integer *n, integer *kl, integer *ku, integer *
+ nrhs, doublecomplex *ab, integer *ldab, integer *ipiv, doublecomplex *
+ b, integer *ldb, integer *info);
+
+/* Subroutine */ int zgbsvx_(char *fact, char *trans, integer *n, integer *kl,
+ integer *ku, integer *nrhs, doublecomplex *ab, integer *ldab,
+ doublecomplex *afb, integer *ldafb, integer *ipiv, char *equed,
+ doublereal *r__, doublereal *c__, doublecomplex *b, integer *ldb,
+ doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *ferr,
+ doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int zgbtf2_(integer *m, integer *n, integer *kl, integer *ku,
+ doublecomplex *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int zgbtrf_(integer *m, integer *n, integer *kl, integer *ku,
+ doublecomplex *ab, integer *ldab, integer *ipiv, integer *info);
+
+/* Subroutine */ int zgbtrs_(char *trans, integer *n, integer *kl, integer *
+ ku, integer *nrhs, doublecomplex *ab, integer *ldab, integer *ipiv,
+ doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int zgebak_(char *job, char *side, integer *n, integer *ilo,
+ integer *ihi, doublereal *scale, integer *m, doublecomplex *v,
+ integer *ldv, integer *info);
+
+/* Subroutine */ int zgebal_(char *job, integer *n, doublecomplex *a, integer
+ *lda, integer *ilo, integer *ihi, doublereal *scale, integer *info);
+
+/* Subroutine */ int zgebd2_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublereal *d__, doublereal *e, doublecomplex *tauq,
+ doublecomplex *taup, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgebrd_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublereal *d__, doublereal *e, doublecomplex *tauq,
+ doublecomplex *taup, doublecomplex *work, integer *lwork, integer *
+ info);
+
+/* Subroutine */ int zgecon_(char *norm, integer *n, doublecomplex *a,
+ integer *lda, doublereal *anorm, doublereal *rcond, doublecomplex *
+ work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeequ_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublereal *r__, doublereal *c__, doublereal *rowcnd,
+ doublereal *colcnd, doublereal *amax, integer *info);
+
+/* Subroutine */ int zgees_(char *jobvs, char *sort, L_fp select, integer *n,
+ doublecomplex *a, integer *lda, integer *sdim, doublecomplex *w,
+ doublecomplex *vs, integer *ldvs, doublecomplex *work, integer *lwork,
+ doublereal *rwork, logical *bwork, integer *info);
+
+/* Subroutine */ int zgeesx_(char *jobvs, char *sort, L_fp select, char *
+ sense, integer *n, doublecomplex *a, integer *lda, integer *sdim,
+ doublecomplex *w, doublecomplex *vs, integer *ldvs, doublereal *
+ rconde, doublereal *rcondv, doublecomplex *work, integer *lwork,
+ doublereal *rwork, logical *bwork, integer *info);
+
+/* Subroutine */ int zgeev_(char *jobvl, char *jobvr, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *w, doublecomplex *vl,
+ integer *ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work,
+ integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+ sense, integer *n, doublecomplex *a, integer *lda, doublecomplex *w,
+ doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *ldvr,
+ integer *ilo, integer *ihi, doublereal *scale, doublereal *abnrm,
+ doublereal *rconde, doublereal *rcondv, doublecomplex *work, integer *
+ lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgegs_(char *jobvsl, char *jobvsr, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *alpha, doublecomplex *beta, doublecomplex *vsl,
+ integer *ldvsl, doublecomplex *vsr, integer *ldvsr, doublecomplex *
+ work, integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgegv_(char *jobvl, char *jobvr, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, integer
+ *ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work, integer
+ *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgehd2_(integer *n, integer *ilo, integer *ihi,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *info);
+
+/* Subroutine */ int zgehrd_(integer *n, integer *ilo, integer *ihi,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int zgelq2_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgelqf_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zgels_(char *trans, integer *m, integer *n, integer *
+ nrhs, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zgelsx_(integer *m, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ integer *jpvt, doublereal *rcond, integer *rank, doublecomplex *work,
+ doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgelsy_(integer *m, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ integer *jpvt, doublereal *rcond, integer *rank, doublecomplex *work,
+ integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeql2_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgeqlf_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zgeqp3_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, integer *jpvt, doublecomplex *tau, doublecomplex *work,
+ integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeqpf_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, integer *jpvt, doublecomplex *tau, doublecomplex *work,
+ doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgeqr2_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgeqrf_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zgerfs_(char *trans, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf,
+ integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x,
+ integer *ldx, doublereal *ferr, doublereal *berr, doublecomplex *work,
+ doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgerq2_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgerqf_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zgesc2_(integer *n, doublecomplex *a, integer *lda,
+ doublecomplex *rhs, integer *ipiv, integer *jpiv, doublereal *scale);
+
+/* Subroutine */ int zgesv_(integer *n, integer *nrhs, doublecomplex *a,
+ integer *lda, integer *ipiv, doublecomplex *b, integer *ldb, integer *
+ info);
+
+/* Subroutine */ int zgesvx_(char *fact, char *trans, integer *n, integer *
+ nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+ ldaf, integer *ipiv, char *equed, doublereal *r__, doublereal *c__,
+ doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+ doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+ work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgetc2_(integer *n, doublecomplex *a, integer *lda,
+ integer *ipiv, integer *jpiv, integer *info);
+
+/* Subroutine */ int zgetf2_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int zgetrf_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int zgetri_(integer *n, doublecomplex *a, integer *lda,
+ integer *ipiv, doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zgetrs_(char *trans, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b,
+ integer *ldb, integer *info);
+
+/* Subroutine */ int zggbak_(char *job, char *side, integer *n, integer *ilo,
+ integer *ihi, doublereal *lscale, doublereal *rscale, integer *m,
+ doublecomplex *v, integer *ldv, integer *info);
+
+/* Subroutine */ int zggbal_(char *job, integer *n, doublecomplex *a, integer
+ *lda, doublecomplex *b, integer *ldb, integer *ilo, integer *ihi,
+ doublereal *lscale, doublereal *rscale, doublereal *work, integer *
+ info);
+
+/* Subroutine */ int zgges_(char *jobvsl, char *jobvsr, char *sort, L_fp
+ delctg, integer *n, doublecomplex *a, integer *lda, doublecomplex *b,
+ integer *ldb, integer *sdim, doublecomplex *alpha, doublecomplex *
+ beta, doublecomplex *vsl, integer *ldvsl, doublecomplex *vsr, integer
+ *ldvsr, doublecomplex *work, integer *lwork, doublereal *rwork,
+ logical *bwork, integer *info);
+
+/* Subroutine */ int zggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp
+ delctg, char *sense, integer *n, doublecomplex *a, integer *lda,
+ doublecomplex *b, integer *ldb, integer *sdim, doublecomplex *alpha,
+ doublecomplex *beta, doublecomplex *vsl, integer *ldvsl,
+ doublecomplex *vsr, integer *ldvsr, doublereal *rconde, doublereal *
+ rcondv, doublecomplex *work, integer *lwork, doublereal *rwork,
+ integer *iwork, integer *liwork, logical *bwork, integer *info);
+
+/* Subroutine */ int zggev_(char *jobvl, char *jobvr, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, integer
+ *ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work, integer
+ *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zggevx_(char *balanc, char *jobvl, char *jobvr, char *
+ sense, integer *n, doublecomplex *a, integer *lda, doublecomplex *b,
+ integer *ldb, doublecomplex *alpha, doublecomplex *beta,
+ doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *ldvr,
+ integer *ilo, integer *ihi, doublereal *lscale, doublereal *rscale,
+ doublereal *abnrm, doublereal *bbnrm, doublereal *rconde, doublereal *
+ rcondv, doublecomplex *work, integer *lwork, doublereal *rwork,
+ integer *iwork, logical *bwork, integer *info);
+
+/* Subroutine */ int zggglm_(integer *n, integer *m, integer *p,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *d__, doublecomplex *x, doublecomplex *y, doublecomplex
+ *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zgghrd_(char *compq, char *compz, integer *n, integer *
+ ilo, integer *ihi, doublecomplex *a, integer *lda, doublecomplex *b,
+ integer *ldb, doublecomplex *q, integer *ldq, doublecomplex *z__,
+ integer *ldz, integer *info);
+
+/* Subroutine */ int zgglse_(integer *m, integer *n, integer *p,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *c__, doublecomplex *d__, doublecomplex *x,
+ doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zggqrf_(integer *n, integer *m, integer *p,
+ doublecomplex *a, integer *lda, doublecomplex *taua, doublecomplex *b,
+ integer *ldb, doublecomplex *taub, doublecomplex *work, integer *
+ lwork, integer *info);
+
+/* Subroutine */ int zggrqf_(integer *m, integer *p, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *taua, doublecomplex *b,
+ integer *ldb, doublecomplex *taub, doublecomplex *work, integer *
+ lwork, integer *info);
+
+/* Subroutine */ int zggsvd_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *n, integer *p, integer *k, integer *l, doublecomplex *a,
+ integer *lda, doublecomplex *b, integer *ldb, doublereal *alpha,
+ doublereal *beta, doublecomplex *u, integer *ldu, doublecomplex *v,
+ integer *ldv, doublecomplex *q, integer *ldq, doublecomplex *work,
+ doublereal *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zggsvp_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *p, integer *n, doublecomplex *a, integer *lda, doublecomplex
+ *b, integer *ldb, doublereal *tola, doublereal *tolb, integer *k,
+ integer *l, doublecomplex *u, integer *ldu, doublecomplex *v, integer
+ *ldv, doublecomplex *q, integer *ldq, integer *iwork, doublereal *
+ rwork, doublecomplex *tau, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zgtcon_(char *norm, integer *n, doublecomplex *dl,
+ doublecomplex *d__, doublecomplex *du, doublecomplex *du2, integer *
+ ipiv, doublereal *anorm, doublereal *rcond, doublecomplex *work,
+ integer *info);
+
+/* Subroutine */ int zgtrfs_(char *trans, integer *n, integer *nrhs,
+ doublecomplex *dl, doublecomplex *d__, doublecomplex *du,
+ doublecomplex *dlf, doublecomplex *df, doublecomplex *duf,
+ doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb,
+ doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr,
+ doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zgtsv_(integer *n, integer *nrhs, doublecomplex *dl,
+ doublecomplex *d__, doublecomplex *du, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zgtsvx_(char *fact, char *trans, integer *n, integer *
+ nrhs, doublecomplex *dl, doublecomplex *d__, doublecomplex *du,
+ doublecomplex *dlf, doublecomplex *df, doublecomplex *duf,
+ doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb,
+ doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *ferr,
+ doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int zgttrf_(integer *n, doublecomplex *dl, doublecomplex *
+ d__, doublecomplex *du, doublecomplex *du2, integer *ipiv, integer *
+ info);
+
+/* Subroutine */ int zgttrs_(char *trans, integer *n, integer *nrhs,
+ doublecomplex *dl, doublecomplex *d__, doublecomplex *du,
+ doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zgtts2_(integer *itrans, integer *n, integer *nrhs,
+ doublecomplex *dl, doublecomplex *d__, doublecomplex *du,
+ doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zhbev_(char *jobz, char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, doublereal *w, doublecomplex *z__,
+ integer *ldz, doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhbevd_(char *jobz, char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, doublereal *w, doublecomplex *z__,
+ integer *ldz, doublecomplex *work, integer *lwork, doublereal *rwork,
+ integer *lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zhbevx_(char *jobz, char *range, char *uplo, integer *n,
+ integer *kd, doublecomplex *ab, integer *ldab, doublecomplex *q,
+ integer *ldq, doublereal *vl, doublereal *vu, integer *il, integer *
+ iu, doublereal *abstol, integer *m, doublereal *w, doublecomplex *z__,
+ integer *ldz, doublecomplex *work, doublereal *rwork, integer *iwork,
+ integer *ifail, integer *info);
+
+/* Subroutine */ int zhbgst_(char *vect, char *uplo, integer *n, integer *ka,
+ integer *kb, doublecomplex *ab, integer *ldab, doublecomplex *bb,
+ integer *ldbb, doublecomplex *x, integer *ldx, doublecomplex *work,
+ doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhbgv_(char *jobz, char *uplo, integer *n, integer *ka,
+ integer *kb, doublecomplex *ab, integer *ldab, doublecomplex *bb,
+ integer *ldbb, doublereal *w, doublecomplex *z__, integer *ldz,
+ doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhbgvx_(char *jobz, char *range, char *uplo, integer *n,
+ integer *ka, integer *kb, doublecomplex *ab, integer *ldab,
+ doublecomplex *bb, integer *ldbb, doublecomplex *q, integer *ldq,
+ doublereal *vl, doublereal *vu, integer *il, integer *iu, doublereal *
+ abstol, integer *m, doublereal *w, doublecomplex *z__, integer *ldz,
+ doublecomplex *work, doublereal *rwork, integer *iwork, integer *
+ ifail, integer *info);
+
+/* Subroutine */ int zhbtrd_(char *vect, char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, doublereal *d__, doublereal *e,
+ doublecomplex *q, integer *ldq, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zhecon_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, doublereal *anorm, doublereal *rcond,
+ doublecomplex *work, integer *info);
+
+/* Subroutine */ int zheev_(char *jobz, char *uplo, integer *n, doublecomplex
+ *a, integer *lda, doublereal *w, doublecomplex *work, integer *lwork,
+ doublereal *rwork, integer *info);
+
+/* Subroutine */ int zheevd_(char *jobz, char *uplo, integer *n,
+ doublecomplex *a, integer *lda, doublereal *w, doublecomplex *work,
+ integer *lwork, doublereal *rwork, integer *lrwork, integer *iwork,
+ integer *liwork, integer *info);
+
+/* Subroutine */ int zheevr_(char *jobz, char *range, char *uplo, integer *n,
+ doublecomplex *a, integer *lda, doublereal *vl, doublereal *vu,
+ integer *il, integer *iu, doublereal *abstol, integer *m, doublereal *
+ w, doublecomplex *z__, integer *ldz, integer *isuppz, doublecomplex *
+ work, integer *lwork, doublereal *rwork, integer *lrwork, integer *
+ iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zheevx_(char *jobz, char *range, char *uplo, integer *n,
+ doublecomplex *a, integer *lda, doublereal *vl, doublereal *vu,
+ integer *il, integer *iu, doublereal *abstol, integer *m, doublereal *
+ w, doublecomplex *z__, integer *ldz, doublecomplex *work, integer *
+ lwork, doublereal *rwork, integer *iwork, integer *ifail, integer *
+ info);
+
+/* Subroutine */ int zhegs2_(integer *itype, char *uplo, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zhegst_(integer *itype, char *uplo, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zhegv_(integer *itype, char *jobz, char *uplo, integer *
+ n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublereal *w, doublecomplex *work, integer *lwork, doublereal *rwork,
+ integer *info);
+
+/* Subroutine */ int zhegvd_(integer *itype, char *jobz, char *uplo, integer *
+ n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublereal *w, doublecomplex *work, integer *lwork, doublereal *rwork,
+ integer *lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zhegvx_(integer *itype, char *jobz, char *range, char *
+ uplo, integer *n, doublecomplex *a, integer *lda, doublecomplex *b,
+ integer *ldb, doublereal *vl, doublereal *vu, integer *il, integer *
+ iu, doublereal *abstol, integer *m, doublereal *w, doublecomplex *z__,
+ integer *ldz, doublecomplex *work, integer *lwork, doublereal *rwork,
+ integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int zherfs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf,
+ integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x,
+ integer *ldx, doublereal *ferr, doublereal *berr, doublecomplex *work,
+ doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhesv_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b,
+ integer *ldb, doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zhesvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+ ldaf, integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x,
+ integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *berr,
+ doublecomplex *work, integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhetf2_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int zhetrd_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, doublereal *d__, doublereal *e, doublecomplex *tau,
+ doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zhetrf_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zhetri_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zhetrs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b,
+ integer *ldb, integer *info);
+
+/* Subroutine */ int zhgeqz_(char *job, char *compq, char *compz, integer *n,
+ integer *ilo, integer *ihi, doublecomplex *a, integer *lda,
+ doublecomplex *b, integer *ldb, doublecomplex *alpha, doublecomplex *
+ beta, doublecomplex *q, integer *ldq, doublecomplex *z__, integer *
+ ldz, doublecomplex *work, integer *lwork, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int zhpcon_(char *uplo, integer *n, doublecomplex *ap,
+ integer *ipiv, doublereal *anorm, doublereal *rcond, doublecomplex *
+ work, integer *info);
+
+/* Subroutine */ int zhpev_(char *jobz, char *uplo, integer *n, doublecomplex
+ *ap, doublereal *w, doublecomplex *z__, integer *ldz, doublecomplex *
+ work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhpevd_(char *jobz, char *uplo, integer *n,
+ doublecomplex *ap, doublereal *w, doublecomplex *z__, integer *ldz,
+ doublecomplex *work, integer *lwork, doublereal *rwork, integer *
+ lrwork, integer *iwork, integer *liwork, integer *info);
+
+/* Subroutine */ int zhpevx_(char *jobz, char *range, char *uplo, integer *n,
+ doublecomplex *ap, doublereal *vl, doublereal *vu, integer *il,
+ integer *iu, doublereal *abstol, integer *m, doublereal *w,
+ doublecomplex *z__, integer *ldz, doublecomplex *work, doublereal *
+ rwork, integer *iwork, integer *ifail, integer *info);
+
+/* Subroutine */ int zhpgst_(integer *itype, char *uplo, integer *n,
+ doublecomplex *ap, doublecomplex *bp, integer *info);
+
+/* Subroutine */ int zhpgv_(integer *itype, char *jobz, char *uplo, integer *
+ n, doublecomplex *ap, doublecomplex *bp, doublereal *w, doublecomplex
+ *z__, integer *ldz, doublecomplex *work, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int zhpgvd_(integer *itype, char *jobz, char *uplo, integer *
+ n, doublecomplex *ap, doublecomplex *bp, doublereal *w, doublecomplex
+ *z__, integer *ldz, doublecomplex *work, integer *lwork, doublereal *
+ rwork, integer *lrwork, integer *iwork, integer *liwork, integer *
+ info);
+
+/* Subroutine */ int zhpgvx_(integer *itype, char *jobz, char *range, char *
+ uplo, integer *n, doublecomplex *ap, doublecomplex *bp, doublereal *
+ vl, doublereal *vu, integer *il, integer *iu, doublereal *abstol,
+ integer *m, doublereal *w, doublecomplex *z__, integer *ldz,
+ doublecomplex *work, doublereal *rwork, integer *iwork, integer *
+ ifail, integer *info);
+
+/* Subroutine */ int zhprfs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *ap, doublecomplex *afp, integer *ipiv, doublecomplex *
+ b, integer *ldb, doublecomplex *x, integer *ldx, doublereal *ferr,
+ doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int zhpsv_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zhpsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublecomplex *ap, doublecomplex *afp, integer *ipiv,
+ doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+ doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+ work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zhptrd_(char *uplo, integer *n, doublecomplex *ap,
+ doublereal *d__, doublereal *e, doublecomplex *tau, integer *info);
+
+/* Subroutine */ int zhptrf_(char *uplo, integer *n, doublecomplex *ap,
+ integer *ipiv, integer *info);
+
+/* Subroutine */ int zhptri_(char *uplo, integer *n, doublecomplex *ap,
+ integer *ipiv, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zhptrs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zhsein_(char *side, char *eigsrc, char *initv, logical *
+ select, integer *n, doublecomplex *h__, integer *ldh, doublecomplex *
+ w, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *ldvr,
+ integer *mm, integer *m, doublecomplex *work, doublereal *rwork,
+ integer *ifaill, integer *ifailr, integer *info);
+
+/* Subroutine */ int zhseqr_(char *job, char *compz, integer *n, integer *ilo,
+ integer *ihi, doublecomplex *h__, integer *ldh, doublecomplex *w,
+ doublecomplex *z__, integer *ldz, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zlabrd_(integer *m, integer *n, integer *nb,
+ doublecomplex *a, integer *lda, doublereal *d__, doublereal *e,
+ doublecomplex *tauq, doublecomplex *taup, doublecomplex *x, integer *
+ ldx, doublecomplex *y, integer *ldy);
+
+/* Subroutine */ int zlacgv_(integer *n, doublecomplex *x, integer *incx);
+
+/* Subroutine */ int zlacon_(integer *n, doublecomplex *v, doublecomplex *x,
+ doublereal *est, integer *kase);
+
+/* Subroutine */ int zlacp2_(char *uplo, integer *m, integer *n, doublereal *
+ a, integer *lda, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zlacpy_(char *uplo, integer *m, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zlacrm_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublereal *b, integer *ldb, doublecomplex *c__,
+ integer *ldc, doublereal *rwork);
+
+/* Subroutine */ int zlacrt_(integer *n, doublecomplex *cx, integer *incx,
+ doublecomplex *cy, integer *incy, doublecomplex *c__, doublecomplex *
+ s);
+
+/* Subroutine */ int zlaed0_(integer *qsiz, integer *n, doublereal *d__,
+ doublereal *e, doublecomplex *q, integer *ldq, doublecomplex *qstore,
+ integer *ldqs, doublereal *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zlaed7_(integer *n, integer *cutpnt, integer *qsiz,
+ integer *tlvls, integer *curlvl, integer *curpbm, doublereal *d__,
+ doublecomplex *q, integer *ldq, doublereal *rho, integer *indxq,
+ doublereal *qstore, integer *qptr, integer *prmptr, integer *perm,
+ integer *givptr, integer *givcol, doublereal *givnum, doublecomplex *
+ work, doublereal *rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zlaed8_(integer *k, integer *n, integer *qsiz,
+ doublecomplex *q, integer *ldq, doublereal *d__, doublereal *rho,
+ integer *cutpnt, doublereal *z__, doublereal *dlamda, doublecomplex *
+ q2, integer *ldq2, doublereal *w, integer *indxp, integer *indx,
+ integer *indxq, integer *perm, integer *givptr, integer *givcol,
+ doublereal *givnum, integer *info);
+
+/* Subroutine */ int zlaein_(logical *rightv, logical *noinit, integer *n,
+ doublecomplex *h__, integer *ldh, doublecomplex *w, doublecomplex *v,
+ doublecomplex *b, integer *ldb, doublereal *rwork, doublereal *eps3,
+ doublereal *smlnum, integer *info);
+
+/* Subroutine */ int zlaesy_(doublecomplex *a, doublecomplex *b,
+ doublecomplex *c__, doublecomplex *rt1, doublecomplex *rt2,
+ doublecomplex *evscal, doublecomplex *cs1, doublecomplex *sn1);
+
+/* Subroutine */ int zlaev2_(doublecomplex *a, doublecomplex *b,
+ doublecomplex *c__, doublereal *rt1, doublereal *rt2, doublereal *cs1,
+ doublecomplex *sn1);
+
+/* Subroutine */ int zlags2_(logical *upper, doublereal *a1, doublecomplex *
+ a2, doublereal *a3, doublereal *b1, doublecomplex *b2, doublereal *b3,
+ doublereal *csu, doublecomplex *snu, doublereal *csv, doublecomplex *
+ snv, doublereal *csq, doublecomplex *snq);
+
+/* Subroutine */ int zlagtm_(char *trans, integer *n, integer *nrhs,
+ doublereal *alpha, doublecomplex *dl, doublecomplex *d__,
+ doublecomplex *du, doublecomplex *x, integer *ldx, doublereal *beta,
+ doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zlahef_(char *uplo, integer *n, integer *nb, integer *kb,
+ doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *w,
+ integer *ldw, integer *info);
+
+/* Subroutine */ int zlahqr_(logical *wantt, logical *wantz, integer *n,
+ integer *ilo, integer *ihi, doublecomplex *h__, integer *ldh,
+ doublecomplex *w, integer *iloz, integer *ihiz, doublecomplex *z__,
+ integer *ldz, integer *info);
+
+/* Subroutine */ int zlahrd_(integer *n, integer *k, integer *nb,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *t,
+ integer *ldt, doublecomplex *y, integer *ldy);
+
+/* Subroutine */ int zlaic1_(integer *job, integer *j, doublecomplex *x,
+ doublereal *sest, doublecomplex *w, doublecomplex *gamma, doublereal *
+ sestpr, doublecomplex *s, doublecomplex *c__);
+
+/* Subroutine */ int zlals0_(integer *icompq, integer *nl, integer *nr,
+ integer *sqre, integer *nrhs, doublecomplex *b, integer *ldb,
+ doublecomplex *bx, integer *ldbx, integer *perm, integer *givptr,
+ integer *givcol, integer *ldgcol, doublereal *givnum, integer *ldgnum,
+ doublereal *poles, doublereal *difl, doublereal *difr, doublereal *
+ z__, integer *k, doublereal *c__, doublereal *s, doublereal *rwork,
+ integer *info);
+
+/* Subroutine */ int zlalsa_(integer *icompq, integer *smlsiz, integer *n,
+ integer *nrhs, doublecomplex *b, integer *ldb, doublecomplex *bx,
+ integer *ldbx, doublereal *u, integer *ldu, doublereal *vt, integer *
+ k, doublereal *difl, doublereal *difr, doublereal *z__, doublereal *
+ poles, integer *givptr, integer *givcol, integer *ldgcol, integer *
+ perm, doublereal *givnum, doublereal *c__, doublereal *s, doublereal *
+ rwork, integer *iwork, integer *info);
+
+/* Subroutine */ int zlapll_(integer *n, doublecomplex *x, integer *incx,
+ doublecomplex *y, integer *incy, doublereal *ssmin);
+
+/* Subroutine */ int zlapmt_(logical *forwrd, integer *m, integer *n,
+ doublecomplex *x, integer *ldx, integer *k);
+
+/* Subroutine */ int zlaqgb_(integer *m, integer *n, integer *kl, integer *ku,
+ doublecomplex *ab, integer *ldab, doublereal *r__, doublereal *c__,
+ doublereal *rowcnd, doublereal *colcnd, doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqge_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublereal *r__, doublereal *c__, doublereal *rowcnd,
+ doublereal *colcnd, doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqhb_(char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, doublereal *s, doublereal *scond,
+ doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqhe_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, doublereal *s, doublereal *scond, doublereal *amax,
+ char *equed);
+
+/* Subroutine */ int zlaqhp_(char *uplo, integer *n, doublecomplex *ap,
+ doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqp2_(integer *m, integer *n, integer *offset,
+ doublecomplex *a, integer *lda, integer *jpvt, doublecomplex *tau,
+ doublereal *vn1, doublereal *vn2, doublecomplex *work);
+
+/* Subroutine */ int zlaqps_(integer *m, integer *n, integer *offset, integer
+ *nb, integer *kb, doublecomplex *a, integer *lda, integer *jpvt,
+ doublecomplex *tau, doublereal *vn1, doublereal *vn2, doublecomplex *
+ auxv, doublecomplex *f, integer *ldf);
+
+/* Subroutine */ int zlaqsb_(char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, doublereal *s, doublereal *scond,
+ doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqsp_(char *uplo, integer *n, doublecomplex *ap,
+ doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+
+/* Subroutine */ int zlaqsy_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, doublereal *s, doublereal *scond, doublereal *amax,
+ char *equed);
+
+/* Subroutine */ int zlar1v_(integer *n, integer *b1, integer *bn, doublereal
+ *sigma, doublereal *d__, doublereal *l, doublereal *ld, doublereal *
+ lld, doublereal *gersch, doublecomplex *z__, doublereal *ztz,
+ doublereal *mingma, integer *r__, integer *isuppz, doublereal *work);
+
+/* Subroutine */ int zlar2v_(integer *n, doublecomplex *x, doublecomplex *y,
+ doublecomplex *z__, integer *incx, doublereal *c__, doublecomplex *s,
+ integer *incc);
+
+/* Subroutine */ int zlarcm_(integer *m, integer *n, doublereal *a, integer *
+ lda, doublecomplex *b, integer *ldb, doublecomplex *c__, integer *ldc,
+ doublereal *rwork);
+
+/* Subroutine */ int zlarf_(char *side, integer *m, integer *n, doublecomplex
+ *v, integer *incv, doublecomplex *tau, doublecomplex *c__, integer *
+ ldc, doublecomplex *work);
+
+/* Subroutine */ int zlarfb_(char *side, char *trans, char *direct, char *
+ storev, integer *m, integer *n, integer *k, doublecomplex *v, integer
+ *ldv, doublecomplex *t, integer *ldt, doublecomplex *c__, integer *
+ ldc, doublecomplex *work, integer *ldwork);
+
+/* Subroutine */ int zlarfg_(integer *n, doublecomplex *alpha, doublecomplex *
+ x, integer *incx, doublecomplex *tau);
+
+/* Subroutine */ int zlarft_(char *direct, char *storev, integer *n, integer *
+ k, doublecomplex *v, integer *ldv, doublecomplex *tau, doublecomplex *
+ t, integer *ldt);
+
+/* Subroutine */ int zlarfx_(char *side, integer *m, integer *n,
+ doublecomplex *v, doublecomplex *tau, doublecomplex *c__, integer *
+ ldc, doublecomplex *work);
+
+/* Subroutine */ int zlargv_(integer *n, doublecomplex *x, integer *incx,
+ doublecomplex *y, integer *incy, doublereal *c__, integer *incc);
+
+/* Subroutine */ int zlarnv_(integer *idist, integer *iseed, integer *n,
+ doublecomplex *x);
+
+/* Subroutine */ int zlarrv_(integer *n, doublereal *d__, doublereal *l,
+ integer *isplit, integer *m, doublereal *w, integer *iblock,
+ doublereal *gersch, doublereal *tol, doublecomplex *z__, integer *ldz,
+ integer *isuppz, doublereal *work, integer *iwork, integer *info);
+
+/* Subroutine */ int zlartg_(doublecomplex *f, doublecomplex *g, doublereal *
+ cs, doublecomplex *sn, doublecomplex *r__);
+
+/* Subroutine */ int zlartv_(integer *n, doublecomplex *x, integer *incx,
+ doublecomplex *y, integer *incy, doublereal *c__, doublecomplex *s,
+ integer *incc);
+
+/* Subroutine */ int zlarz_(char *side, integer *m, integer *n, integer *l,
+ doublecomplex *v, integer *incv, doublecomplex *tau, doublecomplex *
+ c__, integer *ldc, doublecomplex *work);
+
+/* Subroutine */ int zlarzb_(char *side, char *trans, char *direct, char *
+ storev, integer *m, integer *n, integer *k, integer *l, doublecomplex
+ *v, integer *ldv, doublecomplex *t, integer *ldt, doublecomplex *c__,
+ integer *ldc, doublecomplex *work, integer *ldwork);
+
+/* Subroutine */ int zlarzt_(char *direct, char *storev, integer *n, integer *
+ k, doublecomplex *v, integer *ldv, doublecomplex *tau, doublecomplex *
+ t, integer *ldt);
+
+/* Subroutine */ int zlascl_(char *type__, integer *kl, integer *ku,
+ doublereal *cfrom, doublereal *cto, integer *m, integer *n,
+ doublecomplex *a, integer *lda, integer *info);
+
+/* Subroutine */ int zlaset_(char *uplo, integer *m, integer *n,
+ doublecomplex *alpha, doublecomplex *beta, doublecomplex *a, integer *
+ lda);
+
+/* Subroutine */ int zlasr_(char *side, char *pivot, char *direct, integer *m,
+ integer *n, doublereal *c__, doublereal *s, doublecomplex *a,
+ integer *lda);
+
+/* Subroutine */ int zlassq_(integer *n, doublecomplex *x, integer *incx,
+ doublereal *scale, doublereal *sumsq);
+
+/* Subroutine */ int zlaswp_(integer *n, doublecomplex *a, integer *lda,
+ integer *k1, integer *k2, integer *ipiv, integer *incx);
+
+/* Subroutine */ int zlasyf_(char *uplo, integer *n, integer *nb, integer *kb,
+ doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *w,
+ integer *ldw, integer *info);
+
+/* Subroutine */ int zlatbs_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, integer *kd, doublecomplex *ab, integer *ldab,
+ doublecomplex *x, doublereal *scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int zlatdf_(integer *ijob, integer *n, doublecomplex *z__,
+ integer *ldz, doublecomplex *rhs, doublereal *rdsum, doublereal *
+ rdscal, integer *ipiv, integer *jpiv);
+
+/* Subroutine */ int zlatps_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, doublecomplex *ap, doublecomplex *x, doublereal *
+ scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int zlatrd_(char *uplo, integer *n, integer *nb,
+ doublecomplex *a, integer *lda, doublereal *e, doublecomplex *tau,
+ doublecomplex *w, integer *ldw);
+
+/* Subroutine */ int zlatrs_(char *uplo, char *trans, char *diag, char *
+ normin, integer *n, doublecomplex *a, integer *lda, doublecomplex *x,
+ doublereal *scale, doublereal *cnorm, integer *info);
+
+/* Subroutine */ int zlatrz_(integer *m, integer *n, integer *l,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work);
+
+/* Subroutine */ int zlatzm_(char *side, integer *m, integer *n,
+ doublecomplex *v, integer *incv, doublecomplex *tau, doublecomplex *
+ c1, doublecomplex *c2, integer *ldc, doublecomplex *work);
+
+/* Subroutine */ int zlauu2_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *info);
+
+/* Subroutine */ int zlauum_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *info);
+
+/* Subroutine */ int zpbcon_(char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, doublereal *anorm, doublereal *
+ rcond, doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zpbequ_(char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, doublereal *s, doublereal *scond,
+ doublereal *amax, integer *info);
+
+/* Subroutine */ int zpbrfs_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, doublecomplex *ab, integer *ldab, doublecomplex *afb, integer *
+ ldafb, doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+ doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+ rwork, integer *info);
+
+/* Subroutine */ int zpbstf_(char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, integer *info);
+
+/* Subroutine */ int zpbsv_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, doublecomplex *ab, integer *ldab, doublecomplex *b, integer *
+ ldb, integer *info);
+
+/* Subroutine */ int zpbsvx_(char *fact, char *uplo, integer *n, integer *kd,
+ integer *nrhs, doublecomplex *ab, integer *ldab, doublecomplex *afb,
+ integer *ldafb, char *equed, doublereal *s, doublecomplex *b, integer
+ *ldb, doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *
+ ferr, doublereal *berr, doublecomplex *work, doublereal *rwork,
+ integer *info);
+
+/* Subroutine */ int zpbtf2_(char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, integer *info);
+
+/* Subroutine */ int zpbtrf_(char *uplo, integer *n, integer *kd,
+ doublecomplex *ab, integer *ldab, integer *info);
+
+/* Subroutine */ int zpbtrs_(char *uplo, integer *n, integer *kd, integer *
+ nrhs, doublecomplex *ab, integer *ldab, doublecomplex *b, integer *
+ ldb, integer *info);
+
+/* Subroutine */ int zpocon_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, doublereal *anorm, doublereal *rcond, doublecomplex *
+ work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zpoequ_(integer *n, doublecomplex *a, integer *lda,
+ doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int zporfs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf,
+ doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+ doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+ rwork, integer *info);
+
+/* Subroutine */ int zposv_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zposvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+ ldaf, char *equed, doublereal *s, doublecomplex *b, integer *ldb,
+ doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *ferr,
+ doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int zpotf2_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *info);
+
+/* Subroutine */ int zpotrf_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *info);
+
+/* Subroutine */ int zpotri_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *info);
+
+/* Subroutine */ int zpotrs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zppcon_(char *uplo, integer *n, doublecomplex *ap,
+ doublereal *anorm, doublereal *rcond, doublecomplex *work, doublereal
+ *rwork, integer *info);
+
+/* Subroutine */ int zppequ_(char *uplo, integer *n, doublecomplex *ap,
+ doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+
+/* Subroutine */ int zpprfs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *ap, doublecomplex *afp, doublecomplex *b, integer *ldb,
+ doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr,
+ doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zppsv_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *ap, doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int zppsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublecomplex *ap, doublecomplex *afp, char *equed, doublereal *
+ s, doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+ doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+ work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zpptrf_(char *uplo, integer *n, doublecomplex *ap,
+ integer *info);
+
+/* Subroutine */ int zpptri_(char *uplo, integer *n, doublecomplex *ap,
+ integer *info);
+
+/* Subroutine */ int zpptrs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *ap, doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int zptcon_(integer *n, doublereal *d__, doublecomplex *e,
+ doublereal *anorm, doublereal *rcond, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int zptrfs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *d__, doublecomplex *e, doublereal *df, doublecomplex *ef,
+ doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+ doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+ rwork, integer *info);
+
+/* Subroutine */ int zptsv_(integer *n, integer *nrhs, doublereal *d__,
+ doublecomplex *e, doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int zptsvx_(char *fact, integer *n, integer *nrhs,
+ doublereal *d__, doublecomplex *e, doublereal *df, doublecomplex *ef,
+ doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+ doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+ work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zpttrf_(integer *n, doublereal *d__, doublecomplex *e,
+ integer *info);
+
+/* Subroutine */ int zpttrs_(char *uplo, integer *n, integer *nrhs,
+ doublereal *d__, doublecomplex *e, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zptts2_(integer *iuplo, integer *n, integer *nrhs,
+ doublereal *d__, doublecomplex *e, doublecomplex *b, integer *ldb);
+
+/* Subroutine */ int zrot_(integer *n, doublecomplex *cx, integer *incx,
+ doublecomplex *cy, integer *incy, doublereal *c__, doublecomplex *s);
+
+/* Subroutine */ int zspcon_(char *uplo, integer *n, doublecomplex *ap,
+ integer *ipiv, doublereal *anorm, doublereal *rcond, doublecomplex *
+ work, integer *info);
+
+/* Subroutine */ int zspmv_(char *uplo, integer *n, doublecomplex *alpha,
+ doublecomplex *ap, doublecomplex *x, integer *incx, doublecomplex *
+ beta, doublecomplex *y, integer *incy);
+
+/* Subroutine */ int zspr_(char *uplo, integer *n, doublecomplex *alpha,
+ doublecomplex *x, integer *incx, doublecomplex *ap);
+
+/* Subroutine */ int zsprfs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *ap, doublecomplex *afp, integer *ipiv, doublecomplex *
+ b, integer *ldb, doublecomplex *x, integer *ldx, doublereal *ferr,
+ doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int zspsv_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zspsvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublecomplex *ap, doublecomplex *afp, integer *ipiv,
+ doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+ doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+ work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zsptrf_(char *uplo, integer *n, doublecomplex *ap,
+ integer *ipiv, integer *info);
+
+/* Subroutine */ int zsptri_(char *uplo, integer *n, doublecomplex *ap,
+ integer *ipiv, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zsptrs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int zstedc_(char *compz, integer *n, doublereal *d__,
+ doublereal *e, doublecomplex *z__, integer *ldz, doublecomplex *work,
+ integer *lwork, doublereal *rwork, integer *lrwork, integer *iwork,
+ integer *liwork, integer *info);
+
+/* Subroutine */ int zstein_(integer *n, doublereal *d__, doublereal *e,
+ integer *m, doublereal *w, integer *iblock, integer *isplit,
+ doublecomplex *z__, integer *ldz, doublereal *work, integer *iwork,
+ integer *ifail, integer *info);
+
+/* Subroutine */ int zsteqr_(char *compz, integer *n, doublereal *d__,
+ doublereal *e, doublecomplex *z__, integer *ldz, doublereal *work,
+ integer *info);
+
+/* Subroutine */ int zsycon_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, doublereal *anorm, doublereal *rcond,
+ doublecomplex *work, integer *info);
+
+/* Subroutine */ int zsymv_(char *uplo, integer *n, doublecomplex *alpha,
+ doublecomplex *a, integer *lda, doublecomplex *x, integer *incx,
+ doublecomplex *beta, doublecomplex *y, integer *incy);
+
+/* Subroutine */ int zsyr_(char *uplo, integer *n, doublecomplex *alpha,
+ doublecomplex *x, integer *incx, doublecomplex *a, integer *lda);
+
+/* Subroutine */ int zsyrfs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf,
+ integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x,
+ integer *ldx, doublereal *ferr, doublereal *berr, doublecomplex *work,
+ doublereal *rwork, integer *info);
+
+/* Subroutine */ int zsysv_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b,
+ integer *ldb, doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int zsysvx_(char *fact, char *uplo, integer *n, integer *
+ nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+ ldaf, integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x,
+ integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *berr,
+ doublecomplex *work, integer *lwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int zsytf2_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, integer *info);
+
+/* Subroutine */ int zsytrf_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zsytri_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, integer *ipiv, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zsytrs_(char *uplo, integer *n, integer *nrhs,
+ doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b,
+ integer *ldb, integer *info);
+
+/* Subroutine */ int ztbcon_(char *norm, char *uplo, char *diag, integer *n,
+ integer *kd, doublecomplex *ab, integer *ldab, doublereal *rcond,
+ doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztbrfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *kd, integer *nrhs, doublecomplex *ab, integer *ldab,
+ doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+ doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+ rwork, integer *info);
+
+/* Subroutine */ int ztbtrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *kd, integer *nrhs, doublecomplex *ab, integer *ldab,
+ doublecomplex *b, integer *ldb, integer *info);
+
+/* Subroutine */ int ztgevc_(char *side, char *howmny, logical *select,
+ integer *n, doublecomplex *a, integer *lda, doublecomplex *b, integer
+ *ldb, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *
+ ldvr, integer *mm, integer *m, doublecomplex *work, doublereal *rwork,
+ integer *info);
+
+/* Subroutine */ int ztgex2_(logical *wantq, logical *wantz, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *q, integer *ldq, doublecomplex *z__, integer *ldz,
+ integer *j1, integer *info);
+
+/* Subroutine */ int ztgexc_(logical *wantq, logical *wantz, integer *n,
+ doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *q, integer *ldq, doublecomplex *z__, integer *ldz,
+ integer *ifst, integer *ilst, integer *info);
+
+/* Subroutine */ int ztgsen_(integer *ijob, logical *wantq, logical *wantz,
+ logical *select, integer *n, doublecomplex *a, integer *lda,
+ doublecomplex *b, integer *ldb, doublecomplex *alpha, doublecomplex *
+ beta, doublecomplex *q, integer *ldq, doublecomplex *z__, integer *
+ ldz, integer *m, doublereal *pl, doublereal *pr, doublereal *dif,
+ doublecomplex *work, integer *lwork, integer *iwork, integer *liwork,
+ integer *info);
+
+/* Subroutine */ int ztgsja_(char *jobu, char *jobv, char *jobq, integer *m,
+ integer *p, integer *n, integer *k, integer *l, doublecomplex *a,
+ integer *lda, doublecomplex *b, integer *ldb, doublereal *tola,
+ doublereal *tolb, doublereal *alpha, doublereal *beta, doublecomplex *
+ u, integer *ldu, doublecomplex *v, integer *ldv, doublecomplex *q,
+ integer *ldq, doublecomplex *work, integer *ncycle, integer *info);
+
+/* Subroutine */ int ztgsna_(char *job, char *howmny, logical *select,
+ integer *n, doublecomplex *a, integer *lda, doublecomplex *b, integer
+ *ldb, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *
+ ldvr, doublereal *s, doublereal *dif, integer *mm, integer *m,
+ doublecomplex *work, integer *lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int ztgsy2_(char *trans, integer *ijob, integer *m, integer *
+ n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *c__, integer *ldc, doublecomplex *d__, integer *ldd,
+ doublecomplex *e, integer *lde, doublecomplex *f, integer *ldf,
+ doublereal *scale, doublereal *rdsum, doublereal *rdscal, integer *
+ info);
+
+/* Subroutine */ int ztgsyl_(char *trans, integer *ijob, integer *m, integer *
+ n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb,
+ doublecomplex *c__, integer *ldc, doublecomplex *d__, integer *ldd,
+ doublecomplex *e, integer *lde, doublecomplex *f, integer *ldf,
+ doublereal *scale, doublereal *dif, doublecomplex *work, integer *
+ lwork, integer *iwork, integer *info);
+
+/* Subroutine */ int ztpcon_(char *norm, char *uplo, char *diag, integer *n,
+ doublecomplex *ap, doublereal *rcond, doublecomplex *work, doublereal
+ *rwork, integer *info);
+
+/* Subroutine */ int ztprfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, doublecomplex *ap, doublecomplex *b, integer *ldb,
+ doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr,
+ doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztptri_(char *uplo, char *diag, integer *n,
+ doublecomplex *ap, integer *info);
+
+/* Subroutine */ int ztptrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, doublecomplex *ap, doublecomplex *b, integer *ldb,
+ integer *info);
+
+/* Subroutine */ int ztrcon_(char *norm, char *uplo, char *diag, integer *n,
+ doublecomplex *a, integer *lda, doublereal *rcond, doublecomplex *
+ work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztrevc_(char *side, char *howmny, logical *select,
+ integer *n, doublecomplex *t, integer *ldt, doublecomplex *vl,
+ integer *ldvl, doublecomplex *vr, integer *ldvr, integer *mm, integer
+ *m, doublecomplex *work, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztrexc_(char *compq, integer *n, doublecomplex *t,
+ integer *ldt, doublecomplex *q, integer *ldq, integer *ifst, integer *
+ ilst, integer *info);
+
+/* Subroutine */ int ztrrfs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, doublecomplex *a, integer *lda, doublecomplex *b,
+ integer *ldb, doublecomplex *x, integer *ldx, doublereal *ferr,
+ doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+ info);
+
+/* Subroutine */ int ztrsen_(char *job, char *compq, logical *select, integer
+ *n, doublecomplex *t, integer *ldt, doublecomplex *q, integer *ldq,
+ doublecomplex *w, integer *m, doublereal *s, doublereal *sep,
+ doublecomplex *work, integer *lwork, integer *info);
+
+/* Subroutine */ int ztrsna_(char *job, char *howmny, logical *select,
+ integer *n, doublecomplex *t, integer *ldt, doublecomplex *vl,
+ integer *ldvl, doublecomplex *vr, integer *ldvr, doublereal *s,
+ doublereal *sep, integer *mm, integer *m, doublecomplex *work,
+ integer *ldwork, doublereal *rwork, integer *info);
+
+/* Subroutine */ int ztrsyl_(char *trana, char *tranb, integer *isgn, integer
+ *m, integer *n, doublecomplex *a, integer *lda, doublecomplex *b,
+ integer *ldb, doublecomplex *c__, integer *ldc, doublereal *scale,
+ integer *info);
+
+/* Subroutine */ int ztrti2_(char *uplo, char *diag, integer *n,
+ doublecomplex *a, integer *lda, integer *info);
+
+/* Subroutine */ int ztrtri_(char *uplo, char *diag, integer *n,
+ doublecomplex *a, integer *lda, integer *info);
+
+/* Subroutine */ int ztrtrs_(char *uplo, char *trans, char *diag, integer *n,
+ integer *nrhs, doublecomplex *a, integer *lda, doublecomplex *b,
+ integer *ldb, integer *info);
+
+/* Subroutine */ int ztzrqf_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, integer *info);
+
+/* Subroutine */ int ztzrzf_(integer *m, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zung2l_(integer *m, integer *n, integer *k,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *info);
+
+/* Subroutine */ int zung2r_(integer *m, integer *n, integer *k,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *info);
+
+/* Subroutine */ int zungbr_(char *vect, integer *m, integer *n, integer *k,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int zunghr_(integer *n, integer *ilo, integer *ihi,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungl2_(integer *m, integer *n, integer *k,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *info);
+
+/* Subroutine */ int zunglq_(integer *m, integer *n, integer *k,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungql_(integer *m, integer *n, integer *k,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungqr_(integer *m, integer *n, integer *k,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungr2_(integer *m, integer *n, integer *k,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *info);
+
+/* Subroutine */ int zungrq_(integer *m, integer *n, integer *k,
+ doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int zungtr_(char *uplo, integer *n, doublecomplex *a,
+ integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zunm2l_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublecomplex *a, integer *lda, doublecomplex *tau,
+ doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zunm2r_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublecomplex *a, integer *lda, doublecomplex *tau,
+ doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zunmbr_(char *vect, char *side, char *trans, integer *m,
+ integer *n, integer *k, doublecomplex *a, integer *lda, doublecomplex
+ *tau, doublecomplex *c__, integer *ldc, doublecomplex *work, integer *
+ lwork, integer *info);
+
+/* Subroutine */ int zunmhr_(char *side, char *trans, integer *m, integer *n,
+ integer *ilo, integer *ihi, doublecomplex *a, integer *lda,
+ doublecomplex *tau, doublecomplex *c__, integer *ldc, doublecomplex *
+ work, integer *lwork, integer *info);
+
+/* Subroutine */ int zunml2_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublecomplex *a, integer *lda, doublecomplex *tau,
+ doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zunmlq_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublecomplex *a, integer *lda, doublecomplex *tau,
+ doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zunmql_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublecomplex *a, integer *lda, doublecomplex *tau,
+ doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zunmqr_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublecomplex *a, integer *lda, doublecomplex *tau,
+ doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zunmr2_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublecomplex *a, integer *lda, doublecomplex *tau,
+ doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+
+/* Subroutine */ int zunmr3_(char *side, char *trans, integer *m, integer *n,
+ integer *k, integer *l, doublecomplex *a, integer *lda, doublecomplex
+ *tau, doublecomplex *c__, integer *ldc, doublecomplex *work, integer *
+ info);
+
+/* Subroutine */ int zunmrq_(char *side, char *trans, integer *m, integer *n,
+ integer *k, doublecomplex *a, integer *lda, doublecomplex *tau,
+ doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zunmrz_(char *side, char *trans, integer *m, integer *n,
+ integer *k, integer *l, doublecomplex *a, integer *lda, doublecomplex
+ *tau, doublecomplex *c__, integer *ldc, doublecomplex *work, integer *
+ lwork, integer *info);
+
+/* Subroutine */ int zunmtr_(char *side, char *uplo, char *trans, integer *m,
+ integer *n, doublecomplex *a, integer *lda, doublecomplex *tau,
+ doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+ integer *info);
+
+/* Subroutine */ int zupgtr_(char *uplo, integer *n, doublecomplex *ap,
+ doublecomplex *tau, doublecomplex *q, integer *ldq, doublecomplex *
+ work, integer *info);
+
+/* Subroutine */ int zupmtr_(char *side, char *uplo, char *trans, integer *m,
+ integer *n, doublecomplex *ap, doublecomplex *tau, doublecomplex *c__,
+ integer *ldc, doublecomplex *work, integer *info);
+
+#endif /* __CLAPACK_H */
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/close.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/close.c
new file mode 100644
index 00000000..d305ccf8
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/close.c
@@ -0,0 +1,80 @@
+#include "f2c.h"
+#include "fio.h"
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#ifdef NON_UNIX_STDIO
+#ifndef unlink
+#define unlink remove
+#endif
+#else
+#ifdef MSDOS
+#include "io.h"
+#else
+#ifdef __cplusplus
+extern "C" int unlink(const char*);
+#else
+extern int unlink(const char*);
+#endif
+#endif
+#endif
+
+integer f_clos(cllist *a)
+{ unit *b;
+
+ if(a->cunit >= MXUNIT) return(0);
+ b= &f__units[a->cunit];
+ if(b->ufd==NULL)
+ goto done;
+ if (b->uscrtch == 1)
+ goto Delete;
+ if (!a->csta)
+ goto Keep;
+ switch(*a->csta) {
+ default:
+ Keep:
+ case 'k':
+ case 'K':
+ if(b->uwrt == 1)
+ t_runc((alist *)a);
+ if(b->ufnm) {
+ fclose(b->ufd);
+ free(b->ufnm);
+ }
+ break;
+ case 'd':
+ case 'D':
+ Delete:
+ fclose(b->ufd);
+ if(b->ufnm) {
+ unlink(b->ufnm); /*SYSDEP*/
+ free(b->ufnm);
+ }
+ }
+ b->ufd=NULL;
+ done:
+ b->uend=0;
+ b->ufnm=NULL;
+ return(0);
+ }
+void f_exit(void)
+{ int i;
+ static cllist xx;
+ if (!xx.cerr) {
+ xx.cerr=1;
+ xx.csta=NULL;
+ for(i=0;i<MXUNIT;i++)
+ {
+ xx.cunit=i;
+ (void) f_clos(&xx);
+ }
+ }
+}
+int flush_(void)
+{ int i;
+ for(i=0;i<MXUNIT;i++)
+ if(f__units[i].ufd != NULL && f__units[i].uwrt)
+ fflush(f__units[i].ufd);
+return 0;
+}
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgemm.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgemm.c
new file mode 100644
index 00000000..964a278a
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgemm.c
@@ -0,0 +1,313 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dgemm_(char *transa, char *transb, integer *m, integer *
+ n, integer *k, doublereal *alpha, doublereal *a, integer *lda,
+ doublereal *b, integer *ldb, doublereal *beta, doublereal *c__,
+ integer *ldc)
+{
+ /* System generated locals */
+ integer a_dim1, a_offset, b_dim1, b_offset, c_dim1, c_offset, i__1, i__2,
+ i__3;
+ /* Local variables */
+ static integer info;
+ static logical nota, notb;
+ static doublereal temp;
+ static integer i__, j, l, ncola;
+ extern logical lsame_(char *, char *);
+ static integer nrowa, nrowb;
+ extern /* Subroutine */ int xerbla_(char *, integer *);
+#define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1]
+#define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1]
+#define c___ref(a_1,a_2) c__[(a_2)*c_dim1 + a_1]
+/* Purpose
+ =======
+ DGEMM performs one of the matrix-matrix operations
+ C := alpha*op( A )*op( B ) + beta*C,
+ where op( X ) is one of
+ op( X ) = X or op( X ) = X',
+ alpha and beta are scalars, and A, B and C are matrices, with op( A )
+ an m by k matrix, op( B ) a k by n matrix and C an m by n matrix.
+ Parameters
+ ==========
+ TRANSA - CHARACTER*1.
+ On entry, TRANSA specifies the form of op( A ) to be used in
+ the matrix multiplication as follows:
+ TRANSA = 'N' or 'n', op( A ) = A.
+ TRANSA = 'T' or 't', op( A ) = A'.
+ TRANSA = 'C' or 'c', op( A ) = A'.
+ Unchanged on exit.
+ TRANSB - CHARACTER*1.
+ On entry, TRANSB specifies the form of op( B ) to be used in
+ the matrix multiplication as follows:
+ TRANSB = 'N' or 'n', op( B ) = B.
+ TRANSB = 'T' or 't', op( B ) = B'.
+ TRANSB = 'C' or 'c', op( B ) = B'.
+ Unchanged on exit.
+ M - INTEGER.
+ On entry, M specifies the number of rows of the matrix
+ op( A ) and of the matrix C. M must be at least zero.
+ Unchanged on exit.
+ N - INTEGER.
+ On entry, N specifies the number of columns of the matrix
+ op( B ) and the number of columns of the matrix C. N must be
+ at least zero.
+ Unchanged on exit.
+ K - INTEGER.
+ On entry, K specifies the number of columns of the matrix
+ op( A ) and the number of rows of the matrix op( B ). K must
+ be at least zero.
+ Unchanged on exit.
+ ALPHA - DOUBLE PRECISION.
+ On entry, ALPHA specifies the scalar alpha.
+ Unchanged on exit.
+ A - DOUBLE PRECISION array of DIMENSION ( LDA, ka ), where ka is
+ k when TRANSA = 'N' or 'n', and is m otherwise.
+ Before entry with TRANSA = 'N' or 'n', the leading m by k
+ part of the array A must contain the matrix A, otherwise
+ the leading k by m part of the array A must contain the
+ matrix A.
+ Unchanged on exit.
+ LDA - INTEGER.
+ On entry, LDA specifies the first dimension of A as declared
+ in the calling (sub) program. When TRANSA = 'N' or 'n' then
+ LDA must be at least max( 1, m ), otherwise LDA must be at
+ least max( 1, k ).
+ Unchanged on exit.
+ B - DOUBLE PRECISION array of DIMENSION ( LDB, kb ), where kb is
+ n when TRANSB = 'N' or 'n', and is k otherwise.
+ Before entry with TRANSB = 'N' or 'n', the leading k by n
+ part of the array B must contain the matrix B, otherwise
+ the leading n by k part of the array B must contain the
+ matrix B.
+ Unchanged on exit.
+ LDB - INTEGER.
+ On entry, LDB specifies the first dimension of B as declared
+ in the calling (sub) program. When TRANSB = 'N' or 'n' then
+ LDB must be at least max( 1, k ), otherwise LDB must be at
+ least max( 1, n ).
+ Unchanged on exit.
+ BETA - DOUBLE PRECISION.
+ On entry, BETA specifies the scalar beta. When BETA is
+ supplied as zero then C need not be set on input.
+ Unchanged on exit.
+ C - DOUBLE PRECISION array of DIMENSION ( LDC, n ).
+ Before entry, the leading m by n part of the array C must
+ contain the matrix C, except when beta is zero, in which
+ case C need not be set on entry.
+ On exit, the array C is overwritten by the m by n matrix
+ ( alpha*op( A )*op( B ) + beta*C ).
+ LDC - INTEGER.
+ On entry, LDC specifies the first dimension of C as declared
+ in the calling (sub) program. LDC must be at least
+ max( 1, m ).
+ Unchanged on exit.
+ Level 3 Blas routine.
+ -- Written on 8-February-1989.
+ Jack Dongarra, Argonne National Laboratory.
+ Iain Duff, AERE Harwell.
+ Jeremy Du Croz, Numerical Algorithms Group Ltd.
+ Sven Hammarling, Numerical Algorithms Group Ltd.
+ Set NOTA and NOTB as true if A and B respectively are not
+ transposed and set NROWA, NCOLA and NROWB as the number of rows
+ and columns of A and the number of rows of B respectively.
+ Parameter adjustments */
+ a_dim1 = *lda;
+ a_offset = 1 + a_dim1 * 1;
+ a -= a_offset;
+ b_dim1 = *ldb;
+ b_offset = 1 + b_dim1 * 1;
+ b -= b_offset;
+ c_dim1 = *ldc;
+ c_offset = 1 + c_dim1 * 1;
+ c__ -= c_offset;
+ /* Function Body */
+ nota = lsame_(transa, "N");
+ notb = lsame_(transb, "N");
+ if (nota) {
+ nrowa = *m;
+ ncola = *k;
+ } else {
+ nrowa = *k;
+ ncola = *m;
+ }
+ if (notb) {
+ nrowb = *k;
+ } else {
+ nrowb = *n;
+ }
+/* Test the input parameters. */
+ info = 0;
+ if (! nota && ! lsame_(transa, "C") && ! lsame_(
+ transa, "T")) {
+ info = 1;
+ } else if (! notb && ! lsame_(transb, "C") && !
+ lsame_(transb, "T")) {
+ info = 2;
+ } else if (*m < 0) {
+ info = 3;
+ } else if (*n < 0) {
+ info = 4;
+ } else if (*k < 0) {
+ info = 5;
+ } else if (*lda < max(1,nrowa)) {
+ info = 8;
+ } else if (*ldb < max(1,nrowb)) {
+ info = 10;
+ } else if (*ldc < max(1,*m)) {
+ info = 13;
+ }
+ if (info != 0) {
+ xerbla_("DGEMM ", &info);
+ return 0;
+ }
+/* Quick return if possible. */
+ if (*m == 0 || *n == 0 || (*alpha == 0. || *k == 0) && *beta == 1.) {
+ return 0;
+ }
+/* And if alpha.eq.zero. */
+ if (*alpha == 0.) {
+ if (*beta == 0.) {
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ c___ref(i__, j) = 0.;
+/* L10: */
+ }
+/* L20: */
+ }
+ } else {
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ c___ref(i__, j) = *beta * c___ref(i__, j);
+/* L30: */
+ }
+/* L40: */
+ }
+ }
+ return 0;
+ }
+/* Start the operations. */
+ if (notb) {
+ if (nota) {
+/* Form C := alpha*A*B + beta*C. */
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ if (*beta == 0.) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ c___ref(i__, j) = 0.;
+/* L50: */
+ }
+ } else if (*beta != 1.) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ c___ref(i__, j) = *beta * c___ref(i__, j);
+/* L60: */
+ }
+ }
+ i__2 = *k;
+ for (l = 1; l <= i__2; ++l) {
+ if (b_ref(l, j) != 0.) {
+ temp = *alpha * b_ref(l, j);
+ i__3 = *m;
+ for (i__ = 1; i__ <= i__3; ++i__) {
+ c___ref(i__, j) = c___ref(i__, j) + temp * a_ref(
+ i__, l);
+/* L70: */
+ }
+ }
+/* L80: */
+ }
+/* L90: */
+ }
+ } else {
+/* Form C := alpha*A'*B + beta*C */
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ temp = 0.;
+ i__3 = *k;
+ for (l = 1; l <= i__3; ++l) {
+ temp += a_ref(l, i__) * b_ref(l, j);
+/* L100: */
+ }
+ if (*beta == 0.) {
+ c___ref(i__, j) = *alpha * temp;
+ } else {
+ c___ref(i__, j) = *alpha * temp + *beta * c___ref(i__,
+ j);
+ }
+/* L110: */
+ }
+/* L120: */
+ }
+ }
+ } else {
+ if (nota) {
+/* Form C := alpha*A*B' + beta*C */
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ if (*beta == 0.) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ c___ref(i__, j) = 0.;
+/* L130: */
+ }
+ } else if (*beta != 1.) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ c___ref(i__, j) = *beta * c___ref(i__, j);
+/* L140: */
+ }
+ }
+ i__2 = *k;
+ for (l = 1; l <= i__2; ++l) {
+ if (b_ref(j, l) != 0.) {
+ temp = *alpha * b_ref(j, l);
+ i__3 = *m;
+ for (i__ = 1; i__ <= i__3; ++i__) {
+ c___ref(i__, j) = c___ref(i__, j) + temp * a_ref(
+ i__, l);
+/* L150: */
+ }
+ }
+/* L160: */
+ }
+/* L170: */
+ }
+ } else {
+/* Form C := alpha*A'*B' + beta*C */
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ temp = 0.;
+ i__3 = *k;
+ for (l = 1; l <= i__3; ++l) {
+ temp += a_ref(l, i__) * b_ref(j, l);
+/* L180: */
+ }
+ if (*beta == 0.) {
+ c___ref(i__, j) = *alpha * temp;
+ } else {
+ c___ref(i__, j) = *alpha * temp + *beta * c___ref(i__,
+ j);
+ }
+/* L190: */
+ }
+/* L200: */
+ }
+ }
+ }
+ return 0;
+/* End of DGEMM . */
+} /* dgemm_ */
+#undef c___ref
+#undef b_ref
+#undef a_ref
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dger.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dger.c
new file mode 100644
index 00000000..c53835fa
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dger.c
@@ -0,0 +1,143 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dger_(integer *m, integer *n, doublereal *alpha,
+ doublereal *x, integer *incx, doublereal *y, integer *incy,
+ doublereal *a, integer *lda)
+{
+ /* System generated locals */
+ integer a_dim1, a_offset, i__1, i__2;
+ /* Local variables */
+ static integer info;
+ static doublereal temp;
+ static integer i__, j, ix, jy, kx;
+ extern /* Subroutine */ int xerbla_(char *, integer *);
+#define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1]
+/* Purpose
+ =======
+ DGER performs the rank 1 operation
+ A := alpha*x*y' + A,
+ where alpha is a scalar, x is an m element vector, y is an n element
+ vector and A is an m by n matrix.
+ Parameters
+ ==========
+ M - INTEGER.
+ On entry, M specifies the number of rows of the matrix A.
+ M must be at least zero.
+ Unchanged on exit.
+ N - INTEGER.
+ On entry, N specifies the number of columns of the matrix A.
+ N must be at least zero.
+ Unchanged on exit.
+ ALPHA - DOUBLE PRECISION.
+ On entry, ALPHA specifies the scalar alpha.
+ Unchanged on exit.
+ X - DOUBLE PRECISION array of dimension at least
+ ( 1 + ( m - 1 )*abs( INCX ) ).
+ Before entry, the incremented array X must contain the m
+ element vector x.
+ Unchanged on exit.
+ INCX - INTEGER.
+ On entry, INCX specifies the increment for the elements of
+ X. INCX must not be zero.
+ Unchanged on exit.
+ Y - DOUBLE PRECISION array of dimension at least
+ ( 1 + ( n - 1 )*abs( INCY ) ).
+ Before entry, the incremented array Y must contain the n
+ element vector y.
+ Unchanged on exit.
+ INCY - INTEGER.
+ On entry, INCY specifies the increment for the elements of
+ Y. INCY must not be zero.
+ Unchanged on exit.
+ A - DOUBLE PRECISION array of DIMENSION ( LDA, n ).
+ Before entry, the leading m by n part of the array A must
+ contain the matrix of coefficients. On exit, A is
+ overwritten by the updated matrix.
+ LDA - INTEGER.
+ On entry, LDA specifies the first dimension of A as declared
+ in the calling (sub) program. LDA must be at least
+ max( 1, m ).
+ Unchanged on exit.
+ Level 2 Blas routine.
+ -- Written on 22-October-1986.
+ Jack Dongarra, Argonne National Lab.
+ Jeremy Du Croz, Nag Central Office.
+ Sven Hammarling, Nag Central Office.
+ Richard Hanson, Sandia National Labs.
+ Test the input parameters.
+ Parameter adjustments */
+ --x;
+ --y;
+ a_dim1 = *lda;
+ a_offset = 1 + a_dim1 * 1;
+ a -= a_offset;
+ /* Function Body */
+ info = 0;
+ if (*m < 0) {
+ info = 1;
+ } else if (*n < 0) {
+ info = 2;
+ } else if (*incx == 0) {
+ info = 5;
+ } else if (*incy == 0) {
+ info = 7;
+ } else if (*lda < max(1,*m)) {
+ info = 9;
+ }
+ if (info != 0) {
+ xerbla_("DGER ", &info);
+ return 0;
+ }
+/* Quick return if possible. */
+ if (*m == 0 || *n == 0 || *alpha == 0.) {
+ return 0;
+ }
+/* Start the operations. In this version the elements of A are
+ accessed sequentially with one pass through A. */
+ if (*incy > 0) {
+ jy = 1;
+ } else {
+ jy = 1 - (*n - 1) * *incy;
+ }
+ if (*incx == 1) {
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ if (y[jy] != 0.) {
+ temp = *alpha * y[jy];
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ a_ref(i__, j) = a_ref(i__, j) + x[i__] * temp;
+/* L10: */
+ }
+ }
+ jy += *incy;
+/* L20: */
+ }
+ } else {
+ if (*incx > 0) {
+ kx = 1;
+ } else {
+ kx = 1 - (*m - 1) * *incx;
+ }
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ if (y[jy] != 0.) {
+ temp = *alpha * y[jy];
+ ix = kx;
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ a_ref(i__, j) = a_ref(i__, j) + x[ix] * temp;
+ ix += *incx;
+/* L30: */
+ }
+ }
+ jy += *incy;
+/* L40: */
+ }
+ }
+ return 0;
+/* End of DGER . */
+} /* dger_ */
+#undef a_ref
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgesv.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgesv.c
new file mode 100644
index 00000000..5c0dc52b
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgesv.c
@@ -0,0 +1,117 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dgesv_(integer *n, integer *nrhs, doublereal *a, integer
+ *lda, integer *ipiv, doublereal *b, integer *ldb, integer *info)
+{
+/* -- LAPACK driver routine (version 3.0) --
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+ Courant Institute, Argonne National Lab, and Rice University
+ March 31, 1993
+
+
+ Purpose
+ =======
+
+ DGESV computes the solution to a real system of linear equations
+ A * X = B,
+ where A is an N-by-N matrix and X and B are N-by-NRHS matrices.
+
+ The LU decomposition with partial pivoting and row interchanges is
+ used to factor A as
+ A = P * L * U,
+ where P is a permutation matrix, L is unit lower triangular, and U is
+ upper triangular. The factored form of A is then used to solve the
+ system of equations A * X = B.
+
+ Arguments
+ =========
+
+ N (input) INTEGER
+ The number of linear equations, i.e., the order of the
+ matrix A. N >= 0.
+
+ NRHS (input) INTEGER
+ The number of right hand sides, i.e., the number of columns
+ of the matrix B. NRHS >= 0.
+
+ A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+ On entry, the N-by-N coefficient matrix A.
+ On exit, the factors L and U from the factorization
+ A = P*L*U; the unit diagonal elements of L are not stored.
+
+ LDA (input) INTEGER
+ The leading dimension of the array A. LDA >= max(1,N).
+
+ IPIV (output) INTEGER array, dimension (N)
+ The pivot indices that define the permutation matrix P;
+ row i of the matrix was interchanged with row IPIV(i).
+
+ B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
+ On entry, the N-by-NRHS matrix of right hand side matrix B.
+ On exit, if INFO = 0, the N-by-NRHS solution matrix X.
+
+ LDB (input) INTEGER
+ The leading dimension of the array B. LDB >= max(1,N).
+
+ INFO (output) INTEGER
+ = 0: successful exit
+ < 0: if INFO = -i, the i-th argument had an illegal value
+ > 0: if INFO = i, U(i,i) is exactly zero. The factorization
+ has been completed, but the factor U is exactly
+ singular, so the solution could not be computed.
+
+ =====================================================================
+
+
+ Test the input parameters.
+
+ Parameter adjustments */
+ /* System generated locals */
+ integer a_dim1, a_offset, b_dim1, b_offset, i__1;
+ /* Local variables */
+ extern /* Subroutine */ int dgetrf_(integer *, integer *, doublereal *,
+ integer *, integer *, integer *), xerbla_(char *, integer *), dgetrs_(char *, integer *, integer *, doublereal *,
+ integer *, integer *, doublereal *, integer *, integer *);
+
+ a_dim1 = *lda;
+ a_offset = 1 + a_dim1 * 1;
+ a -= a_offset;
+ --ipiv;
+ b_dim1 = *ldb;
+ b_offset = 1 + b_dim1 * 1;
+ b -= b_offset;
+
+ /* Function Body */
+ *info = 0;
+ if (*n < 0) {
+ *info = -1;
+ } else if (*nrhs < 0) {
+ *info = -2;
+ } else if (*lda < max(1,*n)) {
+ *info = -4;
+ } else if (*ldb < max(1,*n)) {
+ *info = -7;
+ }
+ if (*info != 0) {
+ i__1 = -(*info);
+ xerbla_("DGESV ", &i__1);
+ return 0;
+ }
+
+/* Compute the LU factorization of A. */
+
+ dgetrf_(n, n, &a[a_offset], lda, &ipiv[1], info);
+ if (*info == 0) {
+
+/* Solve the system A*X = B, overwriting B with X. */
+
+ dgetrs_("No transpose", n, nrhs, &a[a_offset], lda, &ipiv[1], &b[
+ b_offset], ldb, info);
+ }
+ return 0;
+
+/* End of DGESV */
+
+} /* dgesv_ */
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetf2.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetf2.c
new file mode 100644
index 00000000..83bf1872
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetf2.c
@@ -0,0 +1,157 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dgetf2_(integer *m, integer *n, doublereal *a, integer *
+ lda, integer *ipiv, integer *info)
+{
+/* -- LAPACK routine (version 3.0) --
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+ Courant Institute, Argonne National Lab, and Rice University
+ June 30, 1992
+
+
+ Purpose
+ =======
+
+ DGETF2 computes an LU factorization of a general m-by-n matrix A
+ using partial pivoting with row interchanges.
+
+ The factorization has the form
+ A = P * L * U
+ where P is a permutation matrix, L is lower triangular with unit
+ diagonal elements (lower trapezoidal if m > n), and U is upper
+ triangular (upper trapezoidal if m < n).
+
+ This is the right-looking Level 2 BLAS version of the algorithm.
+
+ Arguments
+ =========
+
+ M (input) INTEGER
+ The number of rows of the matrix A. M >= 0.
+
+ N (input) INTEGER
+ The number of columns of the matrix A. N >= 0.
+
+ A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+ On entry, the m by n matrix to be factored.
+ On exit, the factors L and U from the factorization
+ A = P*L*U; the unit diagonal elements of L are not stored.
+
+ LDA (input) INTEGER
+ The leading dimension of the array A. LDA >= max(1,M).
+
+ IPIV (output) INTEGER array, dimension (min(M,N))
+ The pivot indices; for 1 <= i <= min(M,N), row i of the
+ matrix was interchanged with row IPIV(i).
+
+ INFO (output) INTEGER
+ = 0: successful exit
+ < 0: if INFO = -k, the k-th argument had an illegal value
+ > 0: if INFO = k, U(k,k) is exactly zero. The factorization
+ has been completed, but the factor U is exactly
+ singular, and division by zero will occur if it is used
+ to solve a system of equations.
+
+ =====================================================================
+
+
+ Test the input parameters.
+
+ Parameter adjustments */
+ /* Table of constant values */
+ static integer c__1 = 1;
+ static doublereal c_b6 = -1.;
+
+ /* System generated locals */
+ integer a_dim1, a_offset, i__1, i__2, i__3;
+ doublereal d__1;
+ /* Local variables */
+ extern /* Subroutine */ int dger_(integer *, integer *, doublereal *,
+ doublereal *, integer *, doublereal *, integer *, doublereal *,
+ integer *);
+ static integer j;
+ extern /* Subroutine */ int dscal_(integer *, doublereal *, doublereal *,
+ integer *), dswap_(integer *, doublereal *, integer *, doublereal
+ *, integer *);
+ static integer jp;
+ extern integer idamax_(integer *, doublereal *, integer *);
+ extern /* Subroutine */ int xerbla_(char *, integer *);
+#define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1]
+
+
+ a_dim1 = *lda;
+ a_offset = 1 + a_dim1 * 1;
+ a -= a_offset;
+ --ipiv;
+
+ /* Function Body */
+ *info = 0;
+ if (*m < 0) {
+ *info = -1;
+ } else if (*n < 0) {
+ *info = -2;
+ } else if (*lda < max(1,*m)) {
+ *info = -4;
+ }
+ if (*info != 0) {
+ i__1 = -(*info);
+ xerbla_("DGETF2", &i__1);
+ return 0;
+ }
+
+/* Quick return if possible */
+
+ if (*m == 0 || *n == 0) {
+ return 0;
+ }
+
+ i__1 = min(*m,*n);
+ for (j = 1; j <= i__1; ++j) {
+
+/* Find pivot and test for singularity. */
+
+ i__2 = *m - j + 1;
+ jp = j - 1 + idamax_(&i__2, &a_ref(j, j), &c__1);
+ ipiv[j] = jp;
+ if (a_ref(jp, j) != 0.) {
+
+/* Apply the interchange to columns 1:N. */
+
+ if (jp != j) {
+ dswap_(n, &a_ref(j, 1), lda, &a_ref(jp, 1), lda);
+ }
+
+/* Compute elements J+1:M of J-th column. */
+
+ if (j < *m) {
+ i__2 = *m - j;
+ d__1 = 1. / a_ref(j, j);
+ dscal_(&i__2, &d__1, &a_ref(j + 1, j), &c__1);
+ }
+
+ } else if (*info == 0) {
+
+ *info = j;
+ }
+
+ if (j < min(*m,*n)) {
+
+/* Update trailing submatrix. */
+
+ i__2 = *m - j;
+ i__3 = *n - j;
+ dger_(&i__2, &i__3, &c_b6, &a_ref(j + 1, j), &c__1, &a_ref(j, j +
+ 1), lda, &a_ref(j + 1, j + 1), lda);
+ }
+/* L10: */
+ }
+ return 0;
+
+/* End of DGETF2 */
+
+} /* dgetf2_ */
+
+#undef a_ref
+
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetrf.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetrf.c
new file mode 100644
index 00000000..13175f01
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetrf.c
@@ -0,0 +1,197 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dgetrf_(integer *m, integer *n, doublereal *a, integer *
+ lda, integer *ipiv, integer *info)
+{
+/* -- LAPACK routine (version 3.0) --
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+ Courant Institute, Argonne National Lab, and Rice University
+ March 31, 1993
+
+
+ Purpose
+ =======
+
+ DGETRF computes an LU factorization of a general M-by-N matrix A
+ using partial pivoting with row interchanges.
+
+ The factorization has the form
+ A = P * L * U
+ where P is a permutation matrix, L is lower triangular with unit
+ diagonal elements (lower trapezoidal if m > n), and U is upper
+ triangular (upper trapezoidal if m < n).
+
+ This is the right-looking Level 3 BLAS version of the algorithm.
+
+ Arguments
+ =========
+
+ M (input) INTEGER
+ The number of rows of the matrix A. M >= 0.
+
+ N (input) INTEGER
+ The number of columns of the matrix A. N >= 0.
+
+ A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+ On entry, the M-by-N matrix to be factored.
+ On exit, the factors L and U from the factorization
+ A = P*L*U; the unit diagonal elements of L are not stored.
+
+ LDA (input) INTEGER
+ The leading dimension of the array A. LDA >= max(1,M).
+
+ IPIV (output) INTEGER array, dimension (min(M,N))
+ The pivot indices; for 1 <= i <= min(M,N), row i of the
+ matrix was interchanged with row IPIV(i).
+
+ INFO (output) INTEGER
+ = 0: successful exit
+ < 0: if INFO = -i, the i-th argument had an illegal value
+ > 0: if INFO = i, U(i,i) is exactly zero. The factorization
+ has been completed, but the factor U is exactly
+ singular, and division by zero will occur if it is used
+ to solve a system of equations.
+
+ =====================================================================
+
+
+ Test the input parameters.
+
+ Parameter adjustments */
+ /* Table of constant values */
+ static integer c__1 = 1;
+ static integer c_n1 = -1;
+ static doublereal c_b16 = 1.;
+ static doublereal c_b19 = -1.;
+
+ /* System generated locals */
+ integer a_dim1, a_offset, i__1, i__2, i__3, i__4, i__5;
+ /* Local variables */
+ static integer i__, j;
+ extern /* Subroutine */ int dgemm_(char *, char *, integer *, integer *,
+ integer *, doublereal *, doublereal *, integer *, doublereal *,
+ integer *, doublereal *, doublereal *, integer *);
+ static integer iinfo;
+ extern /* Subroutine */ int dtrsm_(char *, char *, char *, char *,
+ integer *, integer *, doublereal *, doublereal *, integer *,
+ doublereal *, integer *), dgetf2_(
+ integer *, integer *, doublereal *, integer *, integer *, integer
+ *);
+ static integer jb, nb;
+ extern /* Subroutine */ int xerbla_(char *, integer *);
+ extern integer ilaenv_(integer *, char *, char *, integer *, integer *,
+ integer *, integer *, ftnlen, ftnlen);
+ extern /* Subroutine */ int dlaswp_(integer *, doublereal *, integer *,
+ integer *, integer *, integer *, integer *);
+#define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1]
+
+
+ a_dim1 = *lda;
+ a_offset = 1 + a_dim1 * 1;
+ a -= a_offset;
+ --ipiv;
+
+ /* Function Body */
+ *info = 0;
+ if (*m < 0) {
+ *info = -1;
+ } else if (*n < 0) {
+ *info = -2;
+ } else if (*lda < max(1,*m)) {
+ *info = -4;
+ }
+ if (*info != 0) {
+ i__1 = -(*info);
+ xerbla_("DGETRF", &i__1);
+ return 0;
+ }
+
+/* Quick return if possible */
+
+ if (*m == 0 || *n == 0) {
+ return 0;
+ }
+
+/* Determine the block size for this environment. */
+
+ nb = ilaenv_(&c__1, "DGETRF", " ", m, n, &c_n1, &c_n1, (ftnlen)6, (ftnlen)
+ 1);
+ if (nb <= 1 || nb >= min(*m,*n)) {
+
+/* Use unblocked code. */
+
+ dgetf2_(m, n, &a[a_offset], lda, &ipiv[1], info);
+ } else {
+
+/* Use blocked code. */
+
+ i__1 = min(*m,*n);
+ i__2 = nb;
+ for (j = 1; i__2 < 0 ? j >= i__1 : j <= i__1; j += i__2) {
+/* Computing MIN */
+ i__3 = min(*m,*n) - j + 1;
+ jb = min(i__3,nb);
+
+/* Factor diagonal and subdiagonal blocks and test for exact
+ singularity. */
+
+ i__3 = *m - j + 1;
+ dgetf2_(&i__3, &jb, &a_ref(j, j), lda, &ipiv[j], &iinfo);
+
+/* Adjust INFO and the pivot indices. */
+
+ if (*info == 0 && iinfo > 0) {
+ *info = iinfo + j - 1;
+ }
+/* Computing MIN */
+ i__4 = *m, i__5 = j + jb - 1;
+ i__3 = min(i__4,i__5);
+ for (i__ = j; i__ <= i__3; ++i__) {
+ ipiv[i__] = j - 1 + ipiv[i__];
+/* L10: */
+ }
+
+/* Apply interchanges to columns 1:J-1. */
+
+ i__3 = j - 1;
+ i__4 = j + jb - 1;
+ dlaswp_(&i__3, &a[a_offset], lda, &j, &i__4, &ipiv[1], &c__1);
+
+ if (j + jb <= *n) {
+
+/* Apply interchanges to columns J+JB:N. */
+
+ i__3 = *n - j - jb + 1;
+ i__4 = j + jb - 1;
+ dlaswp_(&i__3, &a_ref(1, j + jb), lda, &j, &i__4, &ipiv[1], &
+ c__1);
+
+/* Compute block row of U. */
+
+ i__3 = *n - j - jb + 1;
+ dtrsm_("Left", "Lower", "No transpose", "Unit", &jb, &i__3, &
+ c_b16, &a_ref(j, j), lda, &a_ref(j, j + jb), lda);
+ if (j + jb <= *m) {
+
+/* Update trailing submatrix. */
+
+ i__3 = *m - j - jb + 1;
+ i__4 = *n - j - jb + 1;
+ dgemm_("No transpose", "No transpose", &i__3, &i__4, &jb,
+ &c_b19, &a_ref(j + jb, j), lda, &a_ref(j, j + jb),
+ lda, &c_b16, &a_ref(j + jb, j + jb), lda);
+ }
+ }
+/* L20: */
+ }
+ }
+ return 0;
+
+/* End of DGETRF */
+
+} /* dgetrf_ */
+
+#undef a_ref
+
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetrs.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetrs.c
new file mode 100644
index 00000000..c4dd0b38
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dgetrs.c
@@ -0,0 +1,159 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dgetrs_(char *trans, integer *n, integer *nrhs,
+ doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *
+ ldb, integer *info)
+{
+/* -- LAPACK routine (version 3.0) --
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+ Courant Institute, Argonne National Lab, and Rice University
+ March 31, 1993
+
+
+ Purpose
+ =======
+
+ DGETRS solves a system of linear equations
+ A * X = B or A' * X = B
+ with a general N-by-N matrix A using the LU factorization computed
+ by DGETRF.
+
+ Arguments
+ =========
+
+ TRANS (input) CHARACTER*1
+ Specifies the form of the system of equations:
+ = 'N': A * X = B (No transpose)
+ = 'T': A'* X = B (Transpose)
+ = 'C': A'* X = B (Conjugate transpose = Transpose)
+
+ N (input) INTEGER
+ The order of the matrix A. N >= 0.
+
+ NRHS (input) INTEGER
+ The number of right hand sides, i.e., the number of columns
+ of the matrix B. NRHS >= 0.
+
+ A (input) DOUBLE PRECISION array, dimension (LDA,N)
+ The factors L and U from the factorization A = P*L*U
+ as computed by DGETRF.
+
+ LDA (input) INTEGER
+ The leading dimension of the array A. LDA >= max(1,N).
+
+ IPIV (input) INTEGER array, dimension (N)
+ The pivot indices from DGETRF; for 1<=i<=N, row i of the
+ matrix was interchanged with row IPIV(i).
+
+ B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
+ On entry, the right hand side matrix B.
+ On exit, the solution matrix X.
+
+ LDB (input) INTEGER
+ The leading dimension of the array B. LDB >= max(1,N).
+
+ INFO (output) INTEGER
+ = 0: successful exit
+ < 0: if INFO = -i, the i-th argument had an illegal value
+
+ =====================================================================
+
+
+ Test the input parameters.
+
+ Parameter adjustments */
+ /* Table of constant values */
+ static integer c__1 = 1;
+ static doublereal c_b12 = 1.;
+ static integer c_n1 = -1;
+
+ /* System generated locals */
+ integer a_dim1, a_offset, b_dim1, b_offset, i__1;
+ /* Local variables */
+ extern logical lsame_(char *, char *);
+ extern /* Subroutine */ int dtrsm_(char *, char *, char *, char *,
+ integer *, integer *, doublereal *, doublereal *, integer *,
+ doublereal *, integer *), xerbla_(
+ char *, integer *), dlaswp_(integer *, doublereal *,
+ integer *, integer *, integer *, integer *, integer *);
+ static logical notran;
+
+
+ a_dim1 = *lda;
+ a_offset = 1 + a_dim1 * 1;
+ a -= a_offset;
+ --ipiv;
+ b_dim1 = *ldb;
+ b_offset = 1 + b_dim1 * 1;
+ b -= b_offset;
+
+ /* Function Body */
+ *info = 0;
+ notran = lsame_(trans, "N");
+ if (! notran && ! lsame_(trans, "T") && ! lsame_(
+ trans, "C")) {
+ *info = -1;
+ } else if (*n < 0) {
+ *info = -2;
+ } else if (*nrhs < 0) {
+ *info = -3;
+ } else if (*lda < max(1,*n)) {
+ *info = -5;
+ } else if (*ldb < max(1,*n)) {
+ *info = -8;
+ }
+ if (*info != 0) {
+ i__1 = -(*info);
+ xerbla_("DGETRS", &i__1);
+ return 0;
+ }
+
+/* Quick return if possible */
+
+ if (*n == 0 || *nrhs == 0) {
+ return 0;
+ }
+
+ if (notran) {
+
+/* Solve A * X = B.
+
+ Apply row interchanges to the right hand sides. */
+
+ dlaswp_(nrhs, &b[b_offset], ldb, &c__1, n, &ipiv[1], &c__1);
+
+/* Solve L*X = B, overwriting B with X. */
+
+ dtrsm_("Left", "Lower", "No transpose", "Unit", n, nrhs, &c_b12, &a[
+ a_offset], lda, &b[b_offset], ldb);
+
+/* Solve U*X = B, overwriting B with X. */
+
+ dtrsm_("Left", "Upper", "No transpose", "Non-unit", n, nrhs, &c_b12, &
+ a[a_offset], lda, &b[b_offset], ldb);
+ } else {
+
+/* Solve A' * X = B.
+
+ Solve U'*X = B, overwriting B with X. */
+
+ dtrsm_("Left", "Upper", "Transpose", "Non-unit", n, nrhs, &c_b12, &a[
+ a_offset], lda, &b[b_offset], ldb);
+
+/* Solve L'*X = B, overwriting B with X. */
+
+ dtrsm_("Left", "Lower", "Transpose", "Unit", n, nrhs, &c_b12, &a[
+ a_offset], lda, &b[b_offset], ldb);
+
+/* Apply row interchanges to the solution vectors. */
+
+ dlaswp_(nrhs, &b[b_offset], ldb, &c__1, n, &ipiv[1], &c_n1);
+ }
+
+ return 0;
+
+/* End of DGETRS */
+
+} /* dgetrs_ */
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dlaswp.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dlaswp.c
new file mode 100644
index 00000000..4dd6fd7b
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dlaswp.c
@@ -0,0 +1,143 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dlaswp_(integer *n, doublereal *a, integer *lda, integer
+ *k1, integer *k2, integer *ipiv, integer *incx)
+{
+/* -- LAPACK auxiliary routine (version 3.0) --
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+ Courant Institute, Argonne National Lab, and Rice University
+ June 30, 1999
+
+
+ Purpose
+ =======
+
+ DLASWP performs a series of row interchanges on the matrix A.
+ One row interchange is initiated for each of rows K1 through K2 of A.
+
+ Arguments
+ =========
+
+ N (input) INTEGER
+ The number of columns of the matrix A.
+
+ A (input/output) DOUBLE PRECISION array, dimension (LDA,N)
+ On entry, the matrix of column dimension N to which the row
+ interchanges will be applied.
+ On exit, the permuted matrix.
+
+ LDA (input) INTEGER
+ The leading dimension of the array A.
+
+ K1 (input) INTEGER
+ The first element of IPIV for which a row interchange will
+ be done.
+
+ K2 (input) INTEGER
+ The last element of IPIV for which a row interchange will
+ be done.
+
+ IPIV (input) INTEGER array, dimension (M*abs(INCX))
+ The vector of pivot indices. Only the elements in positions
+ K1 through K2 of IPIV are accessed.
+ IPIV(K) = L implies rows K and L are to be interchanged.
+
+ INCX (input) INTEGER
+ The increment between successive values of IPIV. If IPIV
+ is negative, the pivots are applied in reverse order.
+
+ Further Details
+ ===============
+
+ Modified by
+ R. C. Whaley, Computer Science Dept., Univ. of Tenn., Knoxville, USA
+
+ =====================================================================
+
+
+ Interchange row I with row IPIV(I) for each of rows K1 through K2.
+
+ Parameter adjustments */
+ /* System generated locals */
+ integer a_dim1, a_offset, i__1, i__2, i__3, i__4;
+ /* Local variables */
+ static doublereal temp;
+ static integer i__, j, k, i1, i2, n32, ip, ix, ix0, inc;
+#define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1]
+
+ a_dim1 = *lda;
+ a_offset = 1 + a_dim1 * 1;
+ a -= a_offset;
+ --ipiv;
+
+ /* Function Body */
+ if (*incx > 0) {
+ ix0 = *k1;
+ i1 = *k1;
+ i2 = *k2;
+ inc = 1;
+ } else if (*incx < 0) {
+ ix0 = (1 - *k2) * *incx + 1;
+ i1 = *k2;
+ i2 = *k1;
+ inc = -1;
+ } else {
+ return 0;
+ }
+
+ n32 = *n / 32 << 5;
+ if (n32 != 0) {
+ i__1 = n32;
+ for (j = 1; j <= i__1; j += 32) {
+ ix = ix0;
+ i__2 = i2;
+ i__3 = inc;
+ for (i__ = i1; i__3 < 0 ? i__ >= i__2 : i__ <= i__2; i__ += i__3)
+ {
+ ip = ipiv[ix];
+ if (ip != i__) {
+ i__4 = j + 31;
+ for (k = j; k <= i__4; ++k) {
+ temp = a_ref(i__, k);
+ a_ref(i__, k) = a_ref(ip, k);
+ a_ref(ip, k) = temp;
+/* L10: */
+ }
+ }
+ ix += *incx;
+/* L20: */
+ }
+/* L30: */
+ }
+ }
+ if (n32 != *n) {
+ ++n32;
+ ix = ix0;
+ i__1 = i2;
+ i__3 = inc;
+ for (i__ = i1; i__3 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__3) {
+ ip = ipiv[ix];
+ if (ip != i__) {
+ i__2 = *n;
+ for (k = n32; k <= i__2; ++k) {
+ temp = a_ref(i__, k);
+ a_ref(i__, k) = a_ref(ip, k);
+ a_ref(ip, k) = temp;
+/* L40: */
+ }
+ }
+ ix += *incx;
+/* L50: */
+ }
+ }
+
+ return 0;
+
+/* End of DLASWP */
+
+} /* dlaswp_ */
+
+#undef a_ref
+
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dscal.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dscal.c
new file mode 100644
index 00000000..e0e6ffb9
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dscal.c
@@ -0,0 +1,62 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dscal_(integer *n, doublereal *da, doublereal *dx,
+ integer *incx)
+{
+ /* System generated locals */
+ integer i__1, i__2;
+ /* Local variables */
+ static integer i__, m, nincx, mp1;
+/* scales a vector by a constant.
+ uses unrolled loops for increment equal to one.
+ jack dongarra, linpack, 3/11/78.
+ modified 3/93 to return if incx .le. 0.
+ modified 12/3/93, array(1) declarations changed to array(*)
+ Parameter adjustments */
+ --dx;
+ /* Function Body */
+ if (*n <= 0 || *incx <= 0) {
+ return 0;
+ }
+ if (*incx == 1) {
+ goto L20;
+ }
+/* code for increment not equal to 1 */
+ nincx = *n * *incx;
+ i__1 = nincx;
+ i__2 = *incx;
+ for (i__ = 1; i__2 < 0 ? i__ >= i__1 : i__ <= i__1; i__ += i__2) {
+ dx[i__] = *da * dx[i__];
+/* L10: */
+ }
+ return 0;
+/* code for increment equal to 1
+ clean-up loop */
+L20:
+ m = *n % 5;
+ if (m == 0) {
+ goto L40;
+ }
+ i__2 = m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ dx[i__] = *da * dx[i__];
+/* L30: */
+ }
+ if (*n < 5) {
+ return 0;
+ }
+L40:
+ mp1 = m + 1;
+ i__2 = *n;
+ for (i__ = mp1; i__ <= i__2; i__ += 5) {
+ dx[i__] = *da * dx[i__];
+ dx[i__ + 1] = *da * dx[i__ + 1];
+ dx[i__ + 2] = *da * dx[i__ + 2];
+ dx[i__ + 3] = *da * dx[i__ + 3];
+ dx[i__ + 4] = *da * dx[i__ + 4];
+/* L50: */
+ }
+ return 0;
+} /* dscal_ */
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dswap.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dswap.c
new file mode 100644
index 00000000..5aacf29b
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dswap.c
@@ -0,0 +1,81 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dswap_(integer *n, doublereal *dx, integer *incx,
+ doublereal *dy, integer *incy)
+{
+ /* System generated locals */
+ integer i__1;
+ /* Local variables */
+ static integer i__, m;
+ static doublereal dtemp;
+ static integer ix, iy, mp1;
+/* interchanges two vectors.
+ uses unrolled loops for increments equal one.
+ jack dongarra, linpack, 3/11/78.
+ modified 12/3/93, array(1) declarations changed to array(*)
+ Parameter adjustments */
+ --dy;
+ --dx;
+ /* Function Body */
+ if (*n <= 0) {
+ return 0;
+ }
+ if (*incx == 1 && *incy == 1) {
+ goto L20;
+ }
+/* code for unequal increments or equal increments not equal
+ to 1 */
+ ix = 1;
+ iy = 1;
+ if (*incx < 0) {
+ ix = (-(*n) + 1) * *incx + 1;
+ }
+ if (*incy < 0) {
+ iy = (-(*n) + 1) * *incy + 1;
+ }
+ i__1 = *n;
+ for (i__ = 1; i__ <= i__1; ++i__) {
+ dtemp = dx[ix];
+ dx[ix] = dy[iy];
+ dy[iy] = dtemp;
+ ix += *incx;
+ iy += *incy;
+/* L10: */
+ }
+ return 0;
+/* code for both increments equal to 1
+ clean-up loop */
+L20:
+ m = *n % 3;
+ if (m == 0) {
+ goto L40;
+ }
+ i__1 = m;
+ for (i__ = 1; i__ <= i__1; ++i__) {
+ dtemp = dx[i__];
+ dx[i__] = dy[i__];
+ dy[i__] = dtemp;
+/* L30: */
+ }
+ if (*n < 3) {
+ return 0;
+ }
+L40:
+ mp1 = m + 1;
+ i__1 = *n;
+ for (i__ = mp1; i__ <= i__1; i__ += 3) {
+ dtemp = dx[i__];
+ dx[i__] = dy[i__];
+ dy[i__] = dtemp;
+ dtemp = dx[i__ + 1];
+ dx[i__ + 1] = dy[i__ + 1];
+ dy[i__ + 1] = dtemp;
+ dtemp = dx[i__ + 2];
+ dx[i__ + 2] = dy[i__ + 2];
+ dy[i__ + 2] = dtemp;
+/* L50: */
+ }
+ return 0;
+} /* dswap_ */
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/dtrsm.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dtrsm.c
new file mode 100644
index 00000000..d178c1ed
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/dtrsm.c
@@ -0,0 +1,404 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int dtrsm_(char *side, char *uplo, char *transa, char *diag,
+ integer *m, integer *n, doublereal *alpha, doublereal *a, integer *
+ lda, doublereal *b, integer *ldb)
+{
+ /* System generated locals */
+ integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2, i__3;
+ /* Local variables */
+ static integer info;
+ static doublereal temp;
+ static integer i__, j, k;
+ static logical lside;
+ extern logical lsame_(char *, char *);
+ static integer nrowa;
+ static logical upper;
+ extern /* Subroutine */ int xerbla_(char *, integer *);
+ static logical nounit;
+#define a_ref(a_1,a_2) a[(a_2)*a_dim1 + a_1]
+#define b_ref(a_1,a_2) b[(a_2)*b_dim1 + a_1]
+/* Purpose
+ =======
+ DTRSM solves one of the matrix equations
+ op( A )*X = alpha*B, or X*op( A ) = alpha*B,
+ where alpha is a scalar, X and B are m by n matrices, A is a unit, or
+ non-unit, upper or lower triangular matrix and op( A ) is one of
+ op( A ) = A or op( A ) = A'.
+ The matrix X is overwritten on B.
+ Parameters
+ ==========
+ SIDE - CHARACTER*1.
+ On entry, SIDE specifies whether op( A ) appears on the left
+ or right of X as follows:
+ SIDE = 'L' or 'l' op( A )*X = alpha*B.
+ SIDE = 'R' or 'r' X*op( A ) = alpha*B.
+ Unchanged on exit.
+ UPLO - CHARACTER*1.
+ On entry, UPLO specifies whether the matrix A is an upper or
+ lower triangular matrix as follows:
+ UPLO = 'U' or 'u' A is an upper triangular matrix.
+ UPLO = 'L' or 'l' A is a lower triangular matrix.
+ Unchanged on exit.
+ TRANSA - CHARACTER*1.
+ On entry, TRANSA specifies the form of op( A ) to be used in
+ the matrix multiplication as follows:
+ TRANSA = 'N' or 'n' op( A ) = A.
+ TRANSA = 'T' or 't' op( A ) = A'.
+ TRANSA = 'C' or 'c' op( A ) = A'.
+ Unchanged on exit.
+ DIAG - CHARACTER*1.
+ On entry, DIAG specifies whether or not A is unit triangular
+ as follows:
+ DIAG = 'U' or 'u' A is assumed to be unit triangular.
+ DIAG = 'N' or 'n' A is not assumed to be unit
+ triangular.
+ Unchanged on exit.
+ M - INTEGER.
+ On entry, M specifies the number of rows of B. M must be at
+ least zero.
+ Unchanged on exit.
+ N - INTEGER.
+ On entry, N specifies the number of columns of B. N must be
+ at least zero.
+ Unchanged on exit.
+ ALPHA - DOUBLE PRECISION.
+ On entry, ALPHA specifies the scalar alpha. When alpha is
+ zero then A is not referenced and B need not be set before
+ entry.
+ Unchanged on exit.
+ A - DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m
+ when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'.
+ Before entry with UPLO = 'U' or 'u', the leading k by k
+ upper triangular part of the array A must contain the upper
+ triangular matrix and the strictly lower triangular part of
+ A is not referenced.
+ Before entry with UPLO = 'L' or 'l', the leading k by k
+ lower triangular part of the array A must contain the lower
+ triangular matrix and the strictly upper triangular part of
+ A is not referenced.
+ Note that when DIAG = 'U' or 'u', the diagonal elements of
+ A are not referenced either, but are assumed to be unity.
+ Unchanged on exit.
+ LDA - INTEGER.
+ On entry, LDA specifies the first dimension of A as declared
+ in the calling (sub) program. When SIDE = 'L' or 'l' then
+ LDA must be at least max( 1, m ), when SIDE = 'R' or 'r'
+ then LDA must be at least max( 1, n ).
+ Unchanged on exit.
+ B - DOUBLE PRECISION array of DIMENSION ( LDB, n ).
+ Before entry, the leading m by n part of the array B must
+ contain the right-hand side matrix B, and on exit is
+ overwritten by the solution matrix X.
+ LDB - INTEGER.
+ On entry, LDB specifies the first dimension of B as declared
+ in the calling (sub) program. LDB must be at least
+ max( 1, m ).
+ Unchanged on exit.
+ Level 3 Blas routine.
+ -- Written on 8-February-1989.
+ Jack Dongarra, Argonne National Laboratory.
+ Iain Duff, AERE Harwell.
+ Jeremy Du Croz, Numerical Algorithms Group Ltd.
+ Sven Hammarling, Numerical Algorithms Group Ltd.
+ Test the input parameters.
+ Parameter adjustments */
+ a_dim1 = *lda;
+ a_offset = 1 + a_dim1 * 1;
+ a -= a_offset;
+ b_dim1 = *ldb;
+ b_offset = 1 + b_dim1 * 1;
+ b -= b_offset;
+ /* Function Body */
+ lside = lsame_(side, "L");
+ if (lside) {
+ nrowa = *m;
+ } else {
+ nrowa = *n;
+ }
+ nounit = lsame_(diag, "N");
+ upper = lsame_(uplo, "U");
+ info = 0;
+ if (! lside && ! lsame_(side, "R")) {
+ info = 1;
+ } else if (! upper && ! lsame_(uplo, "L")) {
+ info = 2;
+ } else if (! lsame_(transa, "N") && ! lsame_(transa,
+ "T") && ! lsame_(transa, "C")) {
+ info = 3;
+ } else if (! lsame_(diag, "U") && ! lsame_(diag,
+ "N")) {
+ info = 4;
+ } else if (*m < 0) {
+ info = 5;
+ } else if (*n < 0) {
+ info = 6;
+ } else if (*lda < max(1,nrowa)) {
+ info = 9;
+ } else if (*ldb < max(1,*m)) {
+ info = 11;
+ }
+ if (info != 0) {
+ xerbla_("DTRSM ", &info);
+ return 0;
+ }
+/* Quick return if possible. */
+ if (*n == 0) {
+ return 0;
+ }
+/* And when alpha.eq.zero. */
+ if (*alpha == 0.) {
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, j) = 0.;
+/* L10: */
+ }
+/* L20: */
+ }
+ return 0;
+ }
+/* Start the operations. */
+ if (lside) {
+ if (lsame_(transa, "N")) {
+/* Form B := alpha*inv( A )*B. */
+ if (upper) {
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ if (*alpha != 1.) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, j) = *alpha * b_ref(i__, j);
+/* L30: */
+ }
+ }
+ for (k = *m; k >= 1; --k) {
+ if (b_ref(k, j) != 0.) {
+ if (nounit) {
+ b_ref(k, j) = b_ref(k, j) / a_ref(k, k);
+ }
+ i__2 = k - 1;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, j) = b_ref(i__, j) - b_ref(k, j) *
+ a_ref(i__, k);
+/* L40: */
+ }
+ }
+/* L50: */
+ }
+/* L60: */
+ }
+ } else {
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ if (*alpha != 1.) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, j) = *alpha * b_ref(i__, j);
+/* L70: */
+ }
+ }
+ i__2 = *m;
+ for (k = 1; k <= i__2; ++k) {
+ if (b_ref(k, j) != 0.) {
+ if (nounit) {
+ b_ref(k, j) = b_ref(k, j) / a_ref(k, k);
+ }
+ i__3 = *m;
+ for (i__ = k + 1; i__ <= i__3; ++i__) {
+ b_ref(i__, j) = b_ref(i__, j) - b_ref(k, j) *
+ a_ref(i__, k);
+/* L80: */
+ }
+ }
+/* L90: */
+ }
+/* L100: */
+ }
+ }
+ } else {
+/* Form B := alpha*inv( A' )*B. */
+ if (upper) {
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ temp = *alpha * b_ref(i__, j);
+ i__3 = i__ - 1;
+ for (k = 1; k <= i__3; ++k) {
+ temp -= a_ref(k, i__) * b_ref(k, j);
+/* L110: */
+ }
+ if (nounit) {
+ temp /= a_ref(i__, i__);
+ }
+ b_ref(i__, j) = temp;
+/* L120: */
+ }
+/* L130: */
+ }
+ } else {
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ for (i__ = *m; i__ >= 1; --i__) {
+ temp = *alpha * b_ref(i__, j);
+ i__2 = *m;
+ for (k = i__ + 1; k <= i__2; ++k) {
+ temp -= a_ref(k, i__) * b_ref(k, j);
+/* L140: */
+ }
+ if (nounit) {
+ temp /= a_ref(i__, i__);
+ }
+ b_ref(i__, j) = temp;
+/* L150: */
+ }
+/* L160: */
+ }
+ }
+ }
+ } else {
+ if (lsame_(transa, "N")) {
+/* Form B := alpha*B*inv( A ). */
+ if (upper) {
+ i__1 = *n;
+ for (j = 1; j <= i__1; ++j) {
+ if (*alpha != 1.) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, j) = *alpha * b_ref(i__, j);
+/* L170: */
+ }
+ }
+ i__2 = j - 1;
+ for (k = 1; k <= i__2; ++k) {
+ if (a_ref(k, j) != 0.) {
+ i__3 = *m;
+ for (i__ = 1; i__ <= i__3; ++i__) {
+ b_ref(i__, j) = b_ref(i__, j) - a_ref(k, j) *
+ b_ref(i__, k);
+/* L180: */
+ }
+ }
+/* L190: */
+ }
+ if (nounit) {
+ temp = 1. / a_ref(j, j);
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, j) = temp * b_ref(i__, j);
+/* L200: */
+ }
+ }
+/* L210: */
+ }
+ } else {
+ for (j = *n; j >= 1; --j) {
+ if (*alpha != 1.) {
+ i__1 = *m;
+ for (i__ = 1; i__ <= i__1; ++i__) {
+ b_ref(i__, j) = *alpha * b_ref(i__, j);
+/* L220: */
+ }
+ }
+ i__1 = *n;
+ for (k = j + 1; k <= i__1; ++k) {
+ if (a_ref(k, j) != 0.) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, j) = b_ref(i__, j) - a_ref(k, j) *
+ b_ref(i__, k);
+/* L230: */
+ }
+ }
+/* L240: */
+ }
+ if (nounit) {
+ temp = 1. / a_ref(j, j);
+ i__1 = *m;
+ for (i__ = 1; i__ <= i__1; ++i__) {
+ b_ref(i__, j) = temp * b_ref(i__, j);
+/* L250: */
+ }
+ }
+/* L260: */
+ }
+ }
+ } else {
+/* Form B := alpha*B*inv( A' ). */
+ if (upper) {
+ for (k = *n; k >= 1; --k) {
+ if (nounit) {
+ temp = 1. / a_ref(k, k);
+ i__1 = *m;
+ for (i__ = 1; i__ <= i__1; ++i__) {
+ b_ref(i__, k) = temp * b_ref(i__, k);
+/* L270: */
+ }
+ }
+ i__1 = k - 1;
+ for (j = 1; j <= i__1; ++j) {
+ if (a_ref(j, k) != 0.) {
+ temp = a_ref(j, k);
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, j) = b_ref(i__, j) - temp * b_ref(
+ i__, k);
+/* L280: */
+ }
+ }
+/* L290: */
+ }
+ if (*alpha != 1.) {
+ i__1 = *m;
+ for (i__ = 1; i__ <= i__1; ++i__) {
+ b_ref(i__, k) = *alpha * b_ref(i__, k);
+/* L300: */
+ }
+ }
+/* L310: */
+ }
+ } else {
+ i__1 = *n;
+ for (k = 1; k <= i__1; ++k) {
+ if (nounit) {
+ temp = 1. / a_ref(k, k);
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, k) = temp * b_ref(i__, k);
+/* L320: */
+ }
+ }
+ i__2 = *n;
+ for (j = k + 1; j <= i__2; ++j) {
+ if (a_ref(j, k) != 0.) {
+ temp = a_ref(j, k);
+ i__3 = *m;
+ for (i__ = 1; i__ <= i__3; ++i__) {
+ b_ref(i__, j) = b_ref(i__, j) - temp * b_ref(
+ i__, k);
+/* L330: */
+ }
+ }
+/* L340: */
+ }
+ if (*alpha != 1.) {
+ i__2 = *m;
+ for (i__ = 1; i__ <= i__2; ++i__) {
+ b_ref(i__, k) = *alpha * b_ref(i__, k);
+/* L350: */
+ }
+ }
+/* L360: */
+ }
+ }
+ }
+ }
+ return 0;
+/* End of DTRSM . */
+} /* dtrsm_ */
+#undef b_ref
+#undef a_ref
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/endfile.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/endfile.c
new file mode 100644
index 00000000..d309fc26
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/endfile.c
@@ -0,0 +1,102 @@
+#include "f2c.h"
+#include "fio.h"
+
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#include "string.h"
+
+extern char *f__r_mode[], *f__w_mode[];
+
+integer f_end(alist *a)
+{
+ unit *b;
+ FILE *tf;
+
+ if(a->aunit>=MXUNIT || a->aunit<0) err(a->aerr,101,"endfile");
+ b = &f__units[a->aunit];
+ if(b->ufd==NULL) {
+ char nbuf[10];
+ sprintf(nbuf,"fort.%ld",a->aunit);
+ if (tf = fopen(nbuf, f__w_mode[0]))
+ fclose(tf);
+ return(0);
+ }
+ b->uend=1;
+ return(b->useek ? t_runc(a) : 0);
+}
+
+static int copy(FILE *from, long len, FILE *to)
+{
+ int len1;
+ char buf[BUFSIZ];
+
+ while(fread(buf, len1 = len > BUFSIZ ? BUFSIZ : (int)len, 1, from)) {
+ if (!fwrite(buf, len1, 1, to))
+ return 1;
+ if ((len -= len1) <= 0)
+ break;
+ }
+ return 0;
+ }
+
+int t_runc(alist *a)
+{
+ long loc, len;
+ unit *b;
+ FILE *bf, *tf;
+ int rc = 0;
+
+ b = &f__units[a->aunit];
+ if(b->url)
+ return(0); /*don't truncate direct files*/
+ loc=ftell(bf = b->ufd);
+ fseek(bf,0L,SEEK_END);
+ len=ftell(bf);
+ if (loc >= len || b->useek == 0 || b->ufnm == NULL)
+ return(0);
+ fclose(b->ufd);
+ if (!loc) {
+ if (!(bf = fopen(b->ufnm, f__w_mode[b->ufmt])))
+ rc = 1;
+ if (b->uwrt)
+ b->uwrt = 1;
+ goto done;
+ }
+ if (!(bf = fopen(b->ufnm, f__r_mode[0]))
+ || !(tf = tmpfile())) {
+#ifdef NON_UNIX_STDIO
+ bad:
+#endif
+ rc = 1;
+ goto done;
+ }
+ if (copy(bf, loc, tf)) {
+ bad1:
+ rc = 1;
+ goto done1;
+ }
+ if (!(bf = freopen(b->ufnm, f__w_mode[0], bf)))
+ goto bad1;
+ rewind(tf);
+ if (copy(tf, loc, bf))
+ goto bad1;
+ b->urw = 2;
+#ifdef NON_UNIX_STDIO
+ if (b->ufmt) {
+ fclose(bf);
+ if (!(bf = fopen(b->ufnm, f__w_mode[3])))
+ goto bad;
+ fseek(bf,0L,SEEK_END);
+ b->urw = 3;
+ }
+#endif
+done1:
+ fclose(tf);
+done:
+ f__cf = b->ufd = bf;
+ if (rc)
+ err(a->aerr,111,"endfile");
+ return 0;
+ }
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/err.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/err.c
new file mode 100644
index 00000000..90af7cae
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/err.c
@@ -0,0 +1,240 @@
+#ifndef NON_UNIX_STDIO
+#define _INCLUDE_POSIX_SOURCE /* for HP-UX */
+#define _INCLUDE_XOPEN_SOURCE /* for HP-UX */
+#include "sys/types.h"
+#include "sys/stat.h"
+#endif
+#include "f2c.h"
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#include "fio.h"
+#include "fmt.h" /* for struct syl */
+
+/*global definitions*/
+unit f__units[MXUNIT]; /*unit table*/
+flag f__init; /*0 on entry, 1 after initializations*/
+cilist *f__elist; /*active external io list*/
+icilist *f__svic; /*active internal io list*/
+flag f__reading; /*1 if reading, 0 if writing*/
+flag f__cplus,f__cblank;
+char *f__fmtbuf;
+flag f__external; /*1 if external io, 0 if internal */
+int (*f__getn)(void); /* for formatted input */
+void (*f__putn)(int); /* for formatted output */
+int (*f__doed)(struct syl*, char*, ftnlen),(*f__doned)(struct syl*);
+int (*f__dorevert)(void),(*f__donewrec)(void),(*f__doend)(void);
+flag f__sequential; /*1 if sequential io, 0 if direct*/
+flag f__formatted; /*1 if formatted io, 0 if unformatted*/
+FILE *f__cf; /*current file*/
+unit *f__curunit; /*current unit*/
+int f__recpos; /*place in current record*/
+int f__cursor, f__hiwater, f__scale;
+char *f__icptr;
+
+/*error messages*/
+char *F_err[] =
+{
+ "error in format", /* 100 */
+ "illegal unit number", /* 101 */
+ "formatted io not allowed", /* 102 */
+ "unformatted io not allowed", /* 103 */
+ "direct io not allowed", /* 104 */
+ "sequential io not allowed", /* 105 */
+ "can't backspace file", /* 106 */
+ "null file name", /* 107 */
+ "can't stat file", /* 108 */
+ "unit not connected", /* 109 */
+ "off end of record", /* 110 */
+ "truncation failed in endfile", /* 111 */
+ "incomprehensible list input", /* 112 */
+ "out of free space", /* 113 */
+ "unit not connected", /* 114 */
+ "read unexpected character", /* 115 */
+ "bad logical input field", /* 116 */
+ "bad variable type", /* 117 */
+ "bad namelist name", /* 118 */
+ "variable not in namelist", /* 119 */
+ "no end record", /* 120 */
+ "variable count incorrect", /* 121 */
+ "subscript for scalar variable", /* 122 */
+ "invalid array section", /* 123 */
+ "substring out of bounds", /* 124 */
+ "subscript out of bounds", /* 125 */
+ "can't read file", /* 126 */
+ "can't write file", /* 127 */
+ "'new' file exists", /* 128 */
+ "can't append to file", /* 129 */
+ "non-positive record number" /* 130 */
+};
+#define MAXERR (sizeof(F_err)/sizeof(char *)+100)
+
+int f__canseek(FILE *f) /*SYSDEP*/
+{
+#ifdef NON_UNIX_STDIO
+ return !isatty(fileno(f));
+#else
+ struct stat x;
+
+ if (fstat(fileno(f),&x) < 0)
+ return(0);
+#ifdef S_IFMT
+ switch(x.st_mode & S_IFMT) {
+ case S_IFDIR:
+ case S_IFREG:
+ if(x.st_nlink > 0) /* !pipe */
+ return(1);
+ else
+ return(0);
+ case S_IFCHR:
+ if(isatty(fileno(f)))
+ return(0);
+ return(1);
+#ifdef S_IFBLK
+ case S_IFBLK:
+ return(1);
+#endif
+ }
+#else
+#ifdef S_ISDIR
+ /* POSIX version */
+ if (S_ISREG(x.st_mode) || S_ISDIR(x.st_mode)) {
+ if(x.st_nlink > 0) /* !pipe */
+ return(1);
+ else
+ return(0);
+ }
+ if (S_ISCHR(x.st_mode)) {
+ if(isatty(fileno(f)))
+ return(0);
+ return(1);
+ }
+ if (S_ISBLK(x.st_mode))
+ return(1);
+#else
+ Help! How does fstat work on this system?
+#endif
+#endif
+ return(0); /* who knows what it is? */
+#endif
+}
+
+void f__fatal(int n, char *s)
+{
+ if(n<100 && n>=0) perror(s); /*SYSDEP*/
+ else if(n >= (int)MAXERR || n < -1)
+ { fprintf(stderr,"%s: illegal error number %d\n",s,n);
+ }
+ else if(n == -1) fprintf(stderr,"%s: end of file\n",s);
+ else
+ fprintf(stderr,"%s: %s\n",s,F_err[n-100]);
+ if (f__curunit) {
+ fprintf(stderr,"apparent state: unit %d ",
+ (int)(f__curunit-f__units));
+ fprintf(stderr, f__curunit->ufnm ? "named %s\n" : "(unnamed)\n",
+ f__curunit->ufnm);
+ }
+ else
+ fprintf(stderr,"apparent state: internal I/O\n");
+ if (f__fmtbuf)
+ fprintf(stderr,"last format: %s\n",f__fmtbuf);
+ fprintf(stderr,"lately %s %s %s %s",f__reading?"reading":"writing",
+ f__sequential?"sequential":"direct",f__formatted?"formatted":"unformatted",
+ f__external?"external":"internal");
+ sig_die(" IO", 1);
+}
+/*initialization routine*/
+ VOID
+f_init(Void)
+{ unit *p;
+
+ f__init=1;
+ p= &f__units[0];
+ p->ufd=stderr;
+ p->useek=f__canseek(stderr);
+ p->ufmt=1;
+ p->uwrt=1;
+ p = &f__units[5];
+ p->ufd=stdin;
+ p->useek=f__canseek(stdin);
+ p->ufmt=1;
+ p->uwrt=0;
+ p= &f__units[6];
+ p->ufd=stdout;
+ p->useek=f__canseek(stdout);
+ p->ufmt=1;
+ p->uwrt=1;
+}
+
+int f__nowreading(unit *x)
+{
+ long loc;
+ int ufmt, urw;
+ extern char *f__r_mode[], *f__w_mode[];
+
+ if (x->urw & 1)
+ goto done;
+ if (!x->ufnm)
+ goto cantread;
+ ufmt = x->url ? 0 : x->ufmt;
+ loc = ftell(x->ufd);
+ urw = 3;
+ if (!freopen(x->ufnm, f__w_mode[ufmt|2], x->ufd)) {
+ urw = 1;
+ if(!freopen(x->ufnm, f__r_mode[ufmt], x->ufd)) {
+ cantread:
+ errno = 126;
+ return 1;
+ }
+ }
+ fseek(x->ufd,loc,SEEK_SET);
+ x->urw = urw;
+ done:
+ x->uwrt = 0;
+ return 0;
+}
+
+int f__nowwriting(unit *x)
+{
+ long loc;
+ int ufmt;
+ extern char *f__w_mode[];
+
+ if (x->urw & 2)
+ goto done;
+ if (!x->ufnm)
+ goto cantwrite;
+ ufmt = x->url ? 0 : x->ufmt;
+ if (x->uwrt == 3) { /* just did write, rewind */
+ if (!(f__cf = x->ufd =
+ freopen(x->ufnm,f__w_mode[ufmt],x->ufd)))
+ goto cantwrite;
+ x->urw = 2;
+ }
+ else {
+ loc=ftell(x->ufd);
+ if (!(f__cf = x->ufd =
+ freopen(x->ufnm, f__w_mode[ufmt |= 2], x->ufd)))
+ {
+ x->ufd = NULL;
+ cantwrite:
+ errno = 127;
+ return(1);
+ }
+ x->urw = 3;
+ fseek(x->ufd,loc,SEEK_SET);
+ }
+ done:
+ x->uwrt = 1;
+ return 0;
+}
+
+int err__fl(int f, int m, char *s)
+{
+ if (!f)
+ f__fatal(m, s);
+ if (f__doend)
+ (*f__doend)();
+ return errno = m;
+ }
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/f2c.h b/src/imageplugins/coreplugin/sharpnesseditor/clapack/f2c.h
new file mode 100644
index 00000000..6514cd91
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/f2c.h
@@ -0,0 +1,223 @@
+/* f2c.h -- Standard Fortran to C header file */
+
+/** barf [ba:rf] 2. "He suggested using FORTRAN, and everybody barfed."
+
+ - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */
+
+#ifndef F2C_INCLUDE
+#define F2C_INCLUDE
+
+typedef long int integer;
+typedef unsigned long uinteger;
+typedef char *address;
+typedef short int shortint;
+typedef float real;
+typedef double doublereal;
+typedef struct { real r, i; } complex;
+typedef struct { doublereal r, i; } doublecomplex;
+typedef long int logical;
+typedef short int shortlogical;
+typedef char logical1;
+typedef char integer1;
+#if 0 /* Adjust for integer*8. */
+typedef long long longint; /* system-dependent */
+typedef unsigned long long ulongint; /* system-dependent */
+#define qbit_clear(a,b) ((a) & ~((ulongint)1 << (b)))
+#define qbit_set(a,b) ((a) | ((ulongint)1 << (b)))
+#endif
+
+#define TRUE_ (1)
+#define FALSE_ (0)
+
+/* Extern is for use with -E */
+#ifndef Extern
+#define Extern extern
+#endif
+
+/* I/O stuff */
+
+#ifdef f2c_i2
+/* for -i2 */
+typedef short flag;
+typedef short ftnlen;
+typedef short ftnint;
+#else
+typedef long int flag;
+typedef long int ftnlen;
+typedef long int ftnint;
+#endif
+
+/*external read, write*/
+typedef struct
+{ flag cierr;
+ ftnint ciunit;
+ flag ciend;
+ char *cifmt;
+ ftnint cirec;
+} cilist;
+
+/*internal read, write*/
+typedef struct
+{ flag icierr;
+ char *iciunit;
+ flag iciend;
+ char *icifmt;
+ ftnint icirlen;
+ ftnint icirnum;
+} icilist;
+
+/*open*/
+typedef struct
+{ flag oerr;
+ ftnint ounit;
+ char *ofnm;
+ ftnlen ofnmlen;
+ char *osta;
+ char *oacc;
+ char *ofm;
+ ftnint orl;
+ char *oblnk;
+} olist;
+
+/*close*/
+typedef struct
+{ flag cerr;
+ ftnint cunit;
+ char *csta;
+} cllist;
+
+/*rewind, backspace, endfile*/
+typedef struct
+{ flag aerr;
+ ftnint aunit;
+} alist;
+
+/* inquire */
+typedef struct
+{ flag inerr;
+ ftnint inunit;
+ char *infile;
+ ftnlen infilen;
+ ftnint *inex; /*parameters in standard's order*/
+ ftnint *inopen;
+ ftnint *innum;
+ ftnint *innamed;
+ char *inname;
+ ftnlen innamlen;
+ char *inacc;
+ ftnlen inacclen;
+ char *inseq;
+ ftnlen inseqlen;
+ char *indir;
+ ftnlen indirlen;
+ char *infmt;
+ ftnlen infmtlen;
+ char *inform;
+ ftnint informlen;
+ char *inunf;
+ ftnlen inunflen;
+ ftnint *inrecl;
+ ftnint *innrec;
+ char *inblank;
+ ftnlen inblanklen;
+} inlist;
+
+#define VOID void
+
+union Multitype { /* for multiple entry points */
+ integer1 g;
+ shortint h;
+ integer i;
+ /* longint j; */
+ real r;
+ doublereal d;
+ complex c;
+ doublecomplex z;
+ };
+
+typedef union Multitype Multitype;
+
+/*typedef long int Long;*/ /* No longer used; formerly in Namelist */
+
+struct Vardesc { /* for Namelist */
+ char *name;
+ char *addr;
+ ftnlen *dims;
+ int type;
+ };
+typedef struct Vardesc Vardesc;
+
+struct Namelist {
+ char *name;
+ Vardesc **vars;
+ int nvars;
+ };
+typedef struct Namelist Namelist;
+
+#define abs(x) ((x) >= 0 ? (x) : -(x))
+#define dabs(x) (doublereal)abs(x)
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
+#define dmin(a,b) (doublereal)min(a,b)
+#define dmax(a,b) (doublereal)max(a,b)
+#define bit_test(a,b) ((a) >> (b) & 1)
+#define bit_clear(a,b) ((a) & ~((uinteger)1 << (b)))
+#define bit_set(a,b) ((a) | ((uinteger)1 << (b)))
+
+/* procedure parameter types for -A and -C++ */
+
+#define F2C_proc_par_types 1
+#ifdef __cplusplus
+typedef int /* Unknown procedure type */ (*U_fp)(...);
+typedef shortint (*J_fp)(...);
+typedef integer (*I_fp)(...);
+typedef real (*R_fp)(...);
+typedef doublereal (*D_fp)(...), (*E_fp)(...);
+typedef /* Complex */ VOID (*C_fp)(...);
+typedef /* Double Complex */ VOID (*Z_fp)(...);
+typedef logical (*L_fp)(...);
+typedef shortlogical (*K_fp)(...);
+typedef /* Character */ VOID (*H_fp)(...);
+typedef /* Subroutine */ int (*S_fp)(...);
+#else
+typedef int /* Unknown procedure type */ (*U_fp)();
+typedef shortint (*J_fp)();
+typedef integer (*I_fp)();
+typedef real (*R_fp)();
+typedef doublereal (*D_fp)(), (*E_fp)();
+typedef /* Complex */ VOID (*C_fp)();
+typedef /* Double Complex */ VOID (*Z_fp)();
+typedef logical (*L_fp)();
+typedef shortlogical (*K_fp)();
+typedef /* Character */ VOID (*H_fp)();
+typedef /* Subroutine */ int (*S_fp)();
+#endif
+/* E_fp is for real functions when -R is not specified */
+typedef VOID C_f; /* complex function */
+typedef VOID H_f; /* character function */
+typedef VOID Z_f; /* double complex function */
+typedef doublereal E_f; /* real function with -R not specified */
+
+/* undef any lower-case symbols that your C compiler predefines, e.g.: */
+
+#ifndef Skip_f2c_Undefs
+#undef cray
+#undef gcos
+#undef mc68010
+#undef mc68020
+#undef mips
+#undef pdp11
+#undef sgi
+#undef sparc
+#undef sun
+#undef sun2
+#undef sun3
+#undef sun4
+#undef u370
+#undef u3b
+#undef u3b2
+#undef u3b5
+#undef unix
+#undef vax
+#endif
+#endif
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/fio.h b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fio.h
new file mode 100644
index 00000000..b1632d50
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fio.h
@@ -0,0 +1,96 @@
+#include "stdio.h"
+#include "errno.h"
+#ifndef NULL
+/* ANSI C */
+#include "stddef.h"
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#ifdef MSDOS
+#ifndef NON_UNIX_STDIO
+#define NON_UNIX_STDIO
+#endif
+#endif
+
+#ifdef UIOLEN_int
+typedef int uiolen;
+#else
+typedef long uiolen;
+#endif
+
+/*units*/
+typedef struct
+{ FILE *ufd; /*0=unconnected*/
+ char *ufnm;
+#ifndef MSDOS
+ long uinode;
+ int udev;
+#endif
+ int url; /*0=sequential*/
+ flag useek; /*true=can backspace, use dir, ...*/
+ flag ufmt;
+ flag urw; /* (1 for can read) | (2 for can write) */
+ flag ublnk;
+ flag uend;
+ flag uwrt; /*last io was write*/
+ flag uscrtch;
+} unit;
+
+extern flag f__init;
+extern cilist *f__elist; /*active external io list*/
+extern flag f__reading,f__external,f__sequential,f__formatted;
+#undef Void
+#define Void void
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int (*f__getn)(void); /* for formatted input */
+extern void (*f__putn)(int); /* for formatted output */
+extern void x_putc(int);
+extern long f__inode(char*,int*);
+extern void sig_die(char*,int);
+extern void f__fatal(int,char*);
+extern int t_runc(alist*);
+extern int f__nowreading(unit*), f__nowwriting(unit*);
+extern int fk_open(int,int,ftnint);
+extern int en_fio(void);
+extern void f_init(void);
+extern int (*f__donewrec)(void), t_putc(int), x_wSL(void);
+extern void b_char(char*,char*,ftnlen), g_char(char*,ftnlen,char*);
+extern int c_sfe(cilist*), z_rnew(void);
+extern int isatty(int);
+extern int err__fl(int,int,char*);
+extern int xrd_SL(void);
+extern int f__putbuf(int);
+#ifdef __cplusplus
+ }
+#endif
+extern int (*f__doend)(Void);
+extern FILE *f__cf; /*current file*/
+extern unit *f__curunit; /*current unit*/
+extern unit f__units[];
+#define err(f,m,s) {if(f) errno= m; else f__fatal(m,s); return(m);}
+#define errfl(f,m,s) return err__fl((int)f,m,s)
+
+/*Table sizes*/
+#define MXUNIT 100
+
+extern int f__recpos; /*position in current record*/
+extern int f__cursor; /* offset to move to */
+extern int f__hiwater; /* so TL doesn't confuse us */
+
+#define WRITE 1
+#define READ 2
+#define SEQ 3
+#define DIR 4
+#define FMT 5
+#define UNF 6
+#define EXT 7
+#define INT 8
+
+#define buf_end(x) (x->_flag & _IONBF ? x->_ptr : x->_base + BUFSIZ)
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/fmt.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fmt.c
new file mode 100644
index 00000000..a4fcbc38
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fmt.c
@@ -0,0 +1,470 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+#define skip(s) while(*s==' ') s++
+#ifdef interdata
+#define SYLMX 300
+#endif
+#ifdef pdp11
+#define SYLMX 300
+#endif
+#ifdef vax
+#define SYLMX 300
+#endif
+#ifndef SYLMX
+#define SYLMX 300
+#endif
+#define GLITCH '\2'
+ /* special quote character for stu */
+extern int f__cursor,f__scale;
+extern flag f__cblank,f__cplus; /*blanks in I and compulsory plus*/
+static struct syl f__syl[SYLMX];
+int f__parenlvl,f__pc,f__revloc;
+
+static char *ap_end(char *s)
+{ char quote;
+ quote= *s++;
+ for(;*s;s++)
+ { if(*s!=quote) continue;
+ if(*++s!=quote) return(s);
+ }
+ if(f__elist->cierr) {
+ errno = 100;
+ return(NULL);
+ }
+ f__fatal(100, "bad string");
+ /*NOTREACHED*/ return 0;
+}
+
+static int op_gen(int a, int b, int c, int d)
+{ struct syl *p= &f__syl[f__pc];
+ if(f__pc>=SYLMX)
+ { fprintf(stderr,"format too complicated:\n");
+ sig_die(f__fmtbuf, 1);
+ }
+ p->op=a;
+ p->p1=b;
+ p->p2.i[0]=c;
+ p->p2.i[1]=d;
+ return(f__pc++);
+}
+
+static char *f_list(char*);
+static char *gt_num(char *s, int *n, int n1)
+{ int m=0,f__cnt=0;
+ char c;
+ for(c= *s;;c = *s)
+ { if(c==' ')
+ { s++;
+ continue;
+ }
+ if(c>'9' || c<'0') break;
+ m=10*m+c-'0';
+ f__cnt++;
+ s++;
+ }
+ if(f__cnt==0) {
+ if (!n1)
+ s = 0;
+ *n=n1;
+ }
+ else *n=m;
+ return(s);
+}
+
+static char *f_s(char *s, int curloc)
+{
+ skip(s);
+ if(*s++!='(')
+ {
+ return(NULL);
+ }
+ if(f__parenlvl++ ==1) f__revloc=curloc;
+ if(op_gen(RET1,curloc,0,0)<0 ||
+ (s=f_list(s))==NULL)
+ {
+ return(NULL);
+ }
+ skip(s);
+ return(s);
+}
+
+static int ne_d(char *s, char **p)
+{ int n,x,sign=0;
+ struct syl *sp;
+ switch(*s)
+ {
+ default:
+ return(0);
+ case ':': (void) op_gen(COLON,0,0,0); break;
+ case '$':
+ (void) op_gen(NONL, 0, 0, 0); break;
+ case 'B':
+ case 'b':
+ if(*++s=='z' || *s == 'Z') (void) op_gen(BZ,0,0,0);
+ else (void) op_gen(BN,0,0,0);
+ break;
+ case 'S':
+ case 's':
+ if(*(s+1)=='s' || *(s+1) == 'S')
+ { x=SS;
+ s++;
+ }
+ else if(*(s+1)=='p' || *(s+1) == 'P')
+ { x=SP;
+ s++;
+ }
+ else x=S;
+ (void) op_gen(x,0,0,0);
+ break;
+ case '/': (void) op_gen(SLASH,0,0,0); break;
+ case '-': sign=1;
+ case '+': s++; /*OUTRAGEOUS CODING TRICK*/
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (!(s=gt_num(s,&n,0))) {
+ bad: *p = 0;
+ return 1;
+ }
+ switch(*s)
+ {
+ default:
+ return(0);
+ case 'P':
+ case 'p': if(sign) n= -n; (void) op_gen(P,n,0,0); break;
+ case 'X':
+ case 'x': (void) op_gen(X,n,0,0); break;
+ case 'H':
+ case 'h':
+ sp = &f__syl[op_gen(H,n,0,0)];
+ sp->p2.s = s + 1;
+ s+=n;
+ break;
+ }
+ break;
+ case GLITCH:
+ case '"':
+ case '\'':
+ sp = &f__syl[op_gen(APOS,0,0,0)];
+ sp->p2.s = s;
+ if((*p = ap_end(s)) == NULL)
+ return(0);
+ return(1);
+ case 'T':
+ case 't':
+ if(*(s+1)=='l' || *(s+1) == 'L')
+ { x=TL;
+ s++;
+ }
+ else if(*(s+1)=='r'|| *(s+1) == 'R')
+ { x=TR;
+ s++;
+ }
+ else x=T;
+ if (!(s=gt_num(s+1,&n,0)))
+ goto bad;
+ s--;
+ (void) op_gen(x,n,0,0);
+ break;
+ case 'X':
+ case 'x': (void) op_gen(X,1,0,0); break;
+ case 'P':
+ case 'p': (void) op_gen(P,1,0,0); break;
+ }
+ s++;
+ *p=s;
+ return(1);
+}
+
+static int e_d(char *s, char **p)
+{ int i,im,n,w,d,e,found=0,x=0;
+ char *sv=s;
+ s=gt_num(s,&n,1);
+ (void) op_gen(STACK,n,0,0);
+ switch(*s++)
+ {
+ default: break;
+ case 'E':
+ case 'e': x=1;
+ case 'G':
+ case 'g':
+ found=1;
+ if (!(s=gt_num(s,&w,0))) {
+ bad:
+ *p = 0;
+ return 1;
+ }
+ if(w==0) break;
+ if(*s=='.') {
+ if (!(s=gt_num(s+1,&d,0)))
+ goto bad;
+ }
+ else d=0;
+ if(*s!='E' && *s != 'e')
+ (void) op_gen(x==1?E:G,w,d,0); /* default is Ew.dE2 */
+ else {
+ if (!(s=gt_num(s+1,&e,0)))
+ goto bad;
+ (void) op_gen(x==1?EE:GE,w,d,e);
+ }
+ break;
+ case 'O':
+ case 'o':
+ i = O;
+ im = OM;
+ goto finish_I;
+ case 'Z':
+ case 'z':
+ i = Z;
+ im = ZM;
+ goto finish_I;
+ case 'L':
+ case 'l':
+ found=1;
+ if (!(s=gt_num(s,&w,0)))
+ goto bad;
+ if(w==0) break;
+ (void) op_gen(L,w,0,0);
+ break;
+ case 'A':
+ case 'a':
+ found=1;
+ skip(s);
+ if(*s>='0' && *s<='9')
+ { s=gt_num(s,&w,1);
+ if(w==0) break;
+ (void) op_gen(AW,w,0,0);
+ break;
+ }
+ (void) op_gen(A,0,0,0);
+ break;
+ case 'F':
+ case 'f':
+ if (!(s=gt_num(s,&w,0)))
+ goto bad;
+ found=1;
+ if(w==0) break;
+ if(*s=='.') {
+ if (!(s=gt_num(s+1,&d,0)))
+ goto bad;
+ }
+ else d=0;
+ (void) op_gen(F,w,d,0);
+ break;
+ case 'D':
+ case 'd':
+ found=1;
+ if (!(s=gt_num(s,&w,0)))
+ goto bad;
+ if(w==0) break;
+ if(*s=='.') {
+ if (!(s=gt_num(s+1,&d,0)))
+ goto bad;
+ }
+ else d=0;
+ (void) op_gen(D,w,d,0);
+ break;
+ case 'I':
+ case 'i':
+ i = I;
+ im = IM;
+ finish_I:
+ if (!(s=gt_num(s,&w,0)))
+ goto bad;
+ found=1;
+ if(w==0) break;
+ if(*s!='.')
+ { (void) op_gen(i,w,0,0);
+ break;
+ }
+ if (!(s=gt_num(s+1,&d,0)))
+ goto bad;
+ (void) op_gen(im,w,d,0);
+ break;
+ }
+ if(found==0)
+ { f__pc--; /*unSTACK*/
+ *p=sv;
+ return(0);
+ }
+ *p=s;
+ return(1);
+}
+
+static char *i_tem(char *s)
+{ char *t;
+ int n,curloc;
+ if(*s==')') return(s);
+ if(ne_d(s,&t)) return(t);
+ if(e_d(s,&t)) return(t);
+ s=gt_num(s,&n,1);
+ if((curloc=op_gen(STACK,n,0,0))<0) return(NULL);
+ return(f_s(s,curloc));
+}
+
+static char *f_list(char *s)
+{
+ for(;*s!=0;)
+ { skip(s);
+ if((s=i_tem(s))==NULL) return(NULL);
+ skip(s);
+ if(*s==',') s++;
+ else if(*s==')')
+ { if(--f__parenlvl==0)
+ {
+ (void) op_gen(REVERT,f__revloc,0,0);
+ return(++s);
+ }
+ (void) op_gen(GOTO,0,0,0);
+ return(++s);
+ }
+ }
+ return(NULL);
+}
+
+int pars_f(char *s)
+{
+ f__parenlvl=f__revloc=f__pc=0;
+ if(f_s(s,0) == NULL)
+ {
+ return(-1);
+ }
+ return(0);
+}
+
+#define STKSZ 10
+int f__cnt[STKSZ],f__ret[STKSZ],f__cp,f__rp;
+flag f__workdone, f__nonl;
+
+static int type_f(int n)
+{
+ switch(n)
+ {
+ default:
+ return(n);
+ case RET1:
+ return(RET1);
+ case REVERT: return(REVERT);
+ case GOTO: return(GOTO);
+ case STACK: return(STACK);
+ case X:
+ case SLASH:
+ case APOS: case H:
+ case T: case TL: case TR:
+ return(NED);
+ case F:
+ case I:
+ case IM:
+ case A: case AW:
+ case O: case OM:
+ case L:
+ case E: case EE: case D:
+ case G: case GE:
+ case Z: case ZM:
+ return(ED);
+ }
+}
+
+integer do_fio(ftnint *number, char *ptr, ftnlen len)
+{ struct syl *p;
+ int n,i;
+ for(i=0;i<*number;i++,ptr+=len)
+ {
+loop: switch(type_f((p= &f__syl[f__pc])->op))
+ {
+ default:
+ fprintf(stderr,"unknown code in do_fio: %d\n%s\n",
+ p->op,f__fmtbuf);
+ err(f__elist->cierr,100,"do_fio");
+ case NED:
+ if((*f__doned)(p))
+ { f__pc++;
+ goto loop;
+ }
+ f__pc++;
+ continue;
+ case ED:
+ if(f__cnt[f__cp]<=0)
+ { f__cp--;
+ f__pc++;
+ goto loop;
+ }
+ if(ptr==NULL)
+ return((*f__doend)());
+ f__cnt[f__cp]--;
+ f__workdone=1;
+ if((n=(*f__doed)(p,ptr,len))>0)
+ errfl(f__elist->cierr,errno,"fmt");
+ if(n<0)
+ err(f__elist->ciend,(EOF),"fmt");
+ continue;
+ case STACK:
+ f__cnt[++f__cp]=p->p1;
+ f__pc++;
+ goto loop;
+ case RET1:
+ f__ret[++f__rp]=p->p1;
+ f__pc++;
+ goto loop;
+ case GOTO:
+ if(--f__cnt[f__cp]<=0)
+ { f__cp--;
+ f__rp--;
+ f__pc++;
+ goto loop;
+ }
+ f__pc=1+f__ret[f__rp--];
+ goto loop;
+ case REVERT:
+ f__rp=f__cp=0;
+ f__pc = p->p1;
+ if(ptr==NULL)
+ return((*f__doend)());
+ if(!f__workdone) return(0);
+ if((n=(*f__dorevert)()) != 0) return(n);
+ goto loop;
+ case COLON:
+ if(ptr==NULL)
+ return((*f__doend)());
+ f__pc++;
+ goto loop;
+ case NONL:
+ f__nonl = 1;
+ f__pc++;
+ goto loop;
+ case S:
+ case SS:
+ f__cplus=0;
+ f__pc++;
+ goto loop;
+ case SP:
+ f__cplus = 1;
+ f__pc++;
+ goto loop;
+ case P: f__scale=p->p1;
+ f__pc++;
+ goto loop;
+ case BN:
+ f__cblank=0;
+ f__pc++;
+ goto loop;
+ case BZ:
+ f__cblank=1;
+ f__pc++;
+ goto loop;
+ }
+ }
+ return(0);
+}
+
+int en_fio(Void)
+{ ftnint one=1;
+ return(do_fio(&one,(char *)NULL,(ftnint)0));
+}
+
+ VOID
+fmt_bg(Void)
+{
+ f__workdone=f__cp=f__rp=f__pc=f__cursor=0;
+ f__cnt[0]=f__ret[0]=0;
+}
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/fmt.h b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fmt.h
new file mode 100644
index 00000000..b46bc9c5
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fmt.h
@@ -0,0 +1,86 @@
+struct syl
+{ int op;
+ int p1;
+ union { int i[2]; char *s;} p2;
+ };
+#define RET1 1
+#define REVERT 2
+#define GOTO 3
+#define X 4
+#define SLASH 5
+#define STACK 6
+#define I 7
+#define ED 8
+#define NED 9
+#define IM 10
+#define APOS 11
+#define H 12
+#define TL 13
+#define TR 14
+#define T 15
+#define COLON 16
+#define S 17
+#define SP 18
+#define SS 19
+#define P 20
+#define BN 21
+#define BZ 22
+#define F 23
+#define E 24
+#define EE 25
+#define D 26
+#define G 27
+#define GE 28
+#define L 29
+#define A 30
+#define AW 31
+#define O 32
+#define NONL 33
+#define OM 34
+#define Z 35
+#define ZM 36
+extern int f__pc,f__parenlvl,f__revloc;
+typedef union
+{ real pf;
+ doublereal pd;
+} ufloat;
+typedef union
+{ short is;
+ signed char ic;
+ integer il;
+#ifdef Allow_TYQUAD
+ longint ili;
+#endif
+} Uint;
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int (*f__doed)(struct syl*, char*, ftnlen),(*f__doned)(struct syl*);
+extern int (*f__dorevert)(void);
+extern void fmt_bg(void);
+extern int pars_f(char*);
+extern int rd_ed(struct syl*, char*, ftnlen),rd_ned(struct syl*);
+extern int w_ed(struct syl*, char*, ftnlen),w_ned(struct syl*);
+extern int wrt_E(ufloat*, int, int, int, ftnlen);
+extern int wrt_F(ufloat*, int, int, ftnlen);
+extern int wrt_L(Uint*, int, ftnlen);
+#ifdef __cplusplus
+ }
+#endif
+extern flag f__cblank,f__cplus,f__workdone, f__nonl;
+extern char *f__fmtbuf;
+extern int f__scale;
+#define GET(x) if((x=(*f__getn)())<0) return(x)
+#define VAL(x) (x!='\n'?x:' ')
+#define PUT(x) (*f__putn)(x)
+extern int f__cursor;
+
+#undef TYQUAD
+#ifndef Allow_TYQUAD
+#undef longint
+#define longint long
+#else
+#define TYQUAD 14
+#endif
+
+extern char *f__icvt(longint, int*, int*, int);
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/fmtlib.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fmtlib.c
new file mode 100644
index 00000000..8343337b
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fmtlib.c
@@ -0,0 +1,40 @@
+/* @(#)fmtlib.c 1.2 */
+#define MAXINTLENGTH 23
+
+#include "f2c.h"
+#ifndef Allow_TYQUAD
+#undef longint
+#define longint long
+#undef ulongint
+#define ulongint unsigned long
+#endif
+
+char *f__icvt(longint value, int *ndigit, int *sign, int base)
+{
+ static char buf[MAXINTLENGTH+1];
+ int i;
+ ulongint uvalue;
+
+ if(value > 0) {
+ uvalue = value;
+ *sign = 0;
+ }
+ else if (value < 0) {
+ uvalue = -value;
+ *sign = 1;
+ }
+ else {
+ *sign = 0;
+ *ndigit = 1;
+ buf[MAXINTLENGTH-1] = '0';
+ return &buf[MAXINTLENGTH-1];
+ }
+ i = MAXINTLENGTH;
+ do {
+ buf[--i] = (uvalue%base) + '0';
+ uvalue /= base;
+ }
+ while(uvalue > 0);
+ *ndigit = MAXINTLENGTH - i;
+ return &buf[i];
+ }
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/fp.h b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fp.h
new file mode 100644
index 00000000..40743d79
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/fp.h
@@ -0,0 +1,28 @@
+#define FMAX 40
+#define EXPMAXDIGS 8
+#define EXPMAX 99999999
+/* FMAX = max number of nonzero digits passed to atof() */
+/* EXPMAX = 10^EXPMAXDIGS - 1 = largest allowed exponent absolute value */
+
+#ifdef V10 /* Research Tenth-Edition Unix */
+#include "local.h"
+#endif
+
+/* MAXFRACDIGS and MAXINTDIGS are for wrt_F -- bounds (not necessarily
+ tight) on the maximum number of digits to the right and left of
+ * the decimal point.
+ */
+
+#ifdef VAX
+#define MAXFRACDIGS 56
+#define MAXINTDIGS 38
+#else
+#ifdef CRAY
+#define MAXFRACDIGS 9880
+#define MAXINTDIGS 9864
+#else
+/* values that suffice for IEEE double */
+#define MAXFRACDIGS 344
+#define MAXINTDIGS 308
+#endif
+#endif
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/idamax.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/idamax.c
new file mode 100644
index 00000000..2cc54813
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/idamax.c
@@ -0,0 +1,61 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+integer idamax_(integer *n, doublereal *dx, integer *incx)
+{
+ /* System generated locals */
+ integer ret_val, i__1;
+ doublereal d__1;
+ /* Local variables */
+ static doublereal dmax__;
+ static integer i__, ix;
+/* finds the index of element having max. absolute value.
+ jack dongarra, linpack, 3/11/78.
+ modified 3/93 to return if incx .le. 0.
+ modified 12/3/93, array(1) declarations changed to array(*)
+ Parameter adjustments */
+ --dx;
+ /* Function Body */
+ ret_val = 0;
+ if (*n < 1 || *incx <= 0) {
+ return ret_val;
+ }
+ ret_val = 1;
+ if (*n == 1) {
+ return ret_val;
+ }
+ if (*incx == 1) {
+ goto L20;
+ }
+/* code for increment not equal to 1 */
+ ix = 1;
+ dmax__ = abs(dx[1]);
+ ix += *incx;
+ i__1 = *n;
+ for (i__ = 2; i__ <= i__1; ++i__) {
+ if ((d__1 = dx[ix], abs(d__1)) <= dmax__) {
+ goto L5;
+ }
+ ret_val = i__;
+ dmax__ = (d__1 = dx[ix], abs(d__1));
+L5:
+ ix += *incx;
+/* L10: */
+ }
+ return ret_val;
+/* code for increment equal to 1 */
+L20:
+ dmax__ = abs(dx[1]);
+ i__1 = *n;
+ for (i__ = 2; i__ <= i__1; ++i__) {
+ if ((d__1 = dx[i__], abs(d__1)) <= dmax__) {
+ goto L30;
+ }
+ ret_val = i__;
+ dmax__ = (d__1 = dx[i__], abs(d__1));
+L30:
+ ;
+ }
+ return ret_val;
+} /* idamax_ */
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/ieeeck.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/ieeeck.c
new file mode 100644
index 00000000..39256a48
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/ieeeck.c
@@ -0,0 +1,150 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+integer ieeeck_(integer *ispec, real *zero, real *one)
+{
+/* -- LAPACK auxiliary routine (version 3.0) --
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+ Courant Institute, Argonne National Lab, and Rice University
+ June 30, 1998
+
+
+ Purpose
+ =======
+
+ IEEECK is called from the ILAENV to verify that Infinity and
+ possibly NaN arithmetic is safe (i.e. will not trap).
+
+ Arguments
+ =========
+
+ ISPEC (input) INTEGER
+ Specifies whether to test just for inifinity arithmetic
+ or whether to test for infinity and NaN arithmetic.
+ = 0: Verify infinity arithmetic only.
+ = 1: Verify infinity and NaN arithmetic.
+
+ ZERO (input) REAL
+ Must contain the value 0.0
+ This is passed to prevent the compiler from optimizing
+ away this code.
+
+ ONE (input) REAL
+ Must contain the value 1.0
+ This is passed to prevent the compiler from optimizing
+ away this code.
+
+ RETURN VALUE: INTEGER
+ = 0: Arithmetic failed to produce the correct answers
+ = 1: Arithmetic produced the correct answers */
+ /* System generated locals */
+ integer ret_val;
+ /* Local variables */
+ static real neginf, posinf, negzro, newzro, nan1, nan2, nan3, nan4, nan5,
+ nan6;
+
+
+ ret_val = 1;
+
+ posinf = *one / *zero;
+ if (posinf <= *one) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ neginf = -(*one) / *zero;
+ if (neginf >= *zero) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ negzro = *one / (neginf + *one);
+ if (negzro != *zero) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ neginf = *one / negzro;
+ if (neginf >= *zero) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ newzro = negzro + *zero;
+ if (newzro != *zero) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ posinf = *one / newzro;
+ if (posinf <= *one) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ neginf *= posinf;
+ if (neginf >= *zero) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ posinf *= posinf;
+ if (posinf <= *one) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+
+
+
+/* Return if we were only asked to check infinity arithmetic */
+
+ if (*ispec == 0) {
+ return ret_val;
+ }
+
+ nan1 = posinf + neginf;
+
+ nan2 = posinf / neginf;
+
+ nan3 = posinf / posinf;
+
+ nan4 = posinf * *zero;
+
+ nan5 = neginf * negzro;
+
+ nan6 = nan5 * 0.f;
+
+ if (nan1 == nan1) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ if (nan2 == nan2) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ if (nan3 == nan3) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ if (nan4 == nan4) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ if (nan5 == nan5) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ if (nan6 == nan6) {
+ ret_val = 0;
+ return ret_val;
+ }
+
+ return ret_val;
+} /* ieeeck_ */
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/ilaenv.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/ilaenv.c
new file mode 100644
index 00000000..58299fff
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/ilaenv.c
@@ -0,0 +1,610 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+integer ilaenv_(integer *ispec, char *name__, char *opts, integer *n1,
+ integer *n2, integer *n3, integer *n4, ftnlen name_len, ftnlen
+ opts_len)
+{
+/* -- LAPACK auxiliary routine (version 3.0) --
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+ Courant Institute, Argonne National Lab, and Rice University
+ June 30, 1999
+
+
+ Purpose
+ =======
+
+ ILAENV is called from the LAPACK routines to choose problem-dependent
+ parameters for the local environment. See ISPEC for a description of
+ the parameters.
+
+ This version provides a set of parameters which should give good,
+ but not optimal, performance on many of the currently available
+ computers. Users are encouraged to modify this subroutine to set
+ the tuning parameters for their particular machine using the option
+ and problem size information in the arguments.
+
+ This routine will not function correctly if it is converted to all
+ lower case. Converting it to all upper case is allowed.
+
+ Arguments
+ =========
+
+ ISPEC (input) INTEGER
+ Specifies the parameter to be returned as the value of
+ ILAENV.
+ = 1: the optimal blocksize; if this value is 1, an unblocked
+ algorithm will give the best performance.
+ = 2: the minimum block size for which the block routine
+ should be used; if the usable block size is less than
+ this value, an unblocked routine should be used.
+ = 3: the crossover point (in a block routine, for N less
+ than this value, an unblocked routine should be used)
+ = 4: the number of shifts, used in the nonsymmetric
+ eigenvalue routines
+ = 5: the minimum column dimension for blocking to be used;
+ rectangular blocks must have dimension at least k by m,
+ where k is given by ILAENV(2,...) and m by ILAENV(5,...)
+ = 6: the crossover point for the SVD (when reducing an m by n
+ matrix to bidiagonal form, if max(m,n)/min(m,n) exceeds
+ this value, a QR factorization is used first to reduce
+ the matrix to a triangular form.)
+ = 7: the number of processors
+ = 8: the crossover point for the multishift QR and QZ methods
+ for nonsymmetric eigenvalue problems.
+ = 9: maximum size of the subproblems at the bottom of the
+ computation tree in the divide-and-conquer algorithm
+ (used by xGELSD and xGESDD)
+ =10: ieee NaN arithmetic can be trusted not to trap
+ =11: infinity arithmetic can be trusted not to trap
+
+ NAME (input) CHARACTER*(*)
+ The name of the calling subroutine, in either upper case or
+ lower case.
+
+ OPTS (input) CHARACTER*(*)
+ The character options to the subroutine NAME, concatenated
+ into a single character string. For example, UPLO = 'U',
+ TRANS = 'T', and DIAG = 'N' for a triangular routine would
+ be specified as OPTS = 'UTN'.
+
+ N1 (input) INTEGER
+ N2 (input) INTEGER
+ N3 (input) INTEGER
+ N4 (input) INTEGER
+ Problem dimensions for the subroutine NAME; these may not all
+ be required.
+
+ (ILAENV) (output) INTEGER
+ >= 0: the value of the parameter specified by ISPEC
+ < 0: if ILAENV = -k, the k-th argument had an illegal value.
+
+ Further Details
+ ===============
+
+ The following conventions have been used when calling ILAENV from the
+ LAPACK routines:
+ 1) OPTS is a concatenation of all of the character options to
+ subroutine NAME, in the same order that they appear in the
+ argument list for NAME, even if they are not used in determining
+ the value of the parameter specified by ISPEC.
+ 2) The problem dimensions N1, N2, N3, N4 are specified in the order
+ that they appear in the argument list for NAME. N1 is used
+ first, N2 second, and so on, and unused problem dimensions are
+ passed a value of -1.
+ 3) The parameter value returned by ILAENV is checked for validity in
+ the calling subroutine. For example, ILAENV is used to retrieve
+ the optimal blocksize for STRTRI as follows:
+
+ NB = ILAENV( 1, 'STRTRI', UPLO // DIAG, N, -1, -1, -1 )
+ IF( NB.LE.1 ) NB = MAX( 1, N )
+
+ ===================================================================== */
+ /* Table of constant values */
+ static integer c__0 = 0;
+ static real c_b162 = 0.f;
+ static real c_b163 = 1.f;
+ static integer c__1 = 1;
+
+ /* System generated locals */
+ integer ret_val;
+ /* Builtin functions
+ Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen);
+ integer s_cmp(char *, char *, ftnlen, ftnlen);
+ /* Local variables */
+ static integer i__;
+ static logical cname, sname;
+ static integer nbmin;
+ static char c1[1], c2[2], c3[3], c4[2];
+ static integer ic, nb;
+ extern integer ieeeck_(integer *, real *, real *);
+ static integer iz, nx;
+ static char subnam[6];
+
+
+
+
+ switch (*ispec) {
+ case 1: goto L100;
+ case 2: goto L100;
+ case 3: goto L100;
+ case 4: goto L400;
+ case 5: goto L500;
+ case 6: goto L600;
+ case 7: goto L700;
+ case 8: goto L800;
+ case 9: goto L900;
+ case 10: goto L1000;
+ case 11: goto L1100;
+ }
+
+/* Invalid value for ISPEC */
+
+ ret_val = -1;
+ return ret_val;
+
+L100:
+
+/* Convert NAME to upper case if the first character is lower case. */
+
+ ret_val = 1;
+ s_copy(subnam, name__, (ftnlen)6, name_len);
+ ic = *(unsigned char *)subnam;
+ iz = 'Z';
+ if (iz == 90 || iz == 122) {
+
+/* ASCII character set */
+
+ if (ic >= 97 && ic <= 122) {
+ *(unsigned char *)subnam = (char) (ic - 32);
+ for (i__ = 2; i__ <= 6; ++i__) {
+ ic = *(unsigned char *)&subnam[i__ - 1];
+ if (ic >= 97 && ic <= 122) {
+ *(unsigned char *)&subnam[i__ - 1] = (char) (ic - 32);
+ }
+/* L10: */
+ }
+ }
+
+ } else if (iz == 233 || iz == 169) {
+
+/* EBCDIC character set */
+
+ if (ic >= 129 && ic <= 137 || ic >= 145 && ic <= 153 || ic >= 162 &&
+ ic <= 169) {
+ *(unsigned char *)subnam = (char) (ic + 64);
+ for (i__ = 2; i__ <= 6; ++i__) {
+ ic = *(unsigned char *)&subnam[i__ - 1];
+ if (ic >= 129 && ic <= 137 || ic >= 145 && ic <= 153 || ic >=
+ 162 && ic <= 169) {
+ *(unsigned char *)&subnam[i__ - 1] = (char) (ic + 64);
+ }
+/* L20: */
+ }
+ }
+
+ } else if (iz == 218 || iz == 250) {
+
+/* Prime machines: ASCII+128 */
+
+ if (ic >= 225 && ic <= 250) {
+ *(unsigned char *)subnam = (char) (ic - 32);
+ for (i__ = 2; i__ <= 6; ++i__) {
+ ic = *(unsigned char *)&subnam[i__ - 1];
+ if (ic >= 225 && ic <= 250) {
+ *(unsigned char *)&subnam[i__ - 1] = (char) (ic - 32);
+ }
+/* L30: */
+ }
+ }
+ }
+
+ *(unsigned char *)c1 = *(unsigned char *)subnam;
+ sname = *(unsigned char *)c1 == 'S' || *(unsigned char *)c1 == 'D';
+ cname = *(unsigned char *)c1 == 'C' || *(unsigned char *)c1 == 'Z';
+ if (! (cname || sname)) {
+ return ret_val;
+ }
+ s_copy(c2, subnam + 1, (ftnlen)2, (ftnlen)2);
+ s_copy(c3, subnam + 3, (ftnlen)3, (ftnlen)3);
+ s_copy(c4, c3 + 1, (ftnlen)2, (ftnlen)2);
+
+ switch (*ispec) {
+ case 1: goto L110;
+ case 2: goto L200;
+ case 3: goto L300;
+ }
+
+L110:
+
+/* ISPEC = 1: block size
+
+ In these examples, separate code is provided for setting NB for
+ real and complex. We assume that NB will take the same value in
+ single or double precision. */
+
+ nb = 1;
+
+ if (s_cmp(c2, "GE", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRF", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nb = 64;
+ } else {
+ nb = 64;
+ }
+ } else if (s_cmp(c3, "QRF", (ftnlen)3, (ftnlen)3) == 0 || s_cmp(c3,
+ "RQF", (ftnlen)3, (ftnlen)3) == 0 || s_cmp(c3, "LQF", (ftnlen)
+ 3, (ftnlen)3) == 0 || s_cmp(c3, "QLF", (ftnlen)3, (ftnlen)3)
+ == 0) {
+ if (sname) {
+ nb = 32;
+ } else {
+ nb = 32;
+ }
+ } else if (s_cmp(c3, "HRD", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nb = 32;
+ } else {
+ nb = 32;
+ }
+ } else if (s_cmp(c3, "BRD", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nb = 32;
+ } else {
+ nb = 32;
+ }
+ } else if (s_cmp(c3, "TRI", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nb = 64;
+ } else {
+ nb = 64;
+ }
+ }
+ } else if (s_cmp(c2, "PO", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRF", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nb = 64;
+ } else {
+ nb = 64;
+ }
+ }
+ } else if (s_cmp(c2, "SY", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRF", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nb = 64;
+ } else {
+ nb = 64;
+ }
+ } else if (sname && s_cmp(c3, "TRD", (ftnlen)3, (ftnlen)3) == 0) {
+ nb = 32;
+ } else if (sname && s_cmp(c3, "GST", (ftnlen)3, (ftnlen)3) == 0) {
+ nb = 64;
+ }
+ } else if (cname && s_cmp(c2, "HE", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRF", (ftnlen)3, (ftnlen)3) == 0) {
+ nb = 64;
+ } else if (s_cmp(c3, "TRD", (ftnlen)3, (ftnlen)3) == 0) {
+ nb = 32;
+ } else if (s_cmp(c3, "GST", (ftnlen)3, (ftnlen)3) == 0) {
+ nb = 64;
+ }
+ } else if (sname && s_cmp(c2, "OR", (ftnlen)2, (ftnlen)2) == 0) {
+ if (*(unsigned char *)c3 == 'G') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nb = 32;
+ }
+ } else if (*(unsigned char *)c3 == 'M') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nb = 32;
+ }
+ }
+ } else if (cname && s_cmp(c2, "UN", (ftnlen)2, (ftnlen)2) == 0) {
+ if (*(unsigned char *)c3 == 'G') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nb = 32;
+ }
+ } else if (*(unsigned char *)c3 == 'M') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nb = 32;
+ }
+ }
+ } else if (s_cmp(c2, "GB", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRF", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ if (*n4 <= 64) {
+ nb = 1;
+ } else {
+ nb = 32;
+ }
+ } else {
+ if (*n4 <= 64) {
+ nb = 1;
+ } else {
+ nb = 32;
+ }
+ }
+ }
+ } else if (s_cmp(c2, "PB", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRF", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ if (*n2 <= 64) {
+ nb = 1;
+ } else {
+ nb = 32;
+ }
+ } else {
+ if (*n2 <= 64) {
+ nb = 1;
+ } else {
+ nb = 32;
+ }
+ }
+ }
+ } else if (s_cmp(c2, "TR", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRI", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nb = 64;
+ } else {
+ nb = 64;
+ }
+ }
+ } else if (s_cmp(c2, "LA", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "UUM", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nb = 64;
+ } else {
+ nb = 64;
+ }
+ }
+ } else if (sname && s_cmp(c2, "ST", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "EBZ", (ftnlen)3, (ftnlen)3) == 0) {
+ nb = 1;
+ }
+ }
+ ret_val = nb;
+ return ret_val;
+
+L200:
+
+/* ISPEC = 2: minimum block size */
+
+ nbmin = 2;
+ if (s_cmp(c2, "GE", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "QRF", (ftnlen)3, (ftnlen)3) == 0 || s_cmp(c3, "RQF", (
+ ftnlen)3, (ftnlen)3) == 0 || s_cmp(c3, "LQF", (ftnlen)3, (
+ ftnlen)3) == 0 || s_cmp(c3, "QLF", (ftnlen)3, (ftnlen)3) == 0)
+ {
+ if (sname) {
+ nbmin = 2;
+ } else {
+ nbmin = 2;
+ }
+ } else if (s_cmp(c3, "HRD", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nbmin = 2;
+ } else {
+ nbmin = 2;
+ }
+ } else if (s_cmp(c3, "BRD", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nbmin = 2;
+ } else {
+ nbmin = 2;
+ }
+ } else if (s_cmp(c3, "TRI", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nbmin = 2;
+ } else {
+ nbmin = 2;
+ }
+ }
+ } else if (s_cmp(c2, "SY", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRF", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nbmin = 8;
+ } else {
+ nbmin = 8;
+ }
+ } else if (sname && s_cmp(c3, "TRD", (ftnlen)3, (ftnlen)3) == 0) {
+ nbmin = 2;
+ }
+ } else if (cname && s_cmp(c2, "HE", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRD", (ftnlen)3, (ftnlen)3) == 0) {
+ nbmin = 2;
+ }
+ } else if (sname && s_cmp(c2, "OR", (ftnlen)2, (ftnlen)2) == 0) {
+ if (*(unsigned char *)c3 == 'G') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nbmin = 2;
+ }
+ } else if (*(unsigned char *)c3 == 'M') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nbmin = 2;
+ }
+ }
+ } else if (cname && s_cmp(c2, "UN", (ftnlen)2, (ftnlen)2) == 0) {
+ if (*(unsigned char *)c3 == 'G') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nbmin = 2;
+ }
+ } else if (*(unsigned char *)c3 == 'M') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nbmin = 2;
+ }
+ }
+ }
+ ret_val = nbmin;
+ return ret_val;
+
+L300:
+
+/* ISPEC = 3: crossover point */
+
+ nx = 0;
+ if (s_cmp(c2, "GE", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "QRF", (ftnlen)3, (ftnlen)3) == 0 || s_cmp(c3, "RQF", (
+ ftnlen)3, (ftnlen)3) == 0 || s_cmp(c3, "LQF", (ftnlen)3, (
+ ftnlen)3) == 0 || s_cmp(c3, "QLF", (ftnlen)3, (ftnlen)3) == 0)
+ {
+ if (sname) {
+ nx = 128;
+ } else {
+ nx = 128;
+ }
+ } else if (s_cmp(c3, "HRD", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nx = 128;
+ } else {
+ nx = 128;
+ }
+ } else if (s_cmp(c3, "BRD", (ftnlen)3, (ftnlen)3) == 0) {
+ if (sname) {
+ nx = 128;
+ } else {
+ nx = 128;
+ }
+ }
+ } else if (s_cmp(c2, "SY", (ftnlen)2, (ftnlen)2) == 0) {
+ if (sname && s_cmp(c3, "TRD", (ftnlen)3, (ftnlen)3) == 0) {
+ nx = 32;
+ }
+ } else if (cname && s_cmp(c2, "HE", (ftnlen)2, (ftnlen)2) == 0) {
+ if (s_cmp(c3, "TRD", (ftnlen)3, (ftnlen)3) == 0) {
+ nx = 32;
+ }
+ } else if (sname && s_cmp(c2, "OR", (ftnlen)2, (ftnlen)2) == 0) {
+ if (*(unsigned char *)c3 == 'G') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nx = 128;
+ }
+ }
+ } else if (cname && s_cmp(c2, "UN", (ftnlen)2, (ftnlen)2) == 0) {
+ if (*(unsigned char *)c3 == 'G') {
+ if (s_cmp(c4, "QR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "RQ",
+ (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "LQ", (ftnlen)2, (
+ ftnlen)2) == 0 || s_cmp(c4, "QL", (ftnlen)2, (ftnlen)2) ==
+ 0 || s_cmp(c4, "HR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(
+ c4, "TR", (ftnlen)2, (ftnlen)2) == 0 || s_cmp(c4, "BR", (
+ ftnlen)2, (ftnlen)2) == 0) {
+ nx = 128;
+ }
+ }
+ }
+ ret_val = nx;
+ return ret_val;
+
+L400:
+
+/* ISPEC = 4: number of shifts (used by xHSEQR) */
+
+ ret_val = 6;
+ return ret_val;
+
+L500:
+
+/* ISPEC = 5: minimum column dimension (not used) */
+
+ ret_val = 2;
+ return ret_val;
+
+L600:
+
+/* ISPEC = 6: crossover point for SVD (used by xGELSS and xGESVD) */
+
+ ret_val = (integer) ((real) min(*n1,*n2) * 1.6f);
+ return ret_val;
+
+L700:
+
+/* ISPEC = 7: number of processors (not used) */
+
+ ret_val = 1;
+ return ret_val;
+
+L800:
+
+/* ISPEC = 8: crossover point for multishift (used by xHSEQR) */
+
+ ret_val = 50;
+ return ret_val;
+
+L900:
+
+/* ISPEC = 9: maximum size of the subproblems at the bottom of the
+ computation tree in the divide-and-conquer algorithm
+ (used by xGELSD and xGESDD) */
+
+ ret_val = 25;
+ return ret_val;
+
+L1000:
+
+/* ISPEC = 10: ieee NaN arithmetic can be trusted not to trap
+
+ ILAENV = 0 */
+ ret_val = 1;
+ if (ret_val == 1) {
+ ret_val = ieeeck_(&c__0, &c_b162, &c_b163);
+ }
+ return ret_val;
+
+L1100:
+
+/* ISPEC = 11: infinity arithmetic can be trusted not to trap
+
+ ILAENV = 0 */
+ ret_val = 1;
+ if (ret_val == 1) {
+ ret_val = ieeeck_(&c__1, &c_b162, &c_b163);
+ }
+ return ret_val;
+
+/* End of ILAENV */
+
+} /* ilaenv_ */
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/lsame.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/lsame.c
new file mode 100644
index 00000000..d9baaa3f
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/lsame.c
@@ -0,0 +1,101 @@
+#include "f2c.h"
+
+logical lsame_(char *ca, char *cb)
+{
+/* -- LAPACK auxiliary routine (version 3.0) --
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+ Courant Institute, Argonne National Lab, and Rice University
+ September 30, 1994
+
+
+ Purpose
+ =======
+
+ LSAME returns .TRUE. if CA is the same letter as CB regardless of
+ case.
+
+ Arguments
+ =========
+
+ CA (input) CHARACTER*1
+ CB (input) CHARACTER*1
+ CA and CB specify the single characters to be compared.
+
+ =====================================================================
+
+
+
+ Test if the characters are equal */
+ /* System generated locals */
+ logical ret_val;
+ /* Local variables */
+ static integer inta, intb, zcode;
+
+
+ ret_val = *(unsigned char *)ca == *(unsigned char *)cb;
+ if (ret_val) {
+ return ret_val;
+ }
+
+/* Now test for equivalence if both characters are alphabetic. */
+
+ zcode = 'Z';
+
+/* Use 'Z' rather than 'A' so that ASCII can be detected on Prime
+ machines, on which ICHAR returns a value with bit 8 set.
+ ICHAR('A') on Prime machines returns 193 which is the same as
+ ICHAR('A') on an EBCDIC machine. */
+
+ inta = *(unsigned char *)ca;
+ intb = *(unsigned char *)cb;
+
+ if (zcode == 90 || zcode == 122) {
+
+/* ASCII is assumed - ZCODE is the ASCII code of either lower o
+r
+ upper case 'Z'. */
+
+ if (inta >= 97 && inta <= 122) {
+ inta += -32;
+ }
+ if (intb >= 97 && intb <= 122) {
+ intb += -32;
+ }
+
+ } else if (zcode == 233 || zcode == 169) {
+
+/* EBCDIC is assumed - ZCODE is the EBCDIC code of either lower
+ or
+ upper case 'Z'. */
+
+ if (inta >= 129 && inta <= 137 || inta >= 145 && inta <= 153 || inta
+ >= 162 && inta <= 169) {
+ inta += 64;
+ }
+ if (intb >= 129 && intb <= 137 || intb >= 145 && intb <= 153 || intb
+ >= 162 && intb <= 169) {
+ intb += 64;
+ }
+
+ } else if (zcode == 218 || zcode == 250) {
+
+/* ASCII is assumed, on Prime machines - ZCODE is the ASCII cod
+e
+ plus 128 of either lower or upper case 'Z'. */
+
+ if (inta >= 225 && inta <= 250) {
+ inta += -32;
+ }
+ if (intb >= 225 && intb <= 250) {
+ intb += -32;
+ }
+ }
+ ret_val = inta == intb;
+
+/* RETURN
+
+ End of LSAME */
+
+ return ret_val;
+} /* lsame_ */
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/open.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/open.c
new file mode 100644
index 00000000..e7810757
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/open.c
@@ -0,0 +1,256 @@
+#include "f2c.h"
+#include "fio.h"
+#include "string.h"
+#ifndef NON_POSIX_STDIO
+#ifdef MSDOS
+#include "io.h"
+#else
+#include "unistd.h" /* for access */
+#endif
+#endif
+
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+extern int f__canseek(FILE*);
+extern integer f_clos(cllist*);
+
+#ifdef NON_ANSI_RW_MODES
+char *f__r_mode[2] = {"r", "r"};
+char *f__w_mode[4] = {"w", "w", "r+w", "r+w"};
+#else
+char *f__r_mode[2] = {"rb", "r"};
+char *f__w_mode[4] = {"wb", "w", "r+b", "r+"};
+#endif
+
+static char f__buf0[400], *f__buf = f__buf0;
+int f__buflen = (int)sizeof(f__buf0);
+
+static void f__bufadj(int n, int c)
+{
+ unsigned int len;
+ char *nbuf, *s, *t, *te;
+
+ if (f__buf == f__buf0)
+ f__buflen = 1024;
+ while(f__buflen <= n)
+ f__buflen <<= 1;
+ len = (unsigned int)f__buflen;
+ if (len != f__buflen || !(nbuf = (char*)malloc(len)))
+ f__fatal(113, "malloc failure");
+ s = nbuf;
+ t = f__buf;
+ te = t + c;
+ while(t < te)
+ *s++ = *t++;
+ if (f__buf != f__buf0)
+ free(f__buf);
+ f__buf = nbuf;
+ }
+
+int f__putbuf(int c)
+{
+ char *s, *se;
+ int n;
+
+ if (f__hiwater > f__recpos)
+ f__recpos = f__hiwater;
+ n = f__recpos + 1;
+ if (n >= f__buflen)
+ f__bufadj(n, f__recpos);
+ s = f__buf;
+ se = s + f__recpos;
+ if (c)
+ *se++ = c;
+ *se = 0;
+ for(;;) {
+ fputs(s, f__cf);
+ s += strlen(s);
+ if (s >= se)
+ break; /* normally happens the first time */
+ putc(*s++, f__cf);
+ }
+ return 0;
+ }
+
+void x_putc(int c)
+{
+ if (f__recpos >= f__buflen)
+ f__bufadj(f__recpos, f__buflen);
+ f__buf[f__recpos++] = c;
+ }
+
+#define opnerr(f,m,s) {if(f) errno= m; else opn_err(m,s,a); return(m);}
+
+static void opn_err(int m, char *s, olist *a)
+{
+ if (a->ofnm) {
+ /* supply file name to error message */
+ if (a->ofnmlen >= f__buflen)
+ f__bufadj((int)a->ofnmlen, 0);
+ g_char(a->ofnm, a->ofnmlen, f__curunit->ufnm = f__buf);
+ }
+ f__fatal(m, s);
+ }
+
+integer f_open(olist *a)
+{ unit *b;
+ integer rv;
+ char buf[256], *s;
+ cllist x;
+ int ufmt;
+ FILE *tf;
+#ifndef NON_UNIX_STDIO
+ int n;
+#endif
+ f__external = 1;
+ if(a->ounit>=MXUNIT || a->ounit<0)
+ err(a->oerr,101,"open")
+ if (!f__init)
+ f_init();
+ f__curunit = b = &f__units[a->ounit];
+ if(b->ufd) {
+ if(a->ofnm==0)
+ {
+ same: if (a->oblnk)
+ b->ublnk = *a->oblnk == 'z' || *a->oblnk == 'Z';
+ return(0);
+ }
+#ifdef NON_UNIX_STDIO
+ if (b->ufnm
+ && strlen(b->ufnm) == a->ofnmlen
+ && !strncmp(b->ufnm, a->ofnm, (unsigned)a->ofnmlen))
+ goto same;
+#else
+ g_char(a->ofnm,a->ofnmlen,buf);
+ if (f__inode(buf,&n) == b->uinode && n == b->udev)
+ goto same;
+#endif
+ x.cunit=a->ounit;
+ x.csta=0;
+ x.cerr=a->oerr;
+ if ((rv = f_clos(&x)) != 0)
+ return rv;
+ }
+ b->url = (int)a->orl;
+ b->ublnk = a->oblnk && (*a->oblnk == 'z' || *a->oblnk == 'Z');
+ if(a->ofm==0)
+ { if(b->url>0) b->ufmt=0;
+ else b->ufmt=1;
+ }
+ else if(*a->ofm=='f' || *a->ofm == 'F') b->ufmt=1;
+ else b->ufmt=0;
+ ufmt = b->ufmt;
+#ifdef url_Adjust
+ if (b->url && !ufmt)
+ url_Adjust(b->url);
+#endif
+ if (a->ofnm) {
+ g_char(a->ofnm,a->ofnmlen,buf);
+ if (!buf[0])
+ opnerr(a->oerr,107,"open")
+ }
+ else
+ sprintf(buf, "fort.%ld", (long)a->ounit);
+ b->uscrtch = 0;
+ b->uend=0;
+ b->uwrt = 0;
+ b->ufd = 0;
+ b->urw = 3;
+ switch(a->osta ? *a->osta : 'u')
+ {
+ case 'o':
+ case 'O':
+#ifdef NON_POSIX_STDIO
+ if (!(tf = fopen(buf,"r")))
+ opnerr(a->oerr,errno,"open")
+ fclose(tf);
+#else
+ if (access(buf,0))
+ opnerr(a->oerr,errno,"open")
+#endif
+ break;
+ case 's':
+ case 'S':
+ b->uscrtch=1;
+#ifdef NON_ANSI_STDIO
+ (void) strcpy(buf,"tmp.FXXXXXX");
+ (void) mktemp(buf);
+ goto replace;
+#else
+ if (!(b->ufd = tmpfile()))
+ opnerr(a->oerr,errno,"open")
+ b->ufnm = 0;
+#ifndef NON_UNIX_STDIO
+ b->uinode = b->udev = -1;
+#endif
+ b->useek = 1;
+ return 0;
+#endif
+
+ case 'n':
+ case 'N':
+#ifdef NON_POSIX_STDIO
+ if ((tf = fopen(buf,"r")) || (tf = fopen(buf,"a"))) {
+ fclose(tf);
+ opnerr(a->oerr,128,"open")
+ }
+#else
+ if (!access(buf,0))
+ opnerr(a->oerr,128,"open")
+#endif
+ /* no break */
+ case 'r': /* Fortran 90 replace option */
+ case 'R':
+#ifdef NON_ANSI_STDIO
+ replace:
+#endif
+ if (tf = fopen(buf,f__w_mode[0]))
+ fclose(tf);
+ }
+
+ b->ufnm=(char *) malloc((unsigned int)(strlen(buf)+1));
+ if(b->ufnm==NULL) opnerr(a->oerr,113,"no space");
+ (void) strcpy(b->ufnm,buf);
+ if ((s = a->oacc) && b->url)
+ ufmt = 0;
+ if(!(tf = fopen(buf, f__w_mode[ufmt|2]))) {
+ if (tf = fopen(buf, f__r_mode[ufmt]))
+ b->urw = 1;
+ else if (tf = fopen(buf, f__w_mode[ufmt])) {
+ b->uwrt = 1;
+ b->urw = 2;
+ }
+ else
+ err(a->oerr, errno, "open");
+ }
+ b->useek = f__canseek(b->ufd = tf);
+#ifndef NON_UNIX_STDIO
+ if((b->uinode = f__inode(buf,&b->udev)) == -1)
+ opnerr(a->oerr,108,"open")
+#endif
+ if(b->useek)
+ if (a->orl)
+ rewind(b->ufd);
+ else if ((s = a->oacc) && (*s == 'a' || *s == 'A')
+ && fseek(b->ufd, 0L, SEEK_END))
+ opnerr(a->oerr,129,"open");
+ return(0);
+}
+
+int fk_open(int seq, int fmt, ftnint n)
+{ char nbuf[10];
+ olist a;
+ (void) sprintf(nbuf,"fort.%ld",(long)n);
+ a.oerr=1;
+ a.ounit=n;
+ a.ofnm=nbuf;
+ a.ofnmlen=strlen(nbuf);
+ a.osta=NULL;
+ a.oacc= seq==SEQ?"s":"d";
+ a.ofm = fmt==FMT?"f":"u";
+ a.orl = seq==DIR?1:0;
+ a.oblnk=NULL;
+ return(f_open(&a));
+}
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/s_cmp.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/s_cmp.c
new file mode 100644
index 00000000..cd6a7dc4
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/s_cmp.c
@@ -0,0 +1,40 @@
+#include "f2c.h"
+
+/* compare two strings */
+
+integer s_cmp(char *a0, char *b0, ftnlen la, ftnlen lb)
+{
+unsigned char *a, *aend, *b, *bend;
+a = (unsigned char *)a0;
+b = (unsigned char *)b0;
+aend = a + la;
+bend = b + lb;
+
+if(la <= lb)
+ {
+ while(a < aend)
+ if(*a != *b)
+ return( *a - *b );
+ else
+ { ++a; ++b; }
+
+ while(b < bend)
+ if(*b != ' ')
+ return( ' ' - *b );
+ else ++b;
+ }
+
+else
+ {
+ while(b < bend)
+ if(*a == *b)
+ { ++a; ++b; }
+ else
+ return( *a - *b );
+ while(a < aend)
+ if(*a != ' ')
+ return(*a - ' ');
+ else ++a;
+ }
+return(0);
+}
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/s_copy.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/s_copy.c
new file mode 100644
index 00000000..289c67dd
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/s_copy.c
@@ -0,0 +1,47 @@
+/* Unless compiled with -DNO_OVERWRITE, this variant of s_copy allows the
+ * target of an assignment to appear on its right-hand side (contrary
+ * to the Fortran 77 Standard, but in accordance with Fortran 90),
+ * as in a(2:5) = a(4:7) .
+ */
+
+#include "f2c.h"
+
+/* assign strings: a = b */
+
+void s_copy(char *a, char *b, ftnlen la, ftnlen lb)
+{
+ char *aend, *bend;
+
+ aend = a + la;
+
+ if(la <= lb)
+#ifndef NO_OVERWRITE
+ if (a <= b || a >= b + la)
+#endif
+ while(a < aend)
+ *a++ = *b++;
+#ifndef NO_OVERWRITE
+ else
+ for(b += la; a < aend; )
+ *--aend = *--b;
+#endif
+
+ else {
+ bend = b + lb;
+#ifndef NO_OVERWRITE
+ if (a <= b || a >= bend)
+#endif
+ while(b < bend)
+ *a++ = *b++;
+#ifndef NO_OVERWRITE
+ else {
+ a += lb;
+ while(b < bend)
+ *--a = *--bend;
+ a += lb;
+ }
+#endif
+ while(a < aend)
+ *a++ = ' ';
+ }
+ }
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/s_stop.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/s_stop.c
new file mode 100644
index 00000000..049f71b6
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/s_stop.c
@@ -0,0 +1,37 @@
+#include "stdio.h"
+#include "f2c.h"
+
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+void f_exit(void);
+
+int s_stop(char *s, ftnlen n)
+{
+int i;
+
+if(n > 0)
+ {
+ fprintf(stderr, "STOP ");
+ for(i = 0; i<n ; ++i)
+ putc(*s++, stderr);
+ fprintf(stderr, " statement executed\n");
+ }
+#ifdef NO_ONEXIT
+f_exit();
+#endif
+exit(0);
+
+/* We cannot avoid (useless) compiler diagnostics here: */
+/* some compilers complain if there is no return statement, */
+/* and others complain that this one cannot be reached. */
+
+return 0; /* NOT REACHED */
+}
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/sfe.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/sfe.c
new file mode 100644
index 00000000..4f8907ea
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/sfe.c
@@ -0,0 +1,29 @@
+/* sequential formatted external common routines*/
+#include "f2c.h"
+#include "fio.h"
+
+extern char *f__fmtbuf;
+
+integer e_rsfe(Void)
+{ int n;
+ n=en_fio();
+ f__fmtbuf=NULL;
+ return(n);
+}
+
+int c_sfe(cilist *a) /* check */
+{ unit *p;
+ f__curunit = p = &f__units[a->ciunit];
+ if(a->ciunit >= MXUNIT || a->ciunit<0)
+ err(a->cierr,101,"startio");
+ if(p->ufd==NULL && fk_open(SEQ,FMT,a->ciunit)) err(a->cierr,114,"sfe")
+ if(!p->ufmt) err(a->cierr,102,"sfe")
+ return(0);
+}
+
+integer e_wsfe(Void)
+{
+ int n = en_fio();
+ f__fmtbuf = NULL;
+ return n;
+}
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/sig_die.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/sig_die.c
new file mode 100644
index 00000000..78335200
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/sig_die.c
@@ -0,0 +1,41 @@
+#include "stdio.h"
+#include "signal.h"
+
+#ifndef SIGIOT
+#ifdef SIGABRT
+#define SIGIOT SIGABRT
+#endif
+#endif
+
+#include "stdlib.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+ extern void f_exit(void);
+
+void sig_die(char *s, int kill)
+{
+ /* print error message, then clear buffers */
+ fprintf(stderr, "%s\n", s);
+
+ if(kill)
+ {
+ fflush(stderr);
+ f_exit();
+ fflush(stderr);
+ /* now get a core */
+#ifdef SIGIOT
+ signal(SIGIOT, SIG_DFL);
+#endif
+ abort();
+ }
+ else {
+#ifdef NO_ONEXIT
+ f_exit();
+#endif
+ exit(1);
+ }
+ }
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/util.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/util.c
new file mode 100644
index 00000000..684cdfc4
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/util.c
@@ -0,0 +1,39 @@
+#ifndef NON_UNIX_STDIO
+#define _INCLUDE_POSIX_SOURCE /* for HP-UX */
+#define _INCLUDE_XOPEN_SOURCE /* for HP-UX */
+#include "sys/types.h"
+#include "sys/stat.h"
+#endif
+#include "f2c.h"
+#include "fio.h"
+
+void g_char(char *a, ftnlen alen, char *b)
+{
+ char *x = a + alen, *y = b + alen;
+
+ for(;; y--) {
+ if (x <= a) {
+ *b = 0;
+ return;
+ }
+ if (*--x != ' ')
+ break;
+ }
+ *y-- = 0;
+ do *y-- = *x;
+ while(x-- > a);
+ }
+
+void b_char(char *a, char *b, ftnlen blen)
+{ int i;
+ for(i=0;i<blen && *a!=0;i++) *b++= *a++;
+ for(;i<blen;i++) *b++=' ';
+}
+#ifndef NON_UNIX_STDIO
+long f__inode(char *a, int *dev)
+{ struct stat x;
+ if(stat(a,&x)<0) return(-1);
+ *dev = x.st_dev;
+ return(x.st_ino);
+}
+#endif
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/wref.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/wref.c
new file mode 100644
index 00000000..636489c3
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/wref.c
@@ -0,0 +1,266 @@
+#include "f2c.h"
+#include "fio.h"
+
+#undef abs
+#undef min
+#undef max
+#include "stdlib.h"
+#include "string.h"
+
+#include "fmt.h"
+#include "fp.h"
+#ifndef VAX
+#include "ctype.h"
+#endif
+
+int wrt_E(ufloat *p, int w, int d, int e, ftnlen len)
+{
+ char buf[FMAX+EXPMAXDIGS+4], *s, *se;
+ int d1, delta, e1, i, sign, signspace;
+ double dd;
+#ifdef WANT_LEAD_0
+ int insert0 = 0;
+#endif
+#ifndef VAX
+ int e0 = e;
+#endif
+
+ if(e <= 0)
+ e = 2;
+ if(f__scale) {
+ if(f__scale >= d + 2 || f__scale <= -d)
+ goto nogood;
+ }
+ if(f__scale <= 0)
+ --d;
+ if (len == sizeof(real))
+ dd = p->pf;
+ else
+ dd = p->pd;
+ if (dd < 0.) {
+ signspace = sign = 1;
+ dd = -dd;
+ }
+ else {
+ sign = 0;
+ signspace = (int)f__cplus;
+#ifndef VAX
+ if (!dd)
+ dd = 0.; /* avoid -0 */
+#endif
+ }
+ delta = w - (2 /* for the . and the d adjustment above */
+ + 2 /* for the E+ */ + signspace + d + e);
+#ifdef WANT_LEAD_0
+ if (f__scale <= 0 && delta > 0) {
+ delta--;
+ insert0 = 1;
+ }
+ else
+#endif
+ if (delta < 0) {
+nogood:
+ while(--w >= 0)
+ PUT('*');
+ return(0);
+ }
+ if (f__scale < 0)
+ d += f__scale;
+ if (d > FMAX) {
+ d1 = d - FMAX;
+ d = FMAX;
+ }
+ else
+ d1 = 0;
+ sprintf(buf,"%#.*E", d, dd);
+#ifndef VAX
+ /* check for NaN, Infinity */
+ if (!isdigit(buf[0])) {
+ switch(buf[0]) {
+ case 'n':
+ case 'N':
+ signspace = 0; /* no sign for NaNs */
+ }
+ delta = w - strlen(buf) - signspace;
+ if (delta < 0)
+ goto nogood;
+ while(--delta >= 0)
+ PUT(' ');
+ if (signspace)
+ PUT(sign ? '-' : '+');
+ for(s = buf; *s; s++)
+ PUT(*s);
+ return 0;
+ }
+#endif
+ se = buf + d + 3;
+#ifdef GOOD_SPRINTF_EXPONENT /* When possible, exponent has 2 digits. */
+ if (f__scale != 1 && dd)
+ sprintf(se, "%+.2d", atoi(se) + 1 - f__scale);
+#else
+ if (dd)
+ sprintf(se, "%+.2d", atoi(se) + 1 - f__scale);
+ else
+ strcpy(se, "+00");
+#endif
+ s = ++se;
+ if (e < 2) {
+ if (*s != '0')
+ goto nogood;
+ }
+#ifndef VAX
+ /* accommodate 3 significant digits in exponent */
+ if (s[2]) {
+#ifdef Pedantic
+ if (!e0 && !s[3])
+ for(s -= 2, e1 = 2; s[0] = s[1]; s++);
+
+ /* Pedantic gives the behavior that Fortran 77 specifies, */
+ /* i.e., requires that E be specified for exponent fields */
+ /* of more than 3 digits. With Pedantic undefined, we get */
+ /* the behavior that Cray displays -- you get a bigger */
+ /* exponent field if it fits. */
+#else
+ if (!e0) {
+ for(s -= 2, e1 = 2; s[0] = s[1]; s++)
+#ifdef CRAY
+ delta--;
+ if ((delta += 4) < 0)
+ goto nogood
+#endif
+ ;
+ }
+#endif
+ else if (e0 >= 0)
+ goto shift;
+ else
+ e1 = e;
+ }
+ else
+ shift:
+#endif
+ for(s += 2, e1 = 2; *s; ++e1, ++s)
+ if (e1 >= e)
+ goto nogood;
+ while(--delta >= 0)
+ PUT(' ');
+ if (signspace)
+ PUT(sign ? '-' : '+');
+ s = buf;
+ i = f__scale;
+ if (f__scale <= 0) {
+#ifdef WANT_LEAD_0
+ if (insert0)
+ PUT('0');
+#endif
+ PUT('.');
+ for(; i < 0; ++i)
+ PUT('0');
+ PUT(*s);
+ s += 2;
+ }
+ else if (f__scale > 1) {
+ PUT(*s);
+ s += 2;
+ while(--i > 0)
+ PUT(*s++);
+ PUT('.');
+ }
+ if (d1) {
+ se -= 2;
+ while(s < se) PUT(*s++);
+ se += 2;
+ do PUT('0'); while(--d1 > 0);
+ }
+ while(s < se)
+ PUT(*s++);
+ if (e < 2)
+ PUT(s[1]);
+ else {
+ while(++e1 <= e)
+ PUT('0');
+ while(*s)
+ PUT(*s++);
+ }
+ return 0;
+ }
+
+int wrt_F(ufloat *p, int w, int d, ftnlen len)
+{
+ int d1, sign, n;
+ double x;
+ char *b, buf[MAXINTDIGS+MAXFRACDIGS+4], *s;
+
+ x= (len==sizeof(real)?p->pf:p->pd);
+ if (d < MAXFRACDIGS)
+ d1 = 0;
+ else {
+ d1 = d - MAXFRACDIGS;
+ d = MAXFRACDIGS;
+ }
+ if (x < 0.)
+ { x = -x; sign = 1; }
+ else {
+ sign = 0;
+#ifndef VAX
+ if (!x)
+ x = 0.;
+#endif
+ }
+
+ if (n = f__scale)
+ if (n > 0)
+ do x *= 10.; while(--n > 0);
+ else
+ do x *= 0.1; while(++n < 0);
+
+#ifdef USE_STRLEN
+ sprintf(b = buf, "%#.*f", d, x);
+ n = strlen(b) + d1;
+#else
+ n = sprintf(b = buf, "%#.*f", d, x) + d1;
+#endif
+
+#ifndef WANT_LEAD_0
+ if (buf[0] == '0' && d)
+ { ++b; --n; }
+#endif
+ if (sign) {
+ /* check for all zeros */
+ for(s = b;;) {
+ while(*s == '0') s++;
+ switch(*s) {
+ case '.':
+ s++; continue;
+ case 0:
+ sign = 0;
+ }
+ break;
+ }
+ }
+ if (sign || f__cplus)
+ ++n;
+ if (n > w) {
+#ifdef WANT_LEAD_0
+ if (buf[0] == '0' && --n == w)
+ ++b;
+ else
+#endif
+ {
+ while(--w >= 0)
+ PUT('*');
+ return 0;
+ }
+ }
+ for(w -= n; --w >= 0; )
+ PUT(' ');
+ if (sign)
+ PUT('-');
+ else if (f__cplus)
+ PUT('+');
+ while(n = *b++)
+ PUT(n);
+ while(--d1 >= 0)
+ PUT('0');
+ return 0;
+ }
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/wrtfmt.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/wrtfmt.c
new file mode 100644
index 00000000..74d1131a
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/wrtfmt.c
@@ -0,0 +1,321 @@
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+
+extern icilist *f__svic;
+extern char *f__icptr;
+
+ static int
+mv_cur(Void) /* shouldn't use fseek because it insists on calling fflush */
+ /* instead we know too much about stdio */
+{
+ int cursor = f__cursor;
+ f__cursor = 0;
+ if(f__external == 0) {
+ if(cursor < 0) {
+ if(f__hiwater < f__recpos)
+ f__hiwater = f__recpos;
+ f__recpos += cursor;
+ f__icptr += cursor;
+ if(f__recpos < 0)
+ err(f__elist->cierr, 110, "left off");
+ }
+ else if(cursor > 0) {
+ if(f__recpos + cursor >= f__svic->icirlen)
+ err(f__elist->cierr, 110, "recend");
+ if(f__hiwater <= f__recpos)
+ for(; cursor > 0; cursor--)
+ (*f__putn)(' ');
+ else if(f__hiwater <= f__recpos + cursor) {
+ cursor -= f__hiwater - f__recpos;
+ f__icptr += f__hiwater - f__recpos;
+ f__recpos = f__hiwater;
+ for(; cursor > 0; cursor--)
+ (*f__putn)(' ');
+ }
+ else {
+ f__icptr += cursor;
+ f__recpos += cursor;
+ }
+ }
+ return(0);
+ }
+ if (cursor > 0) {
+ if(f__hiwater <= f__recpos)
+ for(;cursor>0;cursor--) (*f__putn)(' ');
+ else if(f__hiwater <= f__recpos + cursor) {
+ cursor -= f__hiwater - f__recpos;
+ f__recpos = f__hiwater;
+ for(; cursor > 0; cursor--)
+ (*f__putn)(' ');
+ }
+ else {
+ f__recpos += cursor;
+ }
+ }
+ else if (cursor < 0)
+ {
+ if(cursor + f__recpos < 0)
+ err(f__elist->cierr,110,"left off");
+ if(f__hiwater < f__recpos)
+ f__hiwater = f__recpos;
+ f__recpos += cursor;
+ }
+ return(0);
+}
+
+static int wrt_Z(Uint *n, int w, int minlen, ftnlen len)
+{
+ char *s, *se;
+ int i, w1;
+ static int one = 1;
+ static char hex[] = "0123456789ABCDEF";
+ s = (char *)n;
+ --len;
+ if (*(char *)&one) {
+ /* little endian */
+ se = s;
+ s += len;
+ i = -1;
+ }
+ else {
+ se = s + len;
+ i = 1;
+ }
+ for(;; s += i)
+ if (s == se || *s)
+ break;
+ w1 = (i*(se-s) << 1) + 1;
+ if (*s & 0xf0)
+ w1++;
+ if (w1 > w)
+ for(i = 0; i < w; i++)
+ (*f__putn)('*');
+ else {
+ if ((minlen -= w1) > 0)
+ w1 += minlen;
+ while(--w >= w1)
+ (*f__putn)(' ');
+ while(--minlen >= 0)
+ (*f__putn)('0');
+ if (!(*s & 0xf0)) {
+ (*f__putn)(hex[*s & 0xf]);
+ if (s == se)
+ return 0;
+ s += i;
+ }
+ for(;; s += i) {
+ (*f__putn)(hex[*s >> 4 & 0xf]);
+ (*f__putn)(hex[*s & 0xf]);
+ if (s == se)
+ break;
+ }
+ }
+ return 0;
+ }
+
+static int wrt_I(Uint *n, int w, ftnlen len, int base)
+{ int ndigit,sign,spare,i;
+ longint x;
+ char *ans;
+ if(len==sizeof(integer)) x=n->il;
+ else if(len == sizeof(char)) x = n->ic;
+#ifdef Allow_TYQUAD
+ else if (len == sizeof(longint)) x = n->ili;
+#endif
+ else x=n->is;
+ ans=f__icvt(x,&ndigit,&sign, base);
+ spare=w-ndigit;
+ if(sign || f__cplus) spare--;
+ if(spare<0)
+ for(i=0;i<w;i++) (*f__putn)('*');
+ else
+ { for(i=0;i<spare;i++) (*f__putn)(' ');
+ if(sign) (*f__putn)('-');
+ else if(f__cplus) (*f__putn)('+');
+ for(i=0;i<ndigit;i++) (*f__putn)(*ans++);
+ }
+ return(0);
+}
+
+static int wrt_IM(Uint *n, int w, int m, ftnlen len, int base)
+{ int ndigit,sign,spare,i,xsign;
+ longint x;
+ char *ans;
+ if(sizeof(integer)==len) x=n->il;
+ else if(len == sizeof(char)) x = n->ic;
+#ifdef Allow_TYQUAD
+ else if (len == sizeof(longint)) x = n->ili;
+#endif
+ else x=n->is;
+ ans=f__icvt(x,&ndigit,&sign, base);
+ if(sign || f__cplus) xsign=1;
+ else xsign=0;
+ if(ndigit+xsign>w || m+xsign>w)
+ { for(i=0;i<w;i++) (*f__putn)('*');
+ return(0);
+ }
+ if(x==0 && m==0)
+ { for(i=0;i<w;i++) (*f__putn)(' ');
+ return(0);
+ }
+ if(ndigit>=m)
+ spare=w-ndigit-xsign;
+ else
+ spare=w-m-xsign;
+ for(i=0;i<spare;i++) (*f__putn)(' ');
+ if(sign) (*f__putn)('-');
+ else if(f__cplus) (*f__putn)('+');
+ for(i=0;i<m-ndigit;i++) (*f__putn)('0');
+ for(i=0;i<ndigit;i++) (*f__putn)(*ans++);
+ return(0);
+}
+
+static int wrt_AP(char *s)
+{ char quote;
+ int i;
+
+ if(f__cursor && (i = mv_cur()))
+ return i;
+ quote = *s++;
+ for(;*s;s++)
+ { if(*s!=quote) (*f__putn)(*s);
+ else if(*++s==quote) (*f__putn)(*s);
+ else return(1);
+ }
+ return(1);
+}
+
+static int wrt_H(int a, char *s)
+{
+ int i;
+
+ if(f__cursor && (i = mv_cur()))
+ return i;
+ while(a--) (*f__putn)(*s++);
+ return(1);
+}
+
+int wrt_L(Uint *n, int len, ftnlen sz)
+{ int i;
+ long x;
+ if(sizeof(long)==sz) x=n->il;
+ else if(sz == sizeof(char)) x = n->ic;
+ else x=n->is;
+ for(i=0;i<len-1;i++)
+ (*f__putn)(' ');
+ if(x) (*f__putn)('T');
+ else (*f__putn)('F');
+ return(0);
+}
+
+static int wrt_A(char *p, ftnlen len)
+{
+ while(len-- > 0) (*f__putn)(*p++);
+ return(0);
+}
+
+static int wrt_AW(char * p, int w, ftnlen len)
+{
+ while(w>len)
+ { w--;
+ (*f__putn)(' ');
+ }
+ while(w-- > 0)
+ (*f__putn)(*p++);
+ return(0);
+}
+
+static int wrt_G(ufloat *p, int w, int d, int e, ftnlen len)
+{ double up = 1,x;
+ int i=0,oldscale,n,j;
+ x = len==sizeof(real)?p->pf:p->pd;
+ if(x < 0 ) x = -x;
+ if(x<.1) {
+ if (x != 0.)
+ return(wrt_E(p,w,d,e,len));
+ i = 1;
+ goto have_i;
+ }
+ for(;i<=d;i++,up*=10)
+ { if(x>=up) continue;
+ have_i:
+ oldscale = f__scale;
+ f__scale = 0;
+ if(e==0) n=4;
+ else n=e+2;
+ i=wrt_F(p,w-n,d-i,len);
+ for(j=0;j<n;j++) (*f__putn)(' ');
+ f__scale=oldscale;
+ return(i);
+ }
+ return(wrt_E(p,w,d,e,len));
+}
+
+int w_ed(struct syl *p, char *ptr, ftnlen len)
+{
+ int i;
+
+ if(f__cursor && (i = mv_cur()))
+ return i;
+ switch(p->op)
+ {
+ default:
+ fprintf(stderr,"w_ed, unexpected code: %d\n", p->op);
+ sig_die(f__fmtbuf, 1);
+ case I: return(wrt_I((Uint *)ptr,p->p1,len, 10));
+ case IM:
+ return(wrt_IM((Uint *)ptr,p->p1,p->p2.i[0],len,10));
+
+ /* O and OM don't work right for character, double, complex, */
+ /* or doublecomplex, and they differ from Fortran 90 in */
+ /* showing a minus sign for negative values. */
+
+ case O: return(wrt_I((Uint *)ptr, p->p1, len, 8));
+ case OM:
+ return(wrt_IM((Uint *)ptr,p->p1,p->p2.i[0],len,8));
+ case L: return(wrt_L((Uint *)ptr,p->p1, len));
+ case A: return(wrt_A(ptr,len));
+ case AW:
+ return(wrt_AW(ptr,p->p1,len));
+ case D:
+ case E:
+ case EE:
+ return(wrt_E((ufloat *)ptr,p->p1,p->p2.i[0],p->p2.i[1],len));
+ case G:
+ case GE:
+ return(wrt_G((ufloat *)ptr,p->p1,p->p2.i[0],p->p2.i[1],len));
+ case F: return(wrt_F((ufloat *)ptr,p->p1,p->p2.i[0],len));
+
+ /* Z and ZM assume 8-bit bytes. */
+
+ case Z: return(wrt_Z((Uint *)ptr,p->p1,0,len));
+ case ZM:
+ return(wrt_Z((Uint *)ptr,p->p1,p->p2.i[0],len));
+ }
+}
+
+int w_ned(struct syl *p)
+{
+ switch(p->op)
+ {
+ default: fprintf(stderr,"w_ned, unexpected code: %d\n", p->op);
+ sig_die(f__fmtbuf, 1);
+ case SLASH:
+ return((*f__donewrec)());
+ case T: f__cursor = p->p1-f__recpos - 1;
+ return(1);
+ case TL: f__cursor -= p->p1;
+ if(f__cursor < -f__recpos) /* TL1000, 1X */
+ f__cursor = -f__recpos;
+ return(1);
+ case TR:
+ case X:
+ f__cursor += p->p1;
+ return(1);
+ case APOS:
+ return(wrt_AP(p->p2.s));
+ case H:
+ return(wrt_H(p->p1,p->p2.s));
+ }
+}
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/wsfe.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/wsfe.c
new file mode 100644
index 00000000..b772df32
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/wsfe.c
@@ -0,0 +1,69 @@
+/*write sequential formatted external*/
+#include "f2c.h"
+#include "fio.h"
+#include "fmt.h"
+extern int f__hiwater;
+
+ int
+x_wSL(Void)
+{
+ int n = f__putbuf('\n');
+ f__hiwater = f__recpos = f__cursor = 0;
+ return(n == 0);
+}
+
+ static int
+xw_end(Void)
+{
+ int n;
+
+ if(f__nonl) {
+ f__putbuf(n = 0);
+ fflush(f__cf);
+ }
+ else
+ n = f__putbuf('\n');
+ f__hiwater = f__recpos = f__cursor = 0;
+ return n;
+}
+
+ static int
+xw_rev(Void)
+{
+ int n = 0;
+ if(f__workdone) {
+ n = f__putbuf('\n');
+ f__workdone = 0;
+ }
+ f__hiwater = f__recpos = f__cursor = 0;
+ return n;
+}
+
+integer s_wsfe(cilist *a) /*start*/
+{ int n;
+ if(!f__init) f_init();
+ f__reading=0;
+ f__sequential=1;
+ f__formatted=1;
+ f__external=1;
+ if(n=c_sfe(a)) return(n);
+ f__elist=a;
+ f__hiwater = f__cursor=f__recpos=0;
+ f__nonl = 0;
+ f__scale=0;
+ f__fmtbuf=a->cifmt;
+ f__cf=f__curunit->ufd;
+ if(pars_f(f__fmtbuf)<0) err(a->cierr,100,"startio");
+ f__putn= x_putc;
+ f__doed= w_ed;
+ f__doned= w_ned;
+ f__doend=xw_end;
+ f__dorevert=xw_rev;
+ f__donewrec=x_wSL;
+ fmt_bg();
+ f__cplus=0;
+ f__cblank=f__curunit->ublnk;
+ if(f__curunit->uwrt != 1 && f__nowwriting(f__curunit))
+ err(a->cierr,errno,"write start");
+ return(0);
+}
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/clapack/xerbla.c b/src/imageplugins/coreplugin/sharpnesseditor/clapack/xerbla.c
new file mode 100644
index 00000000..d8ef512b
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/clapack/xerbla.c
@@ -0,0 +1,58 @@
+#include "blaswrap.h"
+#include "f2c.h"
+
+/* Subroutine */ int xerbla_(char *srname, integer *info)
+{
+/* -- LAPACK auxiliary routine (preliminary version) --
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+ Courant Institute, Argonne National Lab, and Rice University
+ February 29, 1992
+
+
+ Purpose
+ =======
+
+ XERBLA is an error handler for the LAPACK routines.
+ It is called by an LAPACK routine if an input parameter has an
+ invalid value. A message is printed and execution stops.
+
+ Installers may consider modifying the STOP statement in order to
+ call system-specific exception-handling facilities.
+
+ Arguments
+ =========
+
+ SRNAME (input) CHARACTER*6
+ The name of the routine which called XERBLA.
+
+ INFO (input) INTEGER
+ The position of the invalid parameter in the parameter list
+ of the calling routine. */
+ /* Table of constant values */
+ static integer c__1 = 1;
+
+ /* Format strings */
+ static char fmt_9999[] = "(\002 ** On entry to \002,a6,\002 parameter nu"
+ "mber \002,i2,\002 had \002,\002an illegal value\002)";
+ /* Builtin functions */
+ integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void);
+ /* Subroutine */ int s_stop(char *, ftnlen);
+ /* Fortran I/O blocks */
+ static cilist io___1 = { 0, 6, 0, fmt_9999, 0 };
+
+
+
+
+ s_wsfe(&io___1);
+ do_fio(&c__1, srname, (ftnlen)6);
+ do_fio(&c__1, (char *)&(*info), (ftnlen)sizeof(integer));
+ e_wsfe();
+
+ s_stop("", (ftnlen)0);
+
+
+/* End of XERBLA */
+
+ return 0;
+} /* xerbla_ */
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/imageeffect_sharpen.cpp b/src/imageplugins/coreplugin/sharpnesseditor/imageeffect_sharpen.cpp
new file mode 100644
index 00000000..b2ae9a62
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/imageeffect_sharpen.cpp
@@ -0,0 +1,696 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-09
+ * Description : a tool to sharp an image
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#define MAX_MATRIX_SIZE 25
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqcombobox.h>
+#include <tqwidgetstack.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <knuminput.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+#include <kseparator.h>
+#include <tdeconfig.h>
+#include <kurl.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <tdemessagebox.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imageiface.h"
+#include "dimgsharpen.h"
+#include "unsharp.h"
+#include "refocus.h"
+#include "imageeffect_sharpen.h"
+#include "imageeffect_sharpen.moc"
+
+namespace DigikamImagesPluginCore
+{
+
+ImageEffect_Sharpen::ImageEffect_Sharpen(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Sharpening Photograph"), "sharpen",
+ true, true, true)
+{
+ setHelp("blursharpentool.anchor", "digikam");
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 2, 1, 0, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Method:"), gboxSettings);
+
+ m_sharpMethod = new TQComboBox( false, gboxSettings );
+ m_sharpMethod->insertItem( i18n("Simple sharp") );
+ m_sharpMethod->insertItem( i18n("Unsharp mask") );
+ m_sharpMethod->insertItem( i18n("Refocus") );
+ TQWhatsThis::add( m_sharpMethod, i18n("<p>Select the sharpening method to apply to the image."));
+
+ m_stack = new TQWidgetStack(gboxSettings);
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridSettings->addMultiCellWidget(m_sharpMethod, 0, 0, 1, 1);
+ gridSettings->addMultiCellWidget(new KSeparator(gboxSettings), 1, 1, 0, 1);
+ gridSettings->addMultiCellWidget(m_stack, 2, 2, 0, 1);
+
+ // -------------------------------------------------------------
+
+ TQWidget *simpleSharpSettings = new TQWidget(m_stack);
+ TQGridLayout* grid1 = new TQGridLayout( simpleSharpSettings, 2, 1, 0, spacingHint());
+
+ TQLabel *label = new TQLabel(i18n("Sharpness:"), simpleSharpSettings);
+ m_radiusInput = new KIntNumInput(simpleSharpSettings);
+ m_radiusInput->setRange(0, 100, 1, true);
+ m_radiusInput->setValue(0);
+ TQWhatsThis::add( m_radiusInput, i18n("<p>A sharpness of 0 has no effect, "
+ "1 and above determine the sharpen matrix radius "
+ "that determines how much to sharpen the image."));
+
+ grid1->addMultiCellWidget(label, 0, 0, 0, 1);
+ grid1->addMultiCellWidget(m_radiusInput, 1, 1, 0, 1);
+ grid1->setRowStretch(2, 10);
+ m_stack->addWidget(simpleSharpSettings, SimpleSharp);
+
+ // -------------------------------------------------------------
+
+ TQWidget *unsharpMaskSettings = new TQWidget(m_stack);
+ TQGridLayout* grid2 = new TQGridLayout( unsharpMaskSettings, 6, 1, 0, spacingHint());
+
+ TQLabel *label2 = new TQLabel(i18n("Radius:"), unsharpMaskSettings);
+ m_radiusInput2 = new KIntNumInput(unsharpMaskSettings);
+ m_radiusInput2->setRange(1, 120, 1, true);
+ TQWhatsThis::add( m_radiusInput2, i18n("<p>Radius value is the gaussian blur matrix radius value "
+ "used to determines how much to blur the image.") );
+
+ TQLabel *label3 = new TQLabel(i18n("Amount:"), unsharpMaskSettings);
+ m_amountInput = new KDoubleNumInput(unsharpMaskSettings);
+ m_amountInput->setPrecision(1);
+ m_amountInput->setRange(0.0, 5.0, 0.1, true);
+ TQWhatsThis::add( m_amountInput, i18n("<p>The value of the difference between the "
+ "original and the blur image that is added back into the original.") );
+
+ TQLabel *label4 = new TQLabel(i18n("Threshold:"), unsharpMaskSettings);
+ m_thresholdInput = new KDoubleNumInput(unsharpMaskSettings);
+ m_thresholdInput->setPrecision(2);
+ m_thresholdInput->setRange(0.0, 1.0, 0.01, true);
+ TQWhatsThis::add( m_thresholdInput, i18n("<p>The threshold, as a fraction of the maximum "
+ "luminosity value, needed to apply the difference amount.") );
+
+ grid2->addMultiCellWidget(label2, 0, 0, 0, 1);
+ grid2->addMultiCellWidget(m_radiusInput2, 1, 1, 0, 1);
+ grid2->addMultiCellWidget(label3, 2, 2, 0, 1);
+ grid2->addMultiCellWidget(m_amountInput, 3, 3, 0, 1);
+ grid2->addMultiCellWidget(label4, 4, 4, 0, 1);
+ grid2->addMultiCellWidget(m_thresholdInput, 5, 5, 0, 1);
+ grid2->setRowStretch(6, 10);
+ m_stack->addWidget(unsharpMaskSettings, UnsharpMask);
+
+ // -------------------------------------------------------------
+
+ TQWidget *refocusSettings = new TQWidget(m_stack);
+ TQGridLayout* grid3 = new TQGridLayout(refocusSettings, 10, 1, 0, spacingHint());
+
+ TQLabel *label5 = new TQLabel(i18n("Circular sharpness:"), refocusSettings);
+ m_radius = new KDoubleNumInput(refocusSettings);
+ m_radius->setPrecision(2);
+ m_radius->setRange(0.0, 5.0, 0.01, true);
+ TQWhatsThis::add( m_radius, i18n("<p>This is the radius of the circular convolution. It is the most important "
+ "parameter for using this plugin. For most images the default value of 1.0 "
+ "should give good results. Select a higher value when your image is very blurred."));
+
+ TQLabel *label6 = new TQLabel(i18n("Correlation:"), refocusSettings);
+ m_correlation = new KDoubleNumInput(refocusSettings);
+ m_correlation->setPrecision(2);
+ m_correlation->setRange(0.0, 1.0, 0.01, true);
+ TQWhatsThis::add( m_correlation, i18n("<p>Increasing the correlation may help to reduce artifacts. The correlation can "
+ "range from 0-1. Useful values are 0.5 and values close to 1, e.g. 0.95 and 0.99. "
+ "Using a high value for the correlation will reduce the sharpening effect of the "
+ "plugin."));
+
+ TQLabel *label7 = new TQLabel(i18n("Noise filter:"), refocusSettings);
+ m_noise = new KDoubleNumInput(refocusSettings);
+ m_noise->setPrecision(3);
+ m_noise->setRange(0.0, 1.0, 0.001, true);
+ TQWhatsThis::add( m_noise, i18n("<p>Increasing the noise filter parameter may help to reduce artifacts. The noise filter "
+ "can range from 0-1 but values higher than 0.1 are rarely helpful. When the noise filter "
+ "value is too low, e.g. 0.0 the image quality will be very poor. A useful value is 0.01. "
+ "Using a high value for the noise filter will reduce the sharpening "
+ "effect of the plugin."));
+
+ TQLabel *label8 = new TQLabel(i18n("Gaussian sharpness:"), refocusSettings);
+ m_gauss = new KDoubleNumInput(refocusSettings);
+ m_gauss->setPrecision(2);
+ m_gauss->setRange(0.0, 1.0, 0.01, true);
+ TQWhatsThis::add( m_gauss, i18n("<p>This is the sharpness for the gaussian convolution. Use this parameter when your "
+ "blurring is of a Gaussian type. In most cases you should set this parameter to 0, because "
+ "it causes nasty artifacts. When you use non-zero values, you will probably have to "
+ "increase the correlation and/or noise filter parameters too."));
+
+ TQLabel *label9 = new TQLabel(i18n("Matrix size:"), refocusSettings);
+ m_matrixSize = new KIntNumInput(refocusSettings);
+ m_matrixSize->setRange(0, MAX_MATRIX_SIZE, 1, true);
+ TQWhatsThis::add( m_matrixSize, i18n("<p>This parameter determines the size of the transformation matrix. "
+ "Increasing the matrix width may give better results, especially when you have "
+ "chosen large values for circular or gaussian sharpness."));
+
+ grid3->addMultiCellWidget(label5, 0, 0, 0, 1);
+ grid3->addMultiCellWidget(m_radius, 1, 1, 0, 1);
+ grid3->addMultiCellWidget(label6, 2, 2, 0, 1);
+ grid3->addMultiCellWidget(m_correlation, 3, 3, 0, 1);
+ grid3->addMultiCellWidget(label7, 4, 4, 0, 1);
+ grid3->addMultiCellWidget(m_noise, 5, 5, 0, 1);
+ grid3->addMultiCellWidget(label8, 6, 6, 0, 1);
+ grid3->addMultiCellWidget(m_gauss, 7, 7, 0, 1);
+ grid3->addMultiCellWidget(label9, 8, 8, 0, 1);
+ grid3->addMultiCellWidget(m_matrixSize, 9, 9, 0, 1);
+ grid3->setRowStretch(10, 10);
+ m_stack->addWidget(refocusSettings, Refocus);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_sharpMethod, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotSharpMethodActived(int)));
+
+ // -------------------------------------------------------------
+
+ // Image creation with dummy borders (mosaic mode) used by Refocus method. It needs to do
+ // it before to apply deconvolution filter on original image border pixels including
+ // on matrix size area. This way limit artifacts on image border.
+
+ Digikam::ImageIface iface(0, 0);
+
+ uchar* data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sb = iface.originalSixteenBit();
+ bool a = iface.originalHasAlpha();
+
+ m_img = Digikam::DImg( w + 4*MAX_MATRIX_SIZE, h + 4*MAX_MATRIX_SIZE, sb, a);
+
+ Digikam::DImg tmp;
+ Digikam::DImg org(w, h, sb, a, data);
+
+ // Copy original.
+ m_img.bitBltImage(&org, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+
+ // Create dummy top border
+ tmp = org.copy(0, 0, w, 2*MAX_MATRIX_SIZE);
+ tmp.flip(Digikam::DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, 2*MAX_MATRIX_SIZE, 0);
+
+ // Create dummy bottom border
+ tmp = org.copy(0, h-2*MAX_MATRIX_SIZE, w, 2*MAX_MATRIX_SIZE);
+ tmp.flip(Digikam::DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE+h);
+
+ // Create dummy left border
+ tmp = org.copy(0, 0, 2*MAX_MATRIX_SIZE, h);
+ tmp.flip(Digikam::DImg::HORIZONTAL);
+ m_img.bitBltImage(&tmp, 0, 2*MAX_MATRIX_SIZE);
+
+ // Create dummy right border
+ tmp = org.copy(w-2*MAX_MATRIX_SIZE, 0, 2*MAX_MATRIX_SIZE, h);
+ tmp.flip(Digikam::DImg::HORIZONTAL);
+ m_img.bitBltImage(&tmp, w+2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+
+ // Create dummy top/left corner
+ tmp = org.copy(0, 0, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ tmp.flip(Digikam::DImg::HORIZONTAL);
+ tmp.flip(Digikam::DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, 0, 0);
+
+ // Create dummy top/right corner
+ tmp = org.copy(w-2*MAX_MATRIX_SIZE, 0, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ tmp.flip(Digikam::DImg::HORIZONTAL);
+ tmp.flip(Digikam::DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, w+2*MAX_MATRIX_SIZE, 0);
+
+ // Create dummy bottom/left corner
+ tmp = org.copy(0, h-2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ tmp.flip(Digikam::DImg::HORIZONTAL);
+ tmp.flip(Digikam::DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, 0, h+2*MAX_MATRIX_SIZE);
+
+ // Create dummy bottom/right corner
+ tmp = org.copy(w-2*MAX_MATRIX_SIZE, h-2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ tmp.flip(Digikam::DImg::HORIZONTAL);
+ tmp.flip(Digikam::DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, w+2*MAX_MATRIX_SIZE, h+2*MAX_MATRIX_SIZE);
+
+ delete [] data;
+}
+
+ImageEffect_Sharpen::~ImageEffect_Sharpen()
+{
+}
+
+void ImageEffect_Sharpen::renderingFinished(void)
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ m_radiusInput->setEnabled(true);
+ enableButton(User2, false);
+ enableButton(User3, false);
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ m_radiusInput2->setEnabled(true);
+ m_amountInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ enableButton(User2, false);
+ enableButton(User3, false);
+ break;
+ }
+
+ case Refocus:
+ {
+ m_matrixSize->setEnabled(true);
+ m_radius->setEnabled(true);
+ m_gauss->setEnabled(true);
+ m_correlation->setEnabled(true);
+ m_noise->setEnabled(true);
+ break;
+ }
+ }
+}
+
+void ImageEffect_Sharpen::slotSharpMethodActived(int w)
+{
+ m_stack->raiseWidget(w);
+ if (w == Refocus)
+ {
+ enableButton(User2, true);
+ enableButton(User3, true);
+ }
+ else
+ {
+ enableButton(User2, false);
+ enableButton(User3, false);
+ }
+}
+
+void ImageEffect_Sharpen::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("sharpen Tool Dialog");
+ m_radiusInput->blockSignals(true);
+ m_radiusInput2->blockSignals(true);
+ m_amountInput->blockSignals(true);
+ m_thresholdInput->blockSignals(true);
+ m_matrixSize->blockSignals(true);
+ m_radius->blockSignals(true);
+ m_gauss->blockSignals(true);
+ m_correlation->blockSignals(true);
+ m_noise->blockSignals(true);
+ m_sharpMethod->blockSignals(true);
+ m_radiusInput->setValue(config->readNumEntry("SimpleSharpRadiusAjustment", 0));
+ m_radiusInput2->setValue(config->readNumEntry("UnsharpMaskRadiusAjustment", 1));
+ m_amountInput->setValue(config->readDoubleNumEntry("UnsharpMaskAmountAjustment", 1.0));
+ m_thresholdInput->setValue(config->readDoubleNumEntry("UnsharpMaskThresholdAjustment", 0.05));
+ m_matrixSize->setValue(config->readNumEntry("RefocusMatrixSize", 5));
+ m_radius->setValue(config->readDoubleNumEntry("RefocusRadiusAjustment", 1.0));
+ m_gauss->setValue(config->readDoubleNumEntry("RefocusGaussAjustment", 0.0));
+ m_correlation->setValue(config->readDoubleNumEntry("RefocusCorrelationAjustment", 0.5));
+ m_noise->setValue(config->readDoubleNumEntry("RefocusNoiseAjustment", 0.03));
+ m_sharpMethod->setCurrentItem(config->readNumEntry("SharpenMethod", SimpleSharp));
+ m_radiusInput->blockSignals(false);
+ m_radiusInput2->blockSignals(false);
+ m_amountInput->blockSignals(false);
+ m_thresholdInput->blockSignals(false);
+ m_matrixSize->blockSignals(false);
+ m_radius->blockSignals(false);
+ m_gauss->blockSignals(false);
+ m_correlation->blockSignals(false);
+ m_noise->blockSignals(false);
+ m_sharpMethod->blockSignals(false);
+ slotSharpMethodActived(m_sharpMethod->currentItem());
+}
+
+void ImageEffect_Sharpen::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("sharpen Tool Dialog");
+ config->writeEntry("SimpleSharpRadiusAjustment", m_radiusInput->value());
+ config->writeEntry("UnsharpMaskRadiusAjustment", m_radiusInput2->value());
+ config->writeEntry("UnsharpMaskAmountAjustment", m_amountInput->value());
+ config->writeEntry("UnsharpMaskThresholdAjustment", m_thresholdInput->value());
+ config->writeEntry("RefocusMatrixSize", m_matrixSize->value());
+ config->writeEntry("RefocusRadiusAjustment", m_radius->value());
+ config->writeEntry("RefocusGaussAjustment", m_gauss->value());
+ config->writeEntry("RefocusCorrelationAjustment", m_correlation->value());
+ config->writeEntry("RefocusNoiseAjustment", m_noise->value());
+ config->writeEntry("SharpenMethod", m_sharpMethod->currentItem());
+ config->sync();
+}
+
+void ImageEffect_Sharpen::resetValues(void)
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ m_radiusInput->blockSignals(true);
+ m_radiusInput->setValue(0);
+ m_radiusInput->blockSignals(false);
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ m_radiusInput2->blockSignals(true);
+ m_amountInput->blockSignals(true);
+ m_thresholdInput->blockSignals(true);
+ m_radiusInput2->setValue(1);
+ m_amountInput->setValue(1.0);
+ m_thresholdInput->setValue(0.05);
+ m_radiusInput2->blockSignals(false);
+ m_amountInput->blockSignals(false);
+ m_thresholdInput->blockSignals(false);
+ break;
+ }
+
+ case Refocus:
+ {
+ m_matrixSize->blockSignals(true);
+ m_radius->blockSignals(true);
+ m_gauss->blockSignals(true);
+ m_correlation->blockSignals(true);
+ m_noise->blockSignals(true);
+ m_matrixSize->setValue(5);
+ m_radius->setValue(1.0);
+ m_gauss->setValue(0.0);
+ m_correlation->setValue(0.5);
+ m_noise->setValue(0.03);
+ m_matrixSize->blockSignals(false);
+ m_radius->blockSignals(false);
+ m_gauss->blockSignals(false);
+ m_correlation->blockSignals(false);
+ m_noise->blockSignals(false);
+ break;
+ }
+ }
+}
+
+void ImageEffect_Sharpen::prepareEffect()
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ m_radiusInput->setEnabled(false);
+
+ Digikam::DImg img = m_imagePreviewWidget->getOriginalRegionImage();
+
+ double radius = m_radiusInput->value()/10.0;
+ double sigma;
+
+ if (radius < 1.0) sigma = radius;
+ else sigma = sqrt(radius);
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>
+ (new Digikam::DImgSharpen(&img, this, radius, sigma ));
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ m_radiusInput2->setEnabled(false);
+ m_amountInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+
+ Digikam::DImg img = m_imagePreviewWidget->getOriginalRegionImage();
+
+ int r = m_radiusInput2->value();
+ double a = m_amountInput->value();
+ double th = m_thresholdInput->value();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>
+ (new DigikamImagesPluginCore::UnsharpMask(&img, this, r, a, th));
+ break;
+ }
+
+ case Refocus:
+ {
+ m_matrixSize->setEnabled(false);
+ m_radius->setEnabled(false);
+ m_gauss->setEnabled(false);
+ m_correlation->setEnabled(false);
+ m_noise->setEnabled(false);
+
+ int ms = m_matrixSize->value();
+ double r = m_radius->value();
+ double g = m_gauss->value();
+ double c = m_correlation->value();
+ double n = m_noise->value();
+
+ TQRect area = m_imagePreviewWidget->getOriginalImageRegionToRender();
+ TQRect tmpRect;
+ tmpRect.setLeft(area.left()-2*ms);
+ tmpRect.setRight(area.right()+2*ms);
+ tmpRect.setTop(area.top()-2*ms);
+ tmpRect.setBottom(area.bottom()+2*ms);
+ tmpRect.moveBy(2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ Digikam::DImg imTemp = m_img.copy(tmpRect);
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>
+ (new DigikamImagesPluginCore::Refocus(&imTemp, this, ms, r, g, c, n));
+ break;
+ }
+ }
+}
+
+void ImageEffect_Sharpen::prepareFinal()
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ m_radiusInput->setEnabled(false);
+
+ double radius = m_radiusInput->value()/10.0;
+ double sigma;
+
+ if (radius < 1.0) sigma = radius;
+ else sigma = sqrt(radius);
+
+ Digikam::ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sixteenBit = iface.originalSixteenBit();
+ bool hasAlpha = iface.originalHasAlpha();
+ Digikam::DImg orgImage = Digikam::DImg(w, h, sixteenBit, hasAlpha ,data);
+ delete [] data;
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>
+ (new Digikam::DImgSharpen(&orgImage, this, radius, sigma ));
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ m_radiusInput2->setEnabled(false);
+ m_amountInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+
+ int r = m_radiusInput2->value();
+ double a = m_amountInput->value();
+ double th = m_thresholdInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sixteenBit = iface.originalSixteenBit();
+ bool hasAlpha = iface.originalHasAlpha();
+ Digikam::DImg orgImage = Digikam::DImg(w, h, sixteenBit, hasAlpha ,data);
+ delete [] data;
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>
+ (new DigikamImagesPluginCore::UnsharpMask(&orgImage, this, r, a, th));
+ break;
+ }
+
+ case Refocus:
+ {
+
+ m_matrixSize->setEnabled(false);
+ m_radius->setEnabled(false);
+ m_gauss->setEnabled(false);
+ m_correlation->setEnabled(false);
+ m_noise->setEnabled(false);
+
+ int ms = m_matrixSize->value();
+ double r = m_radius->value();
+ double g = m_gauss->value();
+ double c = m_correlation->value();
+ double n = m_noise->value();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>
+ (new DigikamImagesPluginCore::Refocus(&m_img, this, ms, r, g, c, n));
+ break;
+ }
+ }
+}
+
+void ImageEffect_Sharpen::putPreviewData(void)
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ case UnsharpMask:
+ {
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage();
+ m_imagePreviewWidget->setPreviewImage(imDest);
+ break;
+ }
+
+ case Refocus:
+ {
+ int ms = m_matrixSize->value();
+ TQRect area = m_imagePreviewWidget->getOriginalImageRegionToRender();
+
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage()
+ .copy(2*ms, 2*ms, area.width(), area.height());
+ m_imagePreviewWidget->setPreviewImage(imDest);
+ break;
+ }
+ }
+}
+
+void ImageEffect_Sharpen::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage();
+
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ iface.putOriginalImage(i18n("Sharpen"), imDest.bits());
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ iface.putOriginalImage(i18n("Unsharp Mask"), imDest.bits());
+ break;
+ }
+
+ case Refocus:
+ {
+ TQRect area = m_imagePreviewWidget->getOriginalImageRegionToRender();
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Refocus"), m_threadedFilter->getTargetImage()
+ .copy(2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE,
+ iface.originalWidth(),
+ iface.originalHeight())
+ .bits());
+ break;
+ }
+ }
+}
+
+void ImageEffect_Sharpen::slotUser3()
+{
+ KURL loadRestorationFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Refocus Settings File to Load")) );
+ if ( loadRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(loadRestorationFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+ if ( stream.readLine() != "# Photograph Refocus Configuration File" )
+ {
+ KMessageBox::error(this,
+ i18n("\"%1\" is not a Photograph Refocus settings text file.")
+ .arg(loadRestorationFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+ m_matrixSize->setValue( stream.readLine().toInt() );
+ m_radius->setValue( stream.readLine().toDouble() );
+ m_gauss->setValue( stream.readLine().toDouble() );
+ m_correlation->setValue( stream.readLine().toDouble() );
+ m_noise->setValue( stream.readLine().toDouble() );
+ blockSignals(false);
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot load settings from the Photograph Refocus text file."));
+
+ file.close();
+}
+
+void ImageEffect_Sharpen::slotUser2()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Refocus Settings File to Save")) );
+ if ( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# Photograph Refocus Configuration File\n";
+ stream << m_matrixSize->value() << "\n";
+ stream << m_radius->value() << "\n";
+ stream << m_gauss->value() << "\n";
+ stream << m_correlation->value() << "\n";
+ stream << m_noise->value() << "\n";
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot save settings to the Photograph Refocus text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/imageeffect_sharpen.h b/src/imageplugins/coreplugin/sharpnesseditor/imageeffect_sharpen.h
new file mode 100644
index 00000000..fa926383
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/imageeffect_sharpen.h
@@ -0,0 +1,102 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-09
+ * Description : a tool to sharp an image
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_SHARPEN_H
+#define IMAGEEFFECT_SHARPEN_H
+
+// Digikam include.
+
+#include "ctrlpaneldlg.h"
+
+class TQComboBox;
+class TQWidgetStack;
+
+class KIntNumInput;
+class KDoubleNumInput;
+
+namespace Digikam
+{
+ class DImg;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class ImageEffect_Sharpen : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Sharpen(TQWidget *parent);
+ ~ImageEffect_Sharpen();
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+ void readUserSettings();
+ void slotSharpMethodActived(int);
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ enum SharpingMethods
+ {
+ SimpleSharp=0,
+ UnsharpMask,
+ Refocus
+ };
+
+ TQWidgetStack *m_stack;
+
+ TQComboBox *m_sharpMethod;
+
+ KIntNumInput *m_matrixSize;
+ KIntNumInput *m_radiusInput;
+ KIntNumInput *m_radiusInput2;
+
+ KDoubleNumInput *m_radius;
+ KDoubleNumInput *m_gauss;
+ KDoubleNumInput *m_correlation;
+ KDoubleNumInput *m_noise;
+ KDoubleNumInput *m_amountInput;
+ KDoubleNumInput *m_thresholdInput;
+
+ Digikam::DImg m_img;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* IMAGEEFFECT_SHARPEN_H */
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/matrix.cpp b/src/imageplugins/coreplugin/sharpnesseditor/matrix.cpp
new file mode 100644
index 00000000..cfb8afe4
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/matrix.cpp
@@ -0,0 +1,663 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-04-29
+ * Description : refocus deconvolution matrix implementation.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original implementation from Refocus Gimp plug-in
+ * Copyright (C) 1999-2003 Ernst Lippe
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Uncomment this line to debug matrix computation.
+//#define RF_DEBUG 1
+
+// Square
+#define SQR(x) ((x) * (x))
+
+// C++ includes.
+
+#include <cmath>
+
+extern "C"
+{
+#include "f2c.h"
+#include "clapack.h"
+}
+
+// TQt includes.
+
+#include <tqglobal.h>
+#include <tqstring.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "matrix.h"
+
+namespace DigikamImagesPluginCore
+{
+
+Mat *RefocusMatrix::allocate_matrix (int nrows, int ncols)
+{
+ Mat *result = new Mat;
+ memset (result, 0, sizeof(result));
+
+ result->cols = ncols;
+ result->rows = nrows;
+ result->data = new double [nrows * ncols];
+ memset (result->data, 0, nrows * ncols * sizeof(double));
+
+ return (result);
+}
+
+void RefocusMatrix::finish_matrix (Mat * mat)
+{
+ delete [] mat->data;
+}
+
+void RefocusMatrix::finish_and_free_matrix (Mat * mat)
+{
+ delete [] mat->data;
+ delete mat;
+}
+
+double *RefocusMatrix::mat_eltptr (Mat * mat, const int r, const int c)
+{
+ Q_ASSERT ((r >= 0) && (r < mat->rows));
+ Q_ASSERT ((c >= 0) && (c < mat->rows));
+ return (&(mat->data[mat->rows * c + r]));
+}
+
+double RefocusMatrix::mat_elt (const Mat * mat, const int r, const int c)
+{
+ Q_ASSERT ((r >= 0) && (r < mat->rows));
+ Q_ASSERT ((c >= 0) && (c < mat->rows));
+ return (mat->data[mat->rows * c + r]);
+}
+
+void RefocusMatrix::init_c_mat (CMat * mat, const int radius)
+{
+ mat->radius = radius;
+ mat->row_stride = 2 * radius + 1;
+ mat->data = new double [SQR (mat->row_stride)];
+ memset (mat->data, 0, SQR (mat->row_stride) * sizeof(double));
+ mat->center = mat->data + mat->row_stride * mat->radius + mat->radius;
+}
+
+CMat *RefocusMatrix::allocate_c_mat (const int radius)
+{
+ CMat *result = new CMat;
+ memset(result, 0, sizeof(result));
+ init_c_mat (result, radius);
+ return (result);
+}
+
+void RefocusMatrix::finish_c_mat (CMat * mat)
+{
+ delete [] mat->data;
+ mat->data = NULL;
+}
+
+inline double *RefocusMatrix::c_mat_eltptr (CMat * mat, const int col, const int row)
+{
+ Q_ASSERT ((TQABS (row) <= mat->radius) && (TQABS (col) <= mat->radius));
+ return (mat->center + mat->row_stride * row + col);
+}
+
+inline double RefocusMatrix::c_mat_elt (const CMat * const mat, const int col, const int row)
+{
+ Q_ASSERT ((TQABS (row) <= mat->radius) && (TQABS (col) <= mat->radius));
+ return (mat->center[mat->row_stride * row + col]);
+}
+
+void RefocusMatrix::convolve_mat (CMat * result, const CMat * const mata, const CMat * const matb)
+{
+ int xr, yr, xa, ya;
+
+ for (yr = -result->radius; yr <= result->radius; yr++)
+ {
+ for (xr = -result->radius; xr <= result->radius; xr++)
+ {
+ const int ya_low = TQMAX (-mata->radius, yr - matb->radius);
+ const int ya_high = TQMIN (mata->radius, yr + matb->radius);
+ const int xa_low = TQMAX (-mata->radius, xr - matb->radius);
+ const int xa_high = TQMIN (mata->radius, xr + matb->radius);
+ double val = 0.0;
+
+ for (ya = ya_low; ya <= ya_high; ya++)
+ {
+ for (xa = xa_low; xa <= xa_high; xa++)
+ {
+ val += c_mat_elt (mata, xa, ya) *
+ c_mat_elt (matb, xr - xa, yr - ya);
+ }
+ }
+
+ *c_mat_eltptr (result, xr, yr) = val;
+ }
+ }
+}
+
+void RefocusMatrix::convolve_star_mat (CMat * result, const CMat * const mata, const CMat * const matb)
+{
+ int xr, yr, xa, ya;
+
+ for (yr = -result->radius; yr <= result->radius; yr++)
+ {
+ for (xr = -result->radius; xr <= result->radius; xr++)
+ {
+ const int ya_low = TQMAX (-mata->radius, -matb->radius - yr);
+ const int ya_high = TQMIN (mata->radius, matb->radius - yr);
+ const int xa_low = TQMAX (-mata->radius, -matb->radius - xr);
+ const int xa_high = TQMIN (mata->radius, matb->radius - xr);
+ double val = 0.0;
+
+ for (ya = ya_low; ya <= ya_high; ya++)
+ {
+ for (xa = xa_low; xa <= xa_high; xa++)
+ {
+ val += c_mat_elt (mata, xa, ya) *
+ c_mat_elt (matb, xr + xa, yr + ya);
+ }
+ }
+
+ *c_mat_eltptr (result, xr, yr) = val;
+ }
+ }
+}
+
+void RefocusMatrix::convolve_mat_fun (CMat * result, const CMat * const mata, double (f) (int, int))
+{
+ int xr, yr, xa, ya;
+
+ for (yr = -result->radius; yr <= result->radius; yr++)
+ {
+ for (xr = -result->radius; xr <= result->radius; xr++)
+ {
+ double val = 0.0;
+
+ for (ya = -mata->radius; ya <= mata->radius; ya++)
+ {
+ for (xa = -mata->radius; xa <= mata->radius; xa++)
+ {
+ val += c_mat_elt (mata, xa, ya) * f (xr - xa, yr - ya);
+ }
+ }
+
+ *c_mat_eltptr (result, xr, yr) = val;
+ }
+ }
+}
+
+int RefocusMatrix::as_idx (const int k, const int l, const int m)
+{
+ return ((k + m) * (2 * m + 1) + (l + m));
+}
+
+int RefocusMatrix::as_cidx (const int k, const int l)
+{
+ const int a = TQMAX (TQABS (k), TQABS (l));
+ const int b = TQMIN (TQABS (k), TQABS (l));
+ return ((a * (a + 1)) / 2 + b);
+}
+
+void RefocusMatrix::print_c_mat (const CMat * const mat)
+{
+ int x, y;
+
+ for (y = -mat->radius; y <= mat->radius; y++)
+ {
+ TQString output, num;
+
+ for (x = -mat->radius; x <= mat->radius; x++)
+ {
+ output.append( num.setNum( c_mat_elt (mat, x, y) ) );
+ }
+
+ DDebug() << output << endl;
+ }
+}
+
+void RefocusMatrix::print_matrix (Mat * matrix)
+{
+ int col_idx, row_idx;
+
+ for (row_idx = 0; row_idx < matrix->rows; row_idx++)
+ {
+ TQString output, num;
+
+ for (col_idx = 0; col_idx < matrix->cols; col_idx++)
+ {
+ output.append( num.setNum( mat_elt (matrix, row_idx, col_idx) ) );
+ }
+
+ DDebug() << output << endl;
+ }
+}
+
+Mat *RefocusMatrix::make_s_matrix (CMat * mat, int m, double noise_factor)
+{
+ const int mat_size = SQR (2 * m + 1);
+ Mat *result = allocate_matrix (mat_size, mat_size);
+ int yr, yc, xr, xc;
+
+ for (yr = -m; yr <= m; yr++)
+ {
+ for (xr = -m; xr <= m; xr++)
+ {
+ for (yc = -m; yc <= m; yc++)
+ {
+ for (xc = -m; xc <= m; xc++)
+ {
+ *mat_eltptr (result, as_idx (xr, yr, m),
+ as_idx (xc, yc, m)) =
+ c_mat_elt (mat, xr - xc, yr - yc);
+ if ((xr == xc) && (yr == yc))
+ {
+ *mat_eltptr (result, as_idx (xr, yr, m),
+ as_idx (xc, yc, m)) += noise_factor;
+ }
+ }
+ }
+ }
+ }
+
+ return (result);
+}
+
+Mat *RefocusMatrix::make_s_cmatrix (CMat * mat, int m, double noise_factor)
+{
+ const int mat_size = as_cidx (m + 1, 0);
+ Mat *result = allocate_matrix (mat_size, mat_size);
+ int yr, yc, xr, xc;
+
+ for (yr = 0; yr <= m; yr++)
+ {
+ for (xr = 0; xr <= yr; xr++)
+ {
+ for (yc = -m; yc <= m; yc++)
+ {
+ for (xc = -m; xc <= m; xc++)
+ {
+ *mat_eltptr (result, as_cidx (xr, yr), as_cidx (xc, yc)) +=
+ c_mat_elt (mat, xr - xc, yr - yc);
+ if ((xr == xc) && (yr == yc))
+ {
+ *mat_eltptr (result, as_cidx (xr, yr),
+ as_cidx (xc, yc)) += noise_factor;
+ }
+ }
+ }
+ }
+ }
+
+ return (result);
+}
+
+double RefocusMatrix::correlation (const int x, const int y, const double gamma, const double musq)
+{
+ return (musq + pow (gamma, sqrt (SQR (x) + SQR (y))));
+}
+
+Mat *RefocusMatrix::copy_vec (const CMat * const mat, const int m)
+{
+ Mat *result = allocate_matrix (SQR (2 * m + 1), 1);
+ int x, y, index = 0;
+
+ for (y = -m; y <= m; y++)
+ {
+ for (x = -m; x <= m; x++)
+ {
+ *mat_eltptr (result, index, 0) = c_mat_elt (mat, x, y);
+ index++;
+ }
+ }
+
+ Q_ASSERT (index == SQR (2 * m + 1));
+ return (result);
+}
+
+Mat *RefocusMatrix::copy_cvec (const CMat * const mat, const int m)
+{
+ Mat *result = allocate_matrix (as_cidx (m + 1, 0), 1);
+ int x, y, index = 0;
+
+ for (y = 0; y <= m; y++)
+ {
+ for (x = 0; x <= y; x++)
+ {
+ *mat_eltptr (result, index, 0) = c_mat_elt (mat, x, y);
+ index++;
+ }
+ }
+
+ Q_ASSERT (index == as_cidx (m + 1, 0));
+ return (result);
+}
+
+CMat *RefocusMatrix::copy_cvec2mat (const Mat * const cvec, const int m)
+{
+ CMat *result = allocate_c_mat (m);
+ int x, y;
+
+ for (y = -m; y <= m; y++)
+ {
+ for (x = -m; x <= m; x++)
+ {
+ *c_mat_eltptr (result, x, y) = mat_elt (cvec, as_cidx (x, y), 0);
+ }
+ }
+
+ return (result);
+}
+
+CMat *RefocusMatrix::copy_vec2mat (const Mat * const cvec, const int m)
+{
+ CMat *result = allocate_c_mat (m);
+ int x, y;
+
+ for (y = -m; y <= m; y++)
+ {
+ for (x = -m; x <= m; x++)
+ {
+ *c_mat_eltptr (result, x, y) = mat_elt (cvec, as_idx (x, y, m), 0);
+ }
+ }
+
+ return (result);
+}
+
+CMat *RefocusMatrix::compute_g (const CMat * const convolution, const int m, const double gamma,
+ const double noise_factor, const double musq, const bool symmetric)
+{
+ CMat h_conv_ruv, a, corr;
+ CMat *result;
+ Mat *b;
+ Mat *s;
+ int status;
+
+ init_c_mat (&h_conv_ruv, 3 * m);
+ fill_matrix2 (&corr, 4 * m, correlation, gamma, musq);
+ convolve_mat (&h_conv_ruv, convolution, &corr);
+ init_c_mat (&a, 2 * m);
+ convolve_star_mat (&a, convolution, &h_conv_ruv);
+
+ if (symmetric)
+ {
+ s = make_s_cmatrix (&a, m, noise_factor);
+ b = copy_cvec (&h_conv_ruv, m);
+ }
+ else
+ {
+ s = make_s_matrix (&a, m, noise_factor);
+ b = copy_vec (&h_conv_ruv, m);
+ }
+
+#ifdef RF_DEBUG
+ DDebug() << "Convolution:" << endl;
+ print_c_mat (convolution);
+ DDebug() << "h_conv_ruv:" << endl;
+ print_c_mat (&h_conv_ruv);
+ DDebug() << "Value of s:" << endl;
+ print_matrix (s);
+#endif
+
+ Q_ASSERT (s->cols == s->rows);
+ Q_ASSERT (s->rows == b->rows);
+ status = dgesv (s->rows, 1, s->data, s->rows, b->data, b->rows);
+
+ if (symmetric)
+ {
+ result = copy_cvec2mat (b, m);
+ }
+ else
+ {
+ result = copy_vec2mat (b, m);
+ }
+
+#ifdef RF_DEBUG
+ DDebug() << "Deconvolution:" << endl;
+ print_c_mat (result);
+#endif
+
+ finish_c_mat (&a);
+ finish_c_mat (&h_conv_ruv);
+ finish_c_mat (&corr);
+ finish_and_free_matrix (s);
+ finish_and_free_matrix (b);
+ return (result);
+}
+
+CMat *RefocusMatrix::compute_g_matrix (const CMat * const convolution, const int m,
+ const double gamma, const double noise_factor,
+ const double musq, const bool symmetric)
+{
+#ifdef RF_DEBUG
+ DDebug() << "matrix size: " << m << endl;
+ DDebug() << "correlation: " << gamma << endl;
+ DDebug() << "noise: " << noise_factor << endl;
+#endif
+
+ CMat *g = compute_g (convolution, m, gamma, noise_factor, musq, symmetric);
+ int r, c;
+ double sum = 0.0;
+
+ /* Determine sum of array */
+ for (r = -g->radius; r <= g->radius; r++)
+ {
+ for (c = -g->radius; c <= g->radius; c++)
+ {
+ sum += c_mat_elt (g, r, c);
+ }
+ }
+
+ for (r = -g->radius; r <= g->radius; r++)
+ {
+ for (c = -g->radius; c <= g->radius; c++)
+ {
+ *c_mat_eltptr (g, r, c) /= sum;
+ }
+ }
+
+ return (g);
+}
+
+void RefocusMatrix::fill_matrix (CMat * matrix, const int m,
+ double f (const int, const int, const double),
+ const double fun_arg)
+{
+ int x, y;
+ init_c_mat (matrix, m);
+
+ for (y = -m; y <= m; y++)
+ {
+ for (x = -m; x <= m; x++)
+ {
+ *c_mat_eltptr (matrix, x, y) = f (x, y, fun_arg);
+ }
+ }
+}
+
+void RefocusMatrix::fill_matrix2 (CMat * matrix, const int m,
+ double f (const int, const int, const double, const double),
+ const double fun_arg1, const double fun_arg2)
+{
+ int x, y;
+ init_c_mat (matrix, m);
+
+ for (y = -m; y <= m; y++)
+ {
+ for (x = -m; x <= m; x++)
+ {
+ *c_mat_eltptr (matrix, x, y) = f (x, y, fun_arg1, fun_arg2);
+ }
+ }
+}
+
+void RefocusMatrix::make_gaussian_convolution (const double gradius, CMat * convolution, const int m)
+{
+ int x, y;
+
+#ifdef RF_DEBUG
+ DDebug() << "gauss: " << gradius << endl;
+#endif
+
+ init_c_mat (convolution, m);
+
+ if (SQR (gradius) <= 1 / 3.40282347e38F)
+ {
+ for (y = -m; y <= m; y++)
+ {
+ for (x = -m; x <= m; x++)
+ {
+ *c_mat_eltptr (convolution, x, y) = 0;
+ }
+ }
+
+ *c_mat_eltptr (convolution, 0, 0) = 1;
+ }
+ else
+ {
+ const double alpha = log (2.0) / SQR (gradius);
+
+ for (y = -m; y <= m; y++)
+ {
+ for (x = -m; x <= m; x++)
+ {
+ *c_mat_eltptr (convolution, x, y) =
+ exp (-alpha * (SQR (x) + SQR (y)));
+ }
+ }
+ }
+}
+
+/** Return the integral of sqrt(radius^2 - z^2) for z = 0 to x. */
+
+double RefocusMatrix::circle_integral (const double x, const double radius)
+{
+ if (radius == 0)
+ {
+ // Perhaps some epsilon must be added here.
+ return (0);
+ }
+ else
+ {
+ const double sin = x / radius;
+ const double sq_diff = SQR (radius) - SQR (x);
+ // From a mathematical point of view the following is redundant.
+ // Numerically they are not equivalent!
+
+ if ((sq_diff < 0.0) || (sin < -1.0) || (sin > 1.0))
+ {
+ if (sin < 0)
+ {
+ return (-0.25 * SQR (radius) * M_PI);
+ }
+ else
+ {
+ return (0.25 * SQR (radius) * M_PI);
+ }
+ }
+ else
+ {
+ return (0.5 * x * sqrt (sq_diff) + 0.5 * SQR (radius) * asin (sin));
+ }
+ }
+}
+
+double RefocusMatrix::circle_intensity (const int x, const int y, const double radius)
+{
+ if (radius == 0)
+ {
+ return (((x == 0) && (y == 0)) ? 1 : 0);
+ }
+ else
+ {
+ double xlo = TQABS (x) - 0.5, xhi = TQABS (x) + 0.5,
+ ylo = TQABS (y) - 0.5, yhi = TQABS (y) + 0.5;
+ double symmetry_factor = 1, xc1, xc2;
+
+ if (xlo < 0)
+ {
+ xlo = 0;
+ symmetry_factor *= 2;
+ }
+
+ if (ylo < 0)
+ {
+ ylo = 0;
+ symmetry_factor *= 2;
+ }
+
+ if (SQR (xlo) + SQR (yhi) > SQR (radius))
+ {
+ xc1 = xlo;
+ }
+ else if (SQR (xhi) + SQR (yhi) > SQR (radius))
+ {
+ xc1 = sqrt (SQR (radius) - SQR (yhi));
+ }
+ else
+ {
+ xc1 = xhi;
+ }
+
+ if (SQR (xlo) + SQR (ylo) > SQR (radius))
+ {
+ xc2 = xlo;
+ }
+ else if (SQR (xhi) + SQR (ylo) > SQR (radius))
+ {
+ xc2 = sqrt (SQR (radius) - SQR (ylo));
+ }
+ else
+ {
+ xc2 = xhi;
+ }
+
+ return (((yhi - ylo) * (xc1 - xlo) +
+ circle_integral (xc2, radius) - circle_integral (xc1, radius) -
+ (xc2 - xc1) * ylo) * symmetry_factor / (M_PI * SQR (radius)));
+ }
+}
+
+void RefocusMatrix::make_circle_convolution (const double radius, CMat * convolution, const int m)
+{
+#ifdef RF_DEBUG
+ DDebug() << "radius: " << radius << endl;
+#endif
+
+ fill_matrix (convolution, m, circle_intensity, radius);
+}
+
+int RefocusMatrix::dgesv (const int N, const int NRHS, double *A, const int lda, double *B, const int ldb)
+{
+ int result = 0;
+ integer i_N = N, i_NHRS = NRHS, i_lda = lda, i_ldb = ldb, info;
+ integer *ipiv = new integer[N];
+
+ // Clapack call.
+ dgesv_ (&i_N, &i_NHRS, A, &i_lda, ipiv, B, &i_ldb, &info);
+
+ delete [] ipiv;
+ result = info;
+ return (result);
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/matrix.h b/src/imageplugins/coreplugin/sharpnesseditor/matrix.h
new file mode 100644
index 00000000..6b2f65cb
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/matrix.h
@@ -0,0 +1,129 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-04-29
+ * Description : refocus deconvolution matrix implementation.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef MATRIX_H_INCLUDED
+#define MATRIX_H_INCLUDED
+
+// C ++ includes.
+
+#include <cstdio>
+
+namespace DigikamImagesPluginCore
+{
+
+/**
+* CMat:
+* @radius: Radius of the matrix.
+*
+* Centered matrix. This is a square matrix where
+* the indices range from [-radius, radius].
+* The matrix contains (2 * radius + 1) ** 2 elements.
+*
+**/
+typedef struct
+{
+ int radius; // Radius of the matrix
+ int row_stride; // Size of one row = 2 * radius + 1
+ double *data; // Contents of matrix
+ double *center; // Points to element with index (0, 0)
+}
+CMat;
+
+/**
+* Mat:
+* @rows: Number of rows in the matrix.
+*
+* Normal matrix type. Indices range from
+* [0, rows -1 ] and [0, cols - 1].
+*
+**/
+typedef struct
+{
+ int rows; // Number of rows in the matrix
+ int cols; // Number of columns in the matrix
+ double *data; // Content of the matrix
+}
+Mat;
+
+class RefocusMatrix
+{
+
+public:
+
+ static void fill_matrix (CMat * matrix, const int m, double f (int, int, double), const double fun_arg);
+
+ static void fill_matrix2 (CMat * matrix, const int m,
+ double f (const int, const int, const double, const double),
+ const double fun_arg1, const double fun_arg2);
+
+ static void make_circle_convolution (const double radius, CMat *convolution, const int m);
+
+ static void make_gaussian_convolution (const double alpha, CMat *convolution, const int m);
+
+ static void convolve_star_mat (CMat *result, const CMat *const mata, const CMat* const matb);
+
+ static CMat *compute_g_matrix (const CMat * const convolution, const int m,
+ const double gamma, const double noise_factor,
+ const double musq, const bool symmetric);
+
+ static void finish_matrix (Mat * mat);
+ static void finish_and_free_matrix (Mat * mat);
+ static void init_c_mat (CMat * mat, const int radius);
+ static void finish_c_mat (CMat * mat);
+
+private:
+
+ // Debug methods.
+ static void print_c_mat (const CMat * const mat);
+ static void print_matrix (Mat * matrix);
+
+ static Mat *allocate_matrix (int nrows, int ncols);
+ static double *mat_eltptr (Mat * mat, const int r, const int c);
+ static double mat_elt (const Mat * mat, const int r, const int c);
+ static CMat *allocate_c_mat (const int radius);
+ static inline double *c_mat_eltptr (CMat * mat, const int col, const int row);
+ static inline double c_mat_elt (const CMat * const mat, const int col, const int row);
+ static void convolve_mat (CMat * result, const CMat * const mata, const CMat * const matb);
+ static void convolve_mat_fun (CMat * result, const CMat * const mata, double (f) (int, int));
+ static int as_idx (const int k, const int l, const int m);
+ static int as_cidx (const int k, const int l);
+ static Mat *make_s_matrix (CMat * mat, int m, double noise_factor);
+ static Mat *make_s_cmatrix (CMat * mat, int m, double noise_factor);
+ static double correlation (const int x, const int y, const double gamma, const double musq);
+ static Mat *copy_vec (const CMat * const mat, const int m);
+ static Mat *copy_cvec (const CMat * const mat, const int m);
+ static CMat *copy_cvec2mat (const Mat * const cvec, const int m);
+ static CMat *copy_vec2mat (const Mat * const cvec, const int m);
+ static CMat *compute_g (const CMat * const convolution, const int m, const double gamma,
+ const double noise_factor, const double musq, const bool symmetric);
+ static double circle_integral (const double x, const double radius);
+ static double circle_intensity (const int x, const int y, const double radius);
+
+ // CLapack interface.
+ static int dgesv (const int N, const int NRHS, double *A, const int lda, double *B, const int ldb);
+
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* MATRIX_H_INCLUDED */
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/refocus.cpp b/src/imageplugins/coreplugin/sharpnesseditor/refocus.cpp
new file mode 100644
index 00000000..7e99d663
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/refocus.cpp
@@ -0,0 +1,199 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Refocus threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dcolor.h"
+#include "dimgimagefilters.h"
+#include "matrix.h"
+#include "refocus.h"
+
+namespace DigikamImagesPluginCore
+{
+
+Refocus::Refocus(Digikam::DImg *orgImage, TQObject *parent, int matrixSize, double radius,
+ double gauss, double correlation, double noise)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "Refocus")
+{
+ m_matrixSize = matrixSize;
+ m_radius = radius;
+ m_gauss = gauss;
+ m_correlation = correlation;
+ m_noise = noise;
+ initFilter();
+}
+
+void Refocus::filterImage(void)
+{
+ refocusImage(m_orgImage.bits(), m_orgImage.width(), m_orgImage.height(),
+ m_orgImage.sixteenBit(), m_matrixSize, m_radius, m_gauss,
+ m_correlation, m_noise);
+}
+
+void Refocus::refocusImage(uchar* data, int width, int height, bool sixteenBit,
+ int matrixSize, double radius, double gauss,
+ double correlation, double noise)
+{
+ CMat *matrix=0;
+
+ // Compute matrix
+ DDebug() << "Refocus::Compute matrix..." << endl;
+
+ CMat circle, gaussian, convolution;
+
+ RefocusMatrix::make_gaussian_convolution (gauss, &gaussian, matrixSize);
+ RefocusMatrix::make_circle_convolution (radius, &circle, matrixSize);
+ RefocusMatrix::init_c_mat (&convolution, matrixSize);
+ RefocusMatrix::convolve_star_mat (&convolution, &gaussian, &circle);
+
+ matrix = RefocusMatrix::compute_g_matrix (&convolution, matrixSize, correlation, noise, 0.0, true);
+
+ RefocusMatrix::finish_c_mat (&convolution);
+ RefocusMatrix::finish_c_mat (&gaussian);
+ RefocusMatrix::finish_c_mat (&circle);
+
+ // Apply deconvolution kernel to image.
+ DDebug() << "Refocus::Apply Matrix to image..." << endl;
+ convolveImage(data, m_destImage.bits(), width, height, sixteenBit,
+ matrix->data, 2 * matrixSize + 1);
+
+ // Clean up memory
+ delete matrix;
+}
+
+void Refocus::convolveImage(uchar *orgData, uchar *destData, int width, int height,
+ bool sixteenBit, const double *const matrix, int mat_size)
+{
+ int progress;
+ unsigned short *orgData16 = (unsigned short *)orgData;
+ unsigned short *destData16 = (unsigned short *)destData;
+
+ double valRed, valGreen, valBlue;
+ int x1, y1, x2, y2, index1, index2;
+
+ const int imageSize = width*height;
+ const int mat_offset = mat_size / 2;
+
+ for (y1 = 0; !m_cancel && (y1 < height); y1++)
+ {
+ for (x1 = 0; !m_cancel && (x1 < width); x1++)
+ {
+ valRed = valGreen = valBlue = 0.0;
+
+ if (!sixteenBit) // 8 bits image.
+ {
+ uchar red, green, blue;
+ uchar *ptr;
+
+ for (y2 = 0; !m_cancel && (y2 < mat_size); y2++)
+ {
+ for (x2 = 0; !m_cancel && (x2 < mat_size); x2++)
+ {
+ index1 = width * (y1 + y2 - mat_offset) +
+ x1 + x2 - mat_offset;
+
+ if ( index1 >= 0 && index1 < imageSize )
+ {
+ ptr = &orgData[index1*4];
+ blue = ptr[0];
+ green = ptr[1];
+ red = ptr[2];
+ const double matrixValue = matrix[y2 * mat_size + x2];
+ valRed += matrixValue * red;
+ valGreen += matrixValue * green;
+ valBlue += matrixValue * blue;
+ }
+ }
+ }
+
+ index2 = y1 * width + x1;
+
+ if (index2 >= 0 && index2 < imageSize)
+ {
+ // To get Alpha channel value from original (unchanged)
+ memcpy (&destData[index2*4], &orgData[index2*4], 4);
+ ptr = &destData[index2*4];
+
+ // Overwrite RGB values to destination.
+ ptr[0] = (uchar) CLAMP (valBlue, 0, 255);
+ ptr[1] = (uchar) CLAMP (valGreen, 0, 255);
+ ptr[2] = (uchar) CLAMP (valRed, 0, 255);
+ }
+ }
+ else // 16 bits image.
+ {
+ unsigned short red, green, blue;
+ unsigned short *ptr;
+
+ for (y2 = 0; !m_cancel && (y2 < mat_size); y2++)
+ {
+ for (x2 = 0; !m_cancel && (x2 < mat_size); x2++)
+ {
+ index1 = width * (y1 + y2 - mat_offset) +
+ x1 + x2 - mat_offset;
+
+ if ( index1 >= 0 && index1 < imageSize )
+ {
+ ptr = &orgData16[index1*4];
+ blue = ptr[0];
+ green = ptr[1];
+ red = ptr[2];
+ const double matrixValue = matrix[y2 * mat_size + x2];
+ valRed += matrixValue * red;
+ valGreen += matrixValue * green;
+ valBlue += matrixValue * blue;
+ }
+ }
+ }
+
+ index2 = y1 * width + x1;
+
+ if (index2 >= 0 && index2 < imageSize)
+ {
+ // To get Alpha channel value from original (unchanged)
+ memcpy (&destData16[index2*4], &orgData16[index2*4], 8);
+ ptr = &destData16[index2*4];
+
+ // Overwrite RGB values to destination.
+ ptr[0] = (unsigned short) CLAMP (valBlue, 0, 65535);
+ ptr[1] = (unsigned short) CLAMP (valGreen, 0, 65535);
+ ptr[2] = (unsigned short) CLAMP (valRed, 0, 65535);
+ }
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int)(((double)y1 * 100.0) / height);
+ if (progress%5 == 0)
+ postProgress( progress );
+ }
+}
+
+} // NameSpace DigikamImagesPluginCore
+
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/refocus.h b/src/imageplugins/coreplugin/sharpnesseditor/refocus.h
new file mode 100644
index 00000000..323b24b9
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/refocus.h
@@ -0,0 +1,67 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Refocus threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef REFOCUS_H
+#define REFOCUS_H
+
+// Local includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamImagesPluginCore
+{
+
+class Refocus : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ Refocus(Digikam::DImg *orgImage, TQObject *parent=0, int matrixSize=5, double radius=0.9,
+ double gauss=0.0, double correlation=0.5, double noise=0.01);
+
+ ~Refocus(){};
+
+private: // Refocus filter methods.
+
+ virtual void filterImage(void);
+
+ void refocusImage(uchar* data, int width, int height, bool sixteenBit,
+ int matrixSize, double radius, double gauss,
+ double correlation, double noise);
+
+ void convolveImage(uchar *orgData, uchar *destData, int width, int height,
+ bool sixteenBit, const double *const matrix, int mat_size);
+
+private: // Refocus filter data.
+
+ int m_matrixSize;
+
+ double m_radius;
+ double m_gauss;
+ double m_correlation;
+ double m_noise;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* REFOCUS_H */
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/sharpentool.cpp b/src/imageplugins/coreplugin/sharpnesseditor/sharpentool.cpp
new file mode 100644
index 00000000..aee5d841
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/sharpentool.cpp
@@ -0,0 +1,741 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-09
+ * Description : a tool to sharp an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#define MAX_MATRIX_SIZE 25
+
+// C++ includes.
+
+#include <cmath>
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqwidgetstack.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeapplication.h>
+#include <kseparator.h>
+#include <tdeconfig.h>
+#include <kurl.h>
+#include <kiconloader.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <tdemessagebox.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "dimgsharpen.h"
+#include "unsharp.h"
+#include "refocus.h"
+#include "sharpentool.h"
+#include "sharpentool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamImagesPluginCore
+{
+
+SharpenTool::SharpenTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("sharpen");
+ setToolName(i18n("Sharpen"));
+ setToolIcon(SmallIcon("sharpenimage"));
+ setToolHelp("blursharpentool.anchor");
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 3, 1);
+
+ TQLabel *label1 = new TQLabel(i18n("Method:"), m_gboxSettings->plainPage());
+
+ m_sharpMethod = new RComboBox(m_gboxSettings->plainPage());
+ m_sharpMethod->insertItem( i18n("Simple sharp") );
+ m_sharpMethod->insertItem( i18n("Unsharp mask") );
+ m_sharpMethod->insertItem( i18n("Refocus") );
+ m_sharpMethod->setDefaultItem(SimpleSharp);
+ TQWhatsThis::add( m_sharpMethod, i18n("<p>Select the sharpening method to apply to the image."));
+
+ m_stack = new TQWidgetStack(m_gboxSettings->plainPage());
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 0);
+ grid->addMultiCellWidget(m_sharpMethod, 0, 0, 1, 1);
+ grid->addMultiCellWidget(new KSeparator(m_gboxSettings->plainPage()), 1, 1, 0, 1);
+ grid->addMultiCellWidget(m_stack, 2, 2, 0, 1);
+ grid->setRowStretch(3, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ // -------------------------------------------------------------
+
+ TQWidget *simpleSharpSettings = new TQWidget(m_stack);
+ TQGridLayout* grid1 = new TQGridLayout( simpleSharpSettings, 2, 1);
+
+ TQLabel *label = new TQLabel(i18n("Sharpness:"), simpleSharpSettings);
+ m_radiusInput = new RIntNumInput(simpleSharpSettings);
+ m_radiusInput->setRange(0, 100, 1);
+ m_radiusInput->setDefaultValue(0);
+ TQWhatsThis::add( m_radiusInput, i18n("<p>A sharpness of 0 has no effect, "
+ "1 and above determine the sharpen matrix radius "
+ "that determines how much to sharpen the image."));
+
+ grid1->addMultiCellWidget(label, 0, 0, 0, 1);
+ grid1->addMultiCellWidget(m_radiusInput, 1, 1, 0, 1);
+ grid1->setRowStretch(2, 10);
+ grid1->setMargin(0);
+ grid1->setSpacing(0);
+
+ m_stack->addWidget(simpleSharpSettings, SimpleSharp);
+
+ // -------------------------------------------------------------
+
+ TQWidget *unsharpMaskSettings = new TQWidget(m_stack);
+ TQGridLayout* grid2 = new TQGridLayout( unsharpMaskSettings, 6, 1);
+
+ TQLabel *label2 = new TQLabel(i18n("Radius:"), unsharpMaskSettings);
+ m_radiusInput2 = new RIntNumInput(unsharpMaskSettings);
+ m_radiusInput2->setRange(1, 120, 1);
+ m_radiusInput2->setDefaultValue(1);
+ TQWhatsThis::add( m_radiusInput2, i18n("<p>Radius value is the gaussian blur matrix radius value "
+ "used to determines how much to blur the image.") );
+
+ TQLabel *label3 = new TQLabel(i18n("Amount:"), unsharpMaskSettings);
+ m_amountInput = new RDoubleNumInput(unsharpMaskSettings);
+ m_amountInput->setPrecision(1);
+ m_amountInput->setRange(0.0, 5.0, 0.1);
+ m_amountInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_amountInput, i18n("<p>The value of the difference between the "
+ "original and the blur image that is added back into the original.") );
+
+ TQLabel *label4 = new TQLabel(i18n("Threshold:"), unsharpMaskSettings);
+ m_thresholdInput = new RDoubleNumInput(unsharpMaskSettings);
+ m_thresholdInput->setPrecision(2);
+ m_thresholdInput->setRange(0.0, 1.0, 0.01);
+ m_thresholdInput->setDefaultValue(0.05);
+ TQWhatsThis::add( m_thresholdInput, i18n("<p>The threshold, as a fraction of the maximum "
+ "luminosity value, needed to apply the difference amount.") );
+
+ grid2->addMultiCellWidget(label2, 0, 0, 0, 1);
+ grid2->addMultiCellWidget(m_radiusInput2, 1, 1, 0, 1);
+ grid2->addMultiCellWidget(label3, 2, 2, 0, 1);
+ grid2->addMultiCellWidget(m_amountInput, 3, 3, 0, 1);
+ grid2->addMultiCellWidget(label4, 4, 4, 0, 1);
+ grid2->addMultiCellWidget(m_thresholdInput, 5, 5, 0, 1);
+ grid2->setRowStretch(6, 10);
+ grid2->setMargin(0);
+ grid2->setSpacing(0);
+
+ m_stack->addWidget(unsharpMaskSettings, UnsharpMask);
+
+ // -------------------------------------------------------------
+
+ TQWidget *refocusSettings = new TQWidget(m_stack);
+ TQGridLayout* grid3 = new TQGridLayout(refocusSettings, 10, 1);
+
+ TQLabel *label5 = new TQLabel(i18n("Circular sharpness:"), refocusSettings);
+ m_radius = new RDoubleNumInput(refocusSettings);
+ m_radius->setPrecision(2);
+ m_radius->setRange(0.0, 5.0, 0.01);
+ m_radius->setDefaultValue(1.0);
+ TQWhatsThis::add( m_radius, i18n("<p>This is the radius of the circular convolution. It is the most important "
+ "parameter for using this plugin. For most images the default value of 1.0 "
+ "should give good results. Select a higher value when your image is very blurred."));
+
+ TQLabel *label6 = new TQLabel(i18n("Correlation:"), refocusSettings);
+ m_correlation = new RDoubleNumInput(refocusSettings);
+ m_correlation->setPrecision(2);
+ m_correlation->setRange(0.0, 1.0, 0.01);
+ m_correlation->setDefaultValue(0.5);
+ TQWhatsThis::add( m_correlation, i18n("<p>Increasing the correlation may help to reduce artifacts. The correlation can "
+ "range from 0-1. Useful values are 0.5 and values close to 1, e.g. 0.95 and 0.99. "
+ "Using a high value for the correlation will reduce the sharpening effect of the "
+ "plugin."));
+
+ TQLabel *label7 = new TQLabel(i18n("Noise filter:"), refocusSettings);
+ m_noise = new RDoubleNumInput(refocusSettings);
+ m_noise->setPrecision(3);
+ m_noise->setRange(0.0, 1.0, 0.001);
+ m_noise->setDefaultValue(0.03);
+ TQWhatsThis::add( m_noise, i18n("<p>Increasing the noise filter parameter may help to reduce artifacts. The noise filter "
+ "can range from 0-1 but values higher than 0.1 are rarely helpful. When the noise filter "
+ "value is too low, e.g. 0.0 the image quality will be very poor. A useful value is 0.01. "
+ "Using a high value for the noise filter will reduce the sharpening "
+ "effect of the plugin."));
+
+ TQLabel *label8 = new TQLabel(i18n("Gaussian sharpness:"), refocusSettings);
+ m_gauss = new RDoubleNumInput(refocusSettings);
+ m_gauss->setPrecision(2);
+ m_gauss->setRange(0.0, 1.0, 0.01);
+ m_gauss->setDefaultValue(0.0);
+ TQWhatsThis::add( m_gauss, i18n("<p>This is the sharpness for the gaussian convolution. Use this parameter when your "
+ "blurring is of a Gaussian type. In most cases you should set this parameter to 0, because "
+ "it causes nasty artifacts. When you use non-zero values, you will probably have to "
+ "increase the correlation and/or noise filter parameters too."));
+
+ TQLabel *label9 = new TQLabel(i18n("Matrix size:"), refocusSettings);
+ m_matrixSize = new RIntNumInput(refocusSettings);
+ m_matrixSize->setRange(0, MAX_MATRIX_SIZE, 1);
+ m_matrixSize->setDefaultValue(5);
+ TQWhatsThis::add( m_matrixSize, i18n("<p>This parameter determines the size of the transformation matrix. "
+ "Increasing the matrix width may give better results, especially when you have "
+ "chosen large values for circular or gaussian sharpness."));
+
+ grid3->addMultiCellWidget(label5, 0, 0, 0, 1);
+ grid3->addMultiCellWidget(m_radius, 1, 1, 0, 1);
+ grid3->addMultiCellWidget(label6, 2, 2, 0, 1);
+ grid3->addMultiCellWidget(m_correlation, 3, 3, 0, 1);
+ grid3->addMultiCellWidget(label7, 4, 4, 0, 1);
+ grid3->addMultiCellWidget(m_noise, 5, 5, 0, 1);
+ grid3->addMultiCellWidget(label8, 6, 6, 0, 1);
+ grid3->addMultiCellWidget(m_gauss, 7, 7, 0, 1);
+ grid3->addMultiCellWidget(label9, 8, 8, 0, 1);
+ grid3->addMultiCellWidget(m_matrixSize, 9, 9, 0, 1);
+ grid3->setRowStretch(10, 10);
+ grid3->setMargin(0);
+ grid3->setSpacing(0);
+
+ m_stack->addWidget(refocusSettings, Refocus);
+
+ setToolSettings(m_gboxSettings);
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "sharpen Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_sharpMethod, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotSharpMethodActived(int)));
+
+ // -------------------------------------------------------------
+
+ // Image creation with dummy borders (mosaic mode) used by Refocus method. It needs to do
+ // it before to apply deconvolution filter on original image border pixels including
+ // on matrix size area. This way limit artifacts on image border.
+
+ ImageIface iface(0, 0);
+
+ uchar* data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sb = iface.originalSixteenBit();
+ bool a = iface.originalHasAlpha();
+
+ m_img = DImg( w + 4*MAX_MATRIX_SIZE, h + 4*MAX_MATRIX_SIZE, sb, a);
+
+ DImg tmp;
+ DImg org(w, h, sb, a, data);
+
+ // Copy original.
+ m_img.bitBltImage(&org, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+
+ // Create dummy top border
+ tmp = org.copy(0, 0, w, 2*MAX_MATRIX_SIZE);
+ tmp.flip(DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, 2*MAX_MATRIX_SIZE, 0);
+
+ // Create dummy bottom border
+ tmp = org.copy(0, h-2*MAX_MATRIX_SIZE, w, 2*MAX_MATRIX_SIZE);
+ tmp.flip(DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE+h);
+
+ // Create dummy left border
+ tmp = org.copy(0, 0, 2*MAX_MATRIX_SIZE, h);
+ tmp.flip(DImg::HORIZONTAL);
+ m_img.bitBltImage(&tmp, 0, 2*MAX_MATRIX_SIZE);
+
+ // Create dummy right border
+ tmp = org.copy(w-2*MAX_MATRIX_SIZE, 0, 2*MAX_MATRIX_SIZE, h);
+ tmp.flip(DImg::HORIZONTAL);
+ m_img.bitBltImage(&tmp, w+2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+
+ // Create dummy top/left corner
+ tmp = org.copy(0, 0, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ tmp.flip(DImg::HORIZONTAL);
+ tmp.flip(DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, 0, 0);
+
+ // Create dummy top/right corner
+ tmp = org.copy(w-2*MAX_MATRIX_SIZE, 0, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ tmp.flip(DImg::HORIZONTAL);
+ tmp.flip(DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, w+2*MAX_MATRIX_SIZE, 0);
+
+ // Create dummy bottom/left corner
+ tmp = org.copy(0, h-2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ tmp.flip(DImg::HORIZONTAL);
+ tmp.flip(DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, 0, h+2*MAX_MATRIX_SIZE);
+
+ // Create dummy bottom/right corner
+ tmp = org.copy(w-2*MAX_MATRIX_SIZE, h-2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ tmp.flip(DImg::HORIZONTAL);
+ tmp.flip(DImg::VERTICAL);
+ m_img.bitBltImage(&tmp, w+2*MAX_MATRIX_SIZE, h+2*MAX_MATRIX_SIZE);
+
+ delete [] data;
+}
+
+SharpenTool::~SharpenTool()
+{
+}
+
+void SharpenTool::renderingFinished()
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ m_radiusInput->setEnabled(true);
+ m_gboxSettings->enableButton(EditorToolSettings::Load, false);
+ m_gboxSettings->enableButton(EditorToolSettings::SaveAs, false);
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ m_radiusInput2->setEnabled(true);
+ m_amountInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_gboxSettings->enableButton(EditorToolSettings::Load, false);
+ m_gboxSettings->enableButton(EditorToolSettings::SaveAs, false);
+ break;
+ }
+
+ case Refocus:
+ {
+ m_matrixSize->setEnabled(true);
+ m_radius->setEnabled(true);
+ m_gauss->setEnabled(true);
+ m_correlation->setEnabled(true);
+ m_noise->setEnabled(true);
+ break;
+ }
+ }
+}
+
+void SharpenTool::slotSharpMethodActived(int w)
+{
+ m_stack->raiseWidget(w);
+ if (w == Refocus)
+ {
+ m_gboxSettings->enableButton(EditorToolSettings::Load, true);
+ m_gboxSettings->enableButton(EditorToolSettings::SaveAs, true);
+ }
+ else
+ {
+ m_gboxSettings->enableButton(EditorToolSettings::Load, false);
+ m_gboxSettings->enableButton(EditorToolSettings::SaveAs, false);
+ }
+}
+
+void SharpenTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("sharpen Tool");
+ m_radiusInput->blockSignals(true);
+ m_radiusInput2->blockSignals(true);
+ m_amountInput->blockSignals(true);
+ m_thresholdInput->blockSignals(true);
+ m_matrixSize->blockSignals(true);
+ m_radius->blockSignals(true);
+ m_gauss->blockSignals(true);
+ m_correlation->blockSignals(true);
+ m_noise->blockSignals(true);
+ m_sharpMethod->blockSignals(true);
+
+ m_radiusInput->setValue(config->readNumEntry("SimpleSharpRadiusAjustment", m_radiusInput->defaultValue()));
+ m_radiusInput2->setValue(config->readNumEntry("UnsharpMaskRadiusAjustment", m_radiusInput2->defaultValue()));
+ m_amountInput->setValue(config->readDoubleNumEntry("UnsharpMaskAmountAjustment", m_amountInput->defaultValue()));
+ m_thresholdInput->setValue(config->readDoubleNumEntry("UnsharpMaskThresholdAjustment", m_thresholdInput->defaultValue()));
+ m_matrixSize->setValue(config->readNumEntry("RefocusMatrixSize", m_matrixSize->defaultValue()));
+ m_radius->setValue(config->readDoubleNumEntry("RefocusRadiusAjustment", m_radius->defaultValue()));
+ m_gauss->setValue(config->readDoubleNumEntry("RefocusGaussAjustment", m_gauss->defaultValue()));
+ m_correlation->setValue(config->readDoubleNumEntry("RefocusCorrelationAjustment", m_correlation->defaultValue()));
+ m_noise->setValue(config->readDoubleNumEntry("RefocusNoiseAjustment", m_noise->defaultValue()));
+ m_sharpMethod->setCurrentItem(config->readNumEntry("SharpenMethod", SimpleSharp));
+
+ m_radiusInput->blockSignals(false);
+ m_radiusInput2->blockSignals(false);
+ m_amountInput->blockSignals(false);
+ m_thresholdInput->blockSignals(false);
+ m_matrixSize->blockSignals(false);
+ m_radius->blockSignals(false);
+ m_gauss->blockSignals(false);
+ m_correlation->blockSignals(false);
+ m_noise->blockSignals(false);
+ m_sharpMethod->blockSignals(false);
+
+ slotSharpMethodActived(m_sharpMethod->currentItem());
+}
+
+void SharpenTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("sharpen Tool");
+ config->writeEntry("SimpleSharpRadiusAjustment", m_radiusInput->value());
+ config->writeEntry("UnsharpMaskRadiusAjustment", m_radiusInput2->value());
+ config->writeEntry("UnsharpMaskAmountAjustment", m_amountInput->value());
+ config->writeEntry("UnsharpMaskThresholdAjustment", m_thresholdInput->value());
+ config->writeEntry("RefocusMatrixSize", m_matrixSize->value());
+ config->writeEntry("RefocusRadiusAjustment", m_radius->value());
+ config->writeEntry("RefocusGaussAjustment", m_gauss->value());
+ config->writeEntry("RefocusCorrelationAjustment", m_correlation->value());
+ config->writeEntry("RefocusNoiseAjustment", m_noise->value());
+ config->writeEntry("SharpenMethod", m_sharpMethod->currentItem());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void SharpenTool::slotResetSettings()
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ m_radiusInput->blockSignals(true);
+ m_radiusInput->slotReset();
+ m_radiusInput->blockSignals(false);
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ m_radiusInput2->blockSignals(true);
+ m_amountInput->blockSignals(true);
+ m_thresholdInput->blockSignals(true);
+
+ m_radiusInput2->slotReset();
+ m_amountInput->slotReset();
+ m_thresholdInput->slotReset();
+
+ m_radiusInput2->blockSignals(false);
+ m_amountInput->blockSignals(false);
+ m_thresholdInput->blockSignals(false);
+ break;
+ }
+
+ case Refocus:
+ {
+ m_matrixSize->blockSignals(true);
+ m_radius->blockSignals(true);
+ m_gauss->blockSignals(true);
+ m_correlation->blockSignals(true);
+ m_noise->blockSignals(true);
+
+ m_matrixSize->slotReset();
+ m_radius->slotReset();
+ m_gauss->slotReset();
+ m_correlation->slotReset();
+ m_noise->slotReset();
+
+ m_matrixSize->blockSignals(false);
+ m_radius->blockSignals(false);
+ m_gauss->blockSignals(false);
+ m_correlation->blockSignals(false);
+ m_noise->blockSignals(false);
+ break;
+ }
+ }
+}
+
+void SharpenTool::prepareEffect()
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ m_radiusInput->setEnabled(false);
+
+ DImg img = m_previewWidget->getOriginalRegionImage();
+
+ double radius = m_radiusInput->value()/10.0;
+ double sigma;
+
+ if (radius < 1.0) sigma = radius;
+ else sigma = sqrt(radius);
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new DImgSharpen(&img, this, radius, sigma )));
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ m_radiusInput2->setEnabled(false);
+ m_amountInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+
+ DImg img = m_previewWidget->getOriginalRegionImage();
+
+ int r = m_radiusInput2->value();
+ double a = m_amountInput->value();
+ double th = m_thresholdInput->value();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new DigikamImagesPluginCore::UnsharpMask(&img, this, r, a, th)));
+ break;
+ }
+
+ case Refocus:
+ {
+ m_matrixSize->setEnabled(false);
+ m_radius->setEnabled(false);
+ m_gauss->setEnabled(false);
+ m_correlation->setEnabled(false);
+ m_noise->setEnabled(false);
+
+ int ms = m_matrixSize->value();
+ double r = m_radius->value();
+ double g = m_gauss->value();
+ double c = m_correlation->value();
+ double n = m_noise->value();
+
+ TQRect area = m_previewWidget->getOriginalImageRegionToRender();
+ TQRect tmpRect;
+ tmpRect.setLeft(area.left()-2*ms);
+ tmpRect.setRight(area.right()+2*ms);
+ tmpRect.setTop(area.top()-2*ms);
+ tmpRect.setBottom(area.bottom()+2*ms);
+ tmpRect.moveBy(2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE);
+ DImg imTemp = m_img.copy(tmpRect);
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new DigikamImagesPluginCore::Refocus(&imTemp, this, ms, r, g, c, n)));
+ break;
+ }
+ }
+}
+
+void SharpenTool::prepareFinal()
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ m_radiusInput->setEnabled(false);
+
+ double radius = m_radiusInput->value()/10.0;
+ double sigma;
+
+ if (radius < 1.0) sigma = radius;
+ else sigma = sqrt(radius);
+
+ ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sixteenBit = iface.originalSixteenBit();
+ bool hasAlpha = iface.originalHasAlpha();
+ DImg orgImage = DImg(w, h, sixteenBit, hasAlpha ,data);
+ delete [] data;
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new DImgSharpen(&orgImage, this, radius, sigma )));
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ m_radiusInput2->setEnabled(false);
+ m_amountInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+
+ int r = m_radiusInput2->value();
+ double a = m_amountInput->value();
+ double th = m_thresholdInput->value();
+
+ ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ int w = iface.originalWidth();
+ int h = iface.originalHeight();
+ bool sixteenBit = iface.originalSixteenBit();
+ bool hasAlpha = iface.originalHasAlpha();
+ DImg orgImage = DImg(w, h, sixteenBit, hasAlpha ,data);
+ delete [] data;
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new DigikamImagesPluginCore::UnsharpMask(&orgImage, this, r, a, th)));
+ break;
+ }
+
+ case Refocus:
+ {
+
+ m_matrixSize->setEnabled(false);
+ m_radius->setEnabled(false);
+ m_gauss->setEnabled(false);
+ m_correlation->setEnabled(false);
+ m_noise->setEnabled(false);
+
+ int ms = m_matrixSize->value();
+ double r = m_radius->value();
+ double g = m_gauss->value();
+ double c = m_correlation->value();
+ double n = m_noise->value();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new DigikamImagesPluginCore::Refocus(&m_img, this, ms, r, g, c, n)));
+ break;
+ }
+ }
+}
+
+void SharpenTool::putPreviewData()
+{
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ case UnsharpMask:
+ {
+ DImg imDest = filter()->getTargetImage();
+ m_previewWidget->setPreviewImage(imDest);
+ break;
+ }
+
+ case Refocus:
+ {
+ int ms = m_matrixSize->value();
+ TQRect area = m_previewWidget->getOriginalImageRegionToRender();
+
+ DImg imDest = filter()->getTargetImage()
+ .copy(2*ms, 2*ms, area.width(), area.height());
+ m_previewWidget->setPreviewImage(imDest);
+ break;
+ }
+ }
+}
+
+void SharpenTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ DImg imDest = filter()->getTargetImage();
+
+ switch (m_stack->id(m_stack->visibleWidget()))
+ {
+ case SimpleSharp:
+ {
+ iface.putOriginalImage(i18n("Sharpen"), imDest.bits());
+ break;
+ }
+
+ case UnsharpMask:
+ {
+ iface.putOriginalImage(i18n("Unsharp Mask"), imDest.bits());
+ break;
+ }
+
+ case Refocus:
+ {
+ TQRect area = m_previewWidget->getOriginalImageRegionToRender();
+ ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Refocus"), filter()->getTargetImage()
+ .copy(2*MAX_MATRIX_SIZE, 2*MAX_MATRIX_SIZE,
+ iface.originalWidth(),
+ iface.originalHeight())
+ .bits());
+ break;
+ }
+ }
+}
+
+void SharpenTool::slotLoadSettings()
+{
+ KURL loadRestorationFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Refocus Settings File to Load")) );
+ if ( loadRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(loadRestorationFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+ if ( stream.readLine() != "# Photograph Refocus Configuration File" )
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" is not a Photograph Refocus settings text file.")
+ .arg(loadRestorationFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+ m_matrixSize->setValue( stream.readLine().toInt() );
+ m_radius->setValue( stream.readLine().toDouble() );
+ m_gauss->setValue( stream.readLine().toDouble() );
+ m_correlation->setValue( stream.readLine().toDouble() );
+ m_noise->setValue( stream.readLine().toDouble() );
+ blockSignals(false);
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot load settings from the Photograph Refocus text file."));
+
+ file.close();
+}
+
+void SharpenTool::slotSaveAsSettings()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Refocus Settings File to Save")) );
+ if ( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# Photograph Refocus Configuration File\n";
+ stream << m_matrixSize->value() << "\n";
+ stream << m_radius->value() << "\n";
+ stream << m_gauss->value() << "\n";
+ stream << m_correlation->value() << "\n";
+ stream << m_noise->value() << "\n";
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot save settings to the Photograph Refocus text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/sharpentool.h b/src/imageplugins/coreplugin/sharpnesseditor/sharpentool.h
new file mode 100644
index 00000000..8dbca1c5
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/sharpentool.h
@@ -0,0 +1,111 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-07-09
+ * Description : a tool to sharp an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SHARPENTOOL_H
+#define SHARPENTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQWidgetStack;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RDoubleNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class DImg;
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamImagesPluginCore
+{
+
+class SharpenTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ SharpenTool(TQObject *parent);
+ ~SharpenTool();
+
+private slots:
+
+ void slotSaveAsSettings();
+ void slotLoadSettings();
+ void slotResetSettings();
+ void slotSharpMethodActived(int);
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ enum SharpingMethods
+ {
+ SimpleSharp=0,
+ UnsharpMask,
+ Refocus
+ };
+
+ TQWidgetStack *m_stack;
+
+ KDcrawIface::RComboBox *m_sharpMethod;
+
+ KDcrawIface::RIntNumInput *m_matrixSize;
+ KDcrawIface::RIntNumInput *m_radiusInput;
+ KDcrawIface::RIntNumInput *m_radiusInput2;
+
+ KDcrawIface::RDoubleNumInput *m_radius;
+ KDcrawIface::RDoubleNumInput *m_gauss;
+ KDcrawIface::RDoubleNumInput *m_correlation;
+ KDcrawIface::RDoubleNumInput *m_noise;
+ KDcrawIface::RDoubleNumInput *m_amountInput;
+ KDcrawIface::RDoubleNumInput *m_thresholdInput;
+
+ Digikam::DImg m_img;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* SHARPENTOOL_H */
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/unsharp.cpp b/src/imageplugins/coreplugin/sharpnesseditor/unsharp.cpp
new file mode 100644
index 00000000..fb1b9d21
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/unsharp.cpp
@@ -0,0 +1,127 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Unsharp Mask threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dcolor.h"
+#include "dimgimagefilters.h"
+#include "dimggaussianblur.h"
+#include "unsharp.h"
+
+namespace DigikamImagesPluginCore
+{
+
+UnsharpMask::UnsharpMask(Digikam::DImg *orgImage, TQObject *parent, int radius,
+ double amount, double threshold)
+ : DImgThreadedFilter(orgImage, parent, "UnsharpMask")
+{
+ m_radius = radius;
+ m_amount = amount;
+ m_threshold = threshold;
+ initFilter();
+}
+
+void UnsharpMask::filterImage(void)
+{
+ int progress;
+ int quantum;
+ double quantumThreshold;
+ double value;
+ Digikam::DColor p;
+ Digikam::DColor q;
+
+ if (m_orgImage.isNull())
+ {
+ DWarning() << k_funcinfo << "No image data available!" << endl;
+ return;
+ }
+
+ Digikam::DImgGaussianBlur(this, m_orgImage, m_destImage, 0, 10, (int)(m_radius));
+
+ quantum = m_destImage.sixteenBit() ? 65535 : 255;
+ quantumThreshold = quantum*m_threshold;
+
+ for (uint y = 0 ; !m_cancel && (y < m_destImage.height()) ; y++)
+ {
+ for (uint x = 0 ; !m_cancel && (x < m_destImage.width()) ; x++)
+ {
+ p = m_orgImage.getPixelColor(x, y);
+ q = m_destImage.getPixelColor(x, y);
+
+ // Red channel.
+ value = (double)(p.red())-(double)(q.red());
+
+ if (fabs(2.0*value) < quantumThreshold)
+ value = (double)(p.red());
+ else
+ value = (double)(p.red()) + value*m_amount;
+
+ q.setRed(CLAMP(ROUND(value), 0, quantum));
+
+ // Green Channel.
+ value = (double)(p.green())-(double)(q.green());
+
+ if (fabs(2.0*value) < quantumThreshold)
+ value = (double)(p.green());
+ else
+ value = (double)(p.green()) + value*m_amount;
+
+ q.setGreen(CLAMP(ROUND(value), 0, quantum));
+
+ // Blue Channel.
+ value = (double)(p.blue())-(double)(q.blue());
+
+ if (fabs(2.0*value) < quantumThreshold)
+ value = (double)(p.blue());
+ else
+ value = (double)(p.blue()) + value*m_amount;
+
+ q.setBlue(CLAMP(ROUND(value), 0, quantum));
+
+ // Alpha Channel.
+ value = (double)(p.alpha())-(double)(q.alpha());
+
+ if (fabs(2.0*value) < quantumThreshold)
+ value = (double)(p.alpha());
+ else
+ value = (double)(p.alpha()) + value*m_amount;
+
+ q.setAlpha(CLAMP(ROUND(value), 0, quantum));
+
+ m_destImage.setPixelColor(x, y, q);
+ }
+
+ progress = (int)(10.0 + ((double)y * 90.0) / m_destImage.height());
+ if ( progress%5 == 0 )
+ postProgress( progress );
+ }
+}
+
+} // NameSpace DigikamImagesPluginCore
diff --git a/src/imageplugins/coreplugin/sharpnesseditor/unsharp.h b/src/imageplugins/coreplugin/sharpnesseditor/unsharp.h
new file mode 100644
index 00000000..a1780ab4
--- /dev/null
+++ b/src/imageplugins/coreplugin/sharpnesseditor/unsharp.h
@@ -0,0 +1,58 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Unsharp Mask threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef UNSHARP_MASK_H
+#define UNSHARP_MASK_H
+
+// Local includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamImagesPluginCore
+{
+
+class UnsharpMask : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ UnsharpMask(Digikam::DImg *orgImage, TQObject *parent=0, int radius=1,
+ double amount=1.0, double threshold=0.05);
+
+ ~UnsharpMask(){};
+
+private:
+
+ virtual void filterImage(void);
+
+private:
+
+ int m_radius;
+
+ double m_amount;
+ double m_threshold;
+};
+
+} // NameSpace DigikamImagesPluginCore
+
+#endif /* UNSHARP_MASK_H */
diff --git a/src/imageplugins/distortionfx/Makefile.am b/src/imageplugins/distortionfx/Makefile.am
new file mode 100644
index 00000000..fcb7b74a
--- /dev/null
+++ b/src/imageplugins/distortionfx/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_distortionfx_la_SOURCES = imageplugin_distortionfx.cpp \
+ distortionfxtool.cpp distortionfx.cpp
+
+digikamimageplugin_distortionfx_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_distortionfx_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_distortionfx.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_distortionfx.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_distortionfx_ui.rc
+
diff --git a/src/imageplugins/distortionfx/digikamimageplugin_distortionfx.desktop b/src/imageplugins/distortionfx/digikamimageplugin_distortionfx.desktop
new file mode 100644
index 00000000..8baca4eb
--- /dev/null
+++ b/src/imageplugins/distortionfx/digikamimageplugin_distortionfx.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Name=ImagePlugin_DistortionFX
+Name[bg]=Приставка за снимки - Изкривяващи ефекти
+Name[da]=Plugin for forvrængningseffekt
+Name[el]=ΠρόσθετοΕικόνας_ΕφέΠαραμόρφωσης
+Name[fi]=Vääristymä
+Name[hr]=Izobličenje
+Name[it]=PluginImmagini_EffettiDiDistorsione
+Name[nl]=Afbeeldingsplugin_Vervormingseffect
+Name[sr]=Ефекти изобличења
+Name[sr@Latn]=Efekti izobličenja
+Name[sv]=Insticksprogram för förvrängningseffekt
+Name[tr]=ResimEklentisi_Bozma
+Name[xx]=xxImagePlugin_DistortionFXxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Distortion special effects plugin for digiKam
+Comment[bg]=Приставка на digiKam с изкривяващи снимките ефекти
+Comment[ca]=Connector pel digiKam d'efectes especials de distorsió
+Comment[da]=Digikam plugin for forvrængningsspecialeffekt
+Comment[de]=digiKam-Modul zum Erzeugen von speziellen Verzerrungseffekten
+Comment[el]=Πρόσθετο ειδικών εφέ παραμόρφωσης για το digiKam
+Comment[es]=Plugin para digiKam con efectos de distorsión especiales
+Comment[et]=DigiKami spetsiaalsete moonutusefektide plugin
+Comment[fa]=وصلۀ جلوه‌های ویژۀ اعواج برای digiKam
+Comment[fi]=Vääristymäerikoistehosteita
+Comment[gl]=Un plugin de digiKam para efeitos especiais de distorsión
+Comment[hr]=digiKam dodatak za efekt izobličavanja
+Comment[is]=Íforrit fyrir digiKam sem afbakar sérstaklega myndir
+Comment[it]=Plugin degli effetti speciali di distorsione per digiKam
+Comment[ja]=digiKam ゆがめ特殊効果プラグイン
+Comment[nds]=digiKam-Moduul för Vertarren-Effekten
+Comment[nl]=Digikam-plugin voor vervormingseffect
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਖਿੰਡਾਉਣ ਖਾਸ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam oferująca efekty zniekształceń
+Comment[pt]=Um 'plugin' do digiKam para efeitos especiais de distorção
+Comment[pt_BR]=Plugin de efeito especial de distorção
+Comment[ru]=Модуль специальных шумовых эффектов для digiKam
+Comment[sk]=digiKam plugin pre špeciálne efekty skreslenia
+Comment[sr]=digiKam-ов прикључак за ефекте изобличења
+Comment[sr@Latn]=digiKam-ov priključak za efekte izobličenja
+Comment[sv]=Digikam insticksprogram för förvrängningsspecialeffekt
+Comment[tr]=Bozma etkileri uygulamak için bir digiKam eklentisi
+Comment[uk]=Втулок спеціальних ефектів спотворення для digiKam
+Comment[vi]=Phần bổ sung hiệu ứng méo mó ảnh cho digiKam
+Comment[xx]=xxDistortion special effects plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_distortionfx
+author=Caulier Gilles, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/distortionfx/digikamimageplugin_distortionfx_ui.rc b/src/imageplugins/distortionfx/digikamimageplugin_distortionfx_ui.rc
new file mode 100644
index 00000000..99b905ad
--- /dev/null
+++ b/src/imageplugins/distortionfx/digikamimageplugin_distortionfx_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_distortionfx" >
+
+ <MenuBar>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_distortionfx" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_distortionfx" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/distortionfx/distortionfx.cpp b/src/imageplugins/distortionfx/distortionfx.cpp
new file mode 100644
index 00000000..d17abd4f
--- /dev/null
+++ b/src/imageplugins/distortionfx/distortionfx.cpp
@@ -0,0 +1,869 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-18
+ * Description : Distortion FX threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Distortion algorithms copyrighted 2004-2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Represents 1
+#define ANGLE_RATIO 0.017453292519943295769236907685
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqdatetime.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "distortionfx.h"
+
+namespace DigikamDistortionFXImagesPlugin
+{
+
+DistortionFX::DistortionFX(Digikam::DImg *orgImage, TQObject *parent, int effectType,
+ int level, int iteration, bool antialiasing)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "DistortionFX")
+{
+ m_effectType = effectType;
+ m_level = level;
+ m_iteration = iteration;
+ m_antiAlias = antialiasing;
+
+ initFilter();
+}
+
+void DistortionFX::filterImage(void)
+{
+ int w = m_orgImage.width();
+ int h = m_orgImage.height();
+ int l = m_level;
+ int f = m_iteration;
+
+ switch (m_effectType)
+ {
+ case FishEye:
+ fisheye(&m_orgImage, &m_destImage, (double)(l/5.0), m_antiAlias);
+ break;
+
+ case Twirl:
+ twirl(&m_orgImage, &m_destImage, l, m_antiAlias);
+ break;
+
+ case CilindricalHor:
+ cilindrical(&m_orgImage, &m_destImage, (double)l, true, false, m_antiAlias);
+ break;
+
+ case CilindricalVert:
+ cilindrical(&m_orgImage, &m_destImage, (double)l, false, true, m_antiAlias);
+ break;
+
+ case CilindricalHV:
+ cilindrical(&m_orgImage, &m_destImage, (double)l, true, true, m_antiAlias);
+ break;
+
+ case Caricature:
+ fisheye(&m_orgImage, &m_destImage, (double)(-l/5.0), m_antiAlias);
+ break;
+
+ case MultipleCorners:
+ multipleCorners(&m_orgImage, &m_destImage, l, m_antiAlias);
+ break;
+
+ case WavesHorizontal:
+ waves(&m_orgImage, &m_destImage, l, f, true, true);
+ break;
+
+ case WavesVertical:
+ waves(&m_orgImage, &m_destImage, l, f, true, false);
+ break;
+
+ case BlockWaves1:
+ blockWaves(&m_orgImage, &m_destImage, l, f, false);
+ break;
+
+ case BlockWaves2:
+ blockWaves(&m_orgImage, &m_destImage, l, f, true);
+ break;
+
+ case CircularWaves1:
+ circularWaves(&m_orgImage, &m_destImage, w/2, h/2, (double)l, (double)f, 0.0, false, m_antiAlias);
+ break;
+
+ case CircularWaves2:
+ circularWaves(&m_orgImage, &m_destImage, w/2, h/2, (double)l, (double)f, 25.0, true, m_antiAlias);
+ break;
+
+ case PolarCoordinates:
+ polarCoordinates(&m_orgImage, &m_destImage, true, m_antiAlias);
+ break;
+
+ case UnpolarCoordinates:
+ polarCoordinates(&m_orgImage, &m_destImage, false, m_antiAlias);
+ break;
+
+ case Tile:
+ tile(&m_orgImage, &m_destImage, 200-f, 200-f, l);
+ break;
+ }
+}
+
+/*
+ This code is shared by six methods.
+ Write value of pixel w|h in data to pixel nw|nh in pResBits.
+ Antialias if requested.
+*/
+void DistortionFX::setPixelFromOther(int Width, int Height, bool sixteenBit, int bytesDepth,
+ uchar *data, uchar *pResBits,
+ int w, int h, double nw, double nh, bool AntiAlias)
+{
+ Digikam::DColor color;
+ int offset, offsetOther;
+
+ offset = getOffset(Width, w, h, bytesDepth);
+
+ if (AntiAlias)
+ {
+ uchar *ptr = pResBits + offset;
+ if (sixteenBit)
+ {
+ unsigned short *ptr16 = (unsigned short *)ptr;
+ Digikam::DImgImageFilters().pixelAntiAliasing16((unsigned short *)data, Width, Height, nw, nh,
+ ptr16+3, ptr16+2, ptr16+1, ptr16);
+ }
+ else
+ {
+ Digikam::DImgImageFilters().pixelAntiAliasing(data, Width, Height, nw, nh,
+ ptr+3, ptr+2, ptr+1, ptr);
+ }
+ }
+ else
+ {
+ // we get the position adjusted
+ offsetOther = getOffsetAdjusted(Width, Height, (int)nw, (int)nh, bytesDepth);
+ // read color
+ color.setColor(data + offsetOther, sixteenBit);
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+}
+
+/* Function to apply the fisheye effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Coeff => Distortion effect coeff. Positive value render 'Fish Eyes' effect,
+ * and negative values render 'Caricature' effect.
+ * Antialias => Smart bluring result.
+ *
+ * Theory => This is a great effect if you take employee photos
+ * Its pure trigonometry. I think if you study hard the code you
+ * understand very well.
+ */
+void DistortionFX::fisheye(Digikam::DImg *orgImage, Digikam::DImg *destImage, double Coeff, bool AntiAlias)
+{
+ if (Coeff == 0.0) return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int h, w;
+ double nh, nw, th, tw;
+
+ int progress;
+ int nHalfW = Width / 2, nHalfH = Height / 2;
+
+ Digikam::DColor color;
+ int offset;
+
+ double lfXScale = 1.0, lfYScale = 1.0;
+ double lfRadius, lfRadMax, lfAngle, lfCoeff, lfCoeffStep = Coeff / 1000.0;
+
+ if (Width > Height)
+ lfYScale = (double)Width / (double)Height;
+ else if (Height > Width)
+ lfXScale = (double)Height / (double)Width;
+
+ lfRadMax = (double)TQMAX(Height, Width) / 2.0;
+ lfCoeff = lfRadMax / log (fabs (lfCoeffStep) * lfRadMax + 1.0);
+
+ // main loop
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ th = lfYScale * (double)(h - nHalfH);
+
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ tw = lfXScale * (double)(w - nHalfW);
+
+ // we find the distance from the center
+ lfRadius = sqrt (th * th + tw * tw);
+
+ if (lfRadius < lfRadMax)
+ {
+ lfAngle = atan2 (th, tw);
+
+ if (Coeff > 0.0)
+ lfRadius = (exp (lfRadius / lfCoeff) - 1.0) / lfCoeffStep;
+ else
+ lfRadius = lfCoeff * log (1.0 + (-1.0 * lfCoeffStep) * lfRadius);
+
+ nw = (double)nHalfW + (lfRadius / lfXScale) * cos (lfAngle);
+ nh = (double)nHalfH + (lfRadius / lfYScale) * sin (lfAngle);
+
+ setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
+ }
+ else
+ {
+ // copy pixel
+ offset = getOffset(Width, w, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(pResBits + offset);
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)(h) * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the twirl effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Twirl => Distance value.
+ * Antialias => Smart bluring result.
+ *
+ * Theory => Take spiral studies, you will understand better, I'm studying
+ * hard on this effect, because it is not too fast.
+ */
+void DistortionFX::twirl(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Twirl, bool AntiAlias)
+{
+ // if twirl value is zero, we do nothing
+
+ if (Twirl == 0)
+ return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int h, w;
+ double tw, th, nh, nw;
+
+ Digikam::DColor color;
+ int offset;
+
+ int progress;
+ int nHalfW = Width / 2, nHalfH = Height / 2;
+
+ double lfXScale = 1.0, lfYScale = 1.0;
+ double lfAngle, lfNewAngle, lfAngleStep, lfAngleSum, lfCurrentRadius, lfRadMax;
+
+ if (Width > Height)
+ lfYScale = (double)Width / (double)Height;
+ else if (Height > Width)
+ lfXScale = (double)Height / (double)Width;
+
+ // the angle step is twirl divided by 10000
+ lfAngleStep = Twirl / 10000.0;
+ // now, we get the minimum radius
+ lfRadMax = (double)TQMAX(Width, Height) / 2.0;
+
+ // main loop
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ th = lfYScale * (double)(h - nHalfH);
+
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ tw = lfXScale * (double)(w - nHalfW);
+
+ // now, we get the distance
+ lfCurrentRadius = sqrt (th * th + tw * tw);
+
+ // if distance is less than maximum radius...
+ if (lfCurrentRadius < lfRadMax)
+ {
+ // we find the angle from the center
+ lfAngle = atan2 (th, tw);
+ // we get the accumuled angle
+ lfAngleSum = lfAngleStep * (-1.0 * (lfCurrentRadius - lfRadMax));
+ // ok, we sum angle with accumuled to find a new angle
+ lfNewAngle = lfAngle + lfAngleSum;
+
+ // now we find the exact position's x and y
+ nw = (double)nHalfW + cos (lfNewAngle) * (lfCurrentRadius / lfXScale);
+ nh = (double)nHalfH + sin (lfNewAngle) * (lfCurrentRadius / lfYScale);
+
+ setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
+ }
+ else
+ {
+ // copy pixel
+ offset = getOffset(Width, w, h, bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(pResBits + offset);
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the Cilindrical effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Coeff => Cilindrical value.
+ * Horizontal => Apply horizontally.
+ * Vertical => Apply vertically.
+ * Antialias => Smart bluring result.
+ *
+ * Theory => This is a great effect, similar to Spherize (Photoshop).
+ * If you understand FishEye, you will understand Cilindrical
+ * FishEye apply a logarithm function using a sphere radius,
+ * Spherize use the same function but in a rectangular
+ * environment.
+ */
+void DistortionFX::cilindrical(Digikam::DImg *orgImage, Digikam::DImg *destImage, double Coeff,
+ bool Horizontal, bool Vertical, bool AntiAlias)
+
+{
+ if ((Coeff == 0.0) || (! (Horizontal || Vertical)))
+ return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int progress;
+
+ int h, w;
+ double nh, nw;
+
+ int nHalfW = Width / 2, nHalfH = Height / 2;
+ double lfCoeffX = 1.0, lfCoeffY = 1.0, lfCoeffStep = Coeff / 1000.0;
+
+ if (Horizontal)
+ lfCoeffX = (double)nHalfW / log (fabs (lfCoeffStep) * nHalfW + 1.0);
+ if (Vertical)
+ lfCoeffY = (double)nHalfH / log (fabs (lfCoeffStep) * nHalfH + 1.0);
+
+ // initial copy
+ memcpy (pResBits, data, orgImage->numBytes());
+
+ // main loop
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ // we find the distance from the center
+ nh = fabs ((double)(h - nHalfH));
+ nw = fabs ((double)(w - nHalfW));
+
+ if (Horizontal)
+ {
+ if (Coeff > 0.0)
+ nw = (exp (nw / lfCoeffX) - 1.0) / lfCoeffStep;
+ else
+ nw = lfCoeffX * log (1.0 + (-1.0 * lfCoeffStep) * nw);
+ }
+
+ if (Vertical)
+ {
+ if (Coeff > 0.0)
+ nh = (exp (nh / lfCoeffY) - 1.0) / lfCoeffStep;
+ else
+ nh = lfCoeffY * log (1.0 + (-1.0 * lfCoeffStep) * nh);
+ }
+
+ nw = (double)nHalfW + ((w >= nHalfW) ? nw : -nw);
+ nh = (double)nHalfH + ((h >= nHalfH) ? nh : -nh);
+
+ setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the Multiple Corners effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Factor => nb corners.
+ * Antialias => Smart bluring result.
+ *
+ * Theory => This is an amazing function, you've never seen this before.
+ * I was testing some trigonometric functions, and I saw that if
+ * I multiply the angle by 2, the result is an image like this
+ * If we multiply by 3, we can create the SixCorners effect.
+ */
+void DistortionFX::multipleCorners(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Factor, bool AntiAlias)
+{
+ if (Factor == 0) return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int h, w;
+ double nh, nw;
+ int progress;
+
+ int nHalfW = Width / 2, nHalfH = Height / 2;
+ double lfAngle, lfNewRadius, lfCurrentRadius, lfRadMax;
+
+ lfRadMax = sqrt (Height * Height + Width * Width) / 2.0;
+
+ // main loop
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ // we find the distance from the center
+ nh = nHalfH - h;
+ nw = nHalfW - w;
+
+ // now, we get the distance
+ lfCurrentRadius = sqrt (nh * nh + nw * nw);
+ // we find the angle from the center
+ lfAngle = atan2 (nh, nw) * (double)Factor;
+
+ // ok, we sum angle with accumuled to find a new angle
+ lfNewRadius = lfCurrentRadius * lfCurrentRadius / lfRadMax;
+
+ // now we find the exact position's x and y
+ nw = (double)nHalfW - (cos (lfAngle) * lfNewRadius);
+ nh = (double)nHalfH - (sin (lfAngle) * lfNewRadius);
+
+ setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the Polar Coordinates effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Type => if true Polar Coordinate to Polar else inverse.
+ * Antialias => Smart bluring result.
+ *
+ * Theory => Similar to PolarCoordinates from Photoshop. We apply the polar
+ * transformation in a proportional (Height and Width) radius.
+ */
+void DistortionFX::polarCoordinates(Digikam::DImg *orgImage, Digikam::DImg *destImage, bool Type, bool AntiAlias)
+{
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int h, w;
+ double nh, nw, th, tw;
+ int progress;
+
+ int nHalfW = Width / 2, nHalfH = Height / 2;
+ double lfXScale = 1.0, lfYScale = 1.0;
+ double lfAngle, lfRadius, lfRadMax;
+
+ if (Width > Height)
+ lfYScale = (double)Width / (double)Height;
+ else if (Height > Width)
+ lfXScale = (double)Height / (double)Width;
+
+ lfRadMax = (double)TQMAX(Height, Width) / 2.0;
+
+ // main loop
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ th = lfYScale * (double)(h - nHalfH);
+
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ tw = lfXScale * (double)(w - nHalfW);
+
+ if (Type)
+ {
+ // now, we get the distance
+ lfRadius = sqrt (th * th + tw * tw);
+ // we find the angle from the center
+ lfAngle = atan2 (tw, th);
+
+ // now we find the exact position's x and y
+ nh = lfRadius * (double) Height / lfRadMax;
+ nw = lfAngle * (double) Width / (2 * M_PI);
+
+ nw = (double)nHalfW + nw;
+ }
+ else
+ {
+ lfRadius = (double)(h) * lfRadMax / (double)Height;
+ lfAngle = (double)(w) * (2 * M_PI) / (double) Width;
+
+ nw = (double)nHalfW - (lfRadius / lfXScale) * sin (lfAngle);
+ nh = (double)nHalfH - (lfRadius / lfYScale) * cos (lfAngle);
+ }
+
+ setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the circular waves effect backported from ImageProcessing version 2
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * X, Y => Position of circle center on the image.
+ * Amplitude => Sinoidal maximum height
+ * Frequency => Frequency value.
+ * Phase => Phase value.
+ * WavesType => If true the amplitude is proportional to radius.
+ * Antialias => Smart bluring result.
+ *
+ * Theory => Similar to Waves effect, but here I apply a senoidal function
+ * with the angle point.
+ */
+void DistortionFX::circularWaves(Digikam::DImg *orgImage, Digikam::DImg *destImage, int X, int Y, double Amplitude,
+ double Frequency, double Phase, bool WavesType, bool AntiAlias)
+{
+ if (Amplitude < 0.0) Amplitude = 0.0;
+ if (Frequency < 0.0) Frequency = 0.0;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int h, w;
+ double nh, nw;
+ int progress;
+
+ double lfRadius, lfRadMax, lfNewAmp = Amplitude;
+ double lfFreqAngle = Frequency * ANGLE_RATIO;
+
+ Phase *= ANGLE_RATIO;
+
+ lfRadMax = sqrt (Height * Height + Width * Width);
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ nw = X - w;
+ nh = Y - h;
+
+ lfRadius = sqrt (nw * nw + nh * nh);
+
+ if (WavesType)
+ lfNewAmp = Amplitude * lfRadius / lfRadMax;
+
+ nw = (double)w + lfNewAmp * sin(lfFreqAngle * lfRadius + Phase);
+ nh = (double)h + lfNewAmp * cos(lfFreqAngle * lfRadius + Phase);
+
+ setPixelFromOther(Width, Height, sixteenBit, bytesDepth, data, pResBits, w, h, nw, nh, AntiAlias);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the waves effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Amplitude => Sinoidal maximum height.
+ * Frequency => Frequency value.
+ * FillSides => Like a boolean variable.
+ * Direction => Vertical or horizontal flag.
+ *
+ * Theory => This is an amazing effect, very funny, and very simple to
+ * understand. You just need understand how sin and cos works.
+ */
+void DistortionFX::waves(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int Amplitude, int Frequency,
+ bool FillSides, bool Direction)
+{
+ if (Amplitude < 0) Amplitude = 0;
+ if (Frequency < 0) Frequency = 0;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+
+ int progress;
+ int h, w;
+
+ if (Direction) // Horizontal
+ {
+ int tx;
+
+ for (h = 0; !m_cancel && (h < Height); h++)
+ {
+ tx = lround(Amplitude * sin ((Frequency * 2) * h * (M_PI / 180)));
+ destImage->bitBltImage(orgImage, 0, h, Width, 1, tx, h);
+
+ if (FillSides)
+ {
+ destImage->bitBltImage(orgImage, Width - tx, h, tx, 1, 0, h);
+ destImage->bitBltImage(orgImage, 0, h, Width - (Width - 2 * Amplitude + tx), 1, Width + tx, h);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+ }
+ else
+ {
+ int ty;
+
+ for (w = 0; !m_cancel && (w < Width); w++)
+ {
+ ty = lround(Amplitude * sin ((Frequency * 2) * w * (M_PI / 180)));
+ destImage->bitBltImage(orgImage, w, 0, 1, Height, w, ty);
+
+ if (FillSides)
+ {
+ destImage->bitBltImage(orgImage, w, Height - ty, 1, ty, w, 0);
+ destImage->bitBltImage(orgImage, w, 0, 1, Height - (Height - 2 * Amplitude + ty), w, Height + ty);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)w * 100.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+ }
+}
+
+/* Function to apply the block waves effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * Amplitude => Sinoidal maximum height
+ * Frequency => Frequency value
+ * Mode => The mode to be applied.
+ *
+ * Theory => This is an amazing effect, very funny when amplitude and
+ * frequency are small values.
+ */
+void DistortionFX::blockWaves(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int Amplitude, int Frequency, bool Mode)
+{
+ if (Amplitude < 0) Amplitude = 0;
+ if (Frequency < 0) Frequency = 0;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* pResBits = destImage->bits();
+
+ int nw, nh, progress;
+ double Radius;
+
+ Digikam::DColor color;
+ int offset, offsetOther;
+
+ int nHalfW = Width / 2, nHalfH = Height / 2;
+
+ for (int w = 0; !m_cancel && (w < Width); w++)
+ {
+ for (int h = 0; !m_cancel && (h < Height); h++)
+ {
+ nw = nHalfW - w;
+ nh = nHalfH - h;
+
+ Radius = sqrt (nw * nw + nh * nh);
+
+ if (Mode)
+ {
+ nw = (int)(w + Amplitude * sin (Frequency * nw * (M_PI / 180)));
+ nh = (int)(h + Amplitude * cos (Frequency * nh * (M_PI / 180)));
+ }
+ else
+ {
+ nw = (int)(w + Amplitude * sin (Frequency * w * (M_PI / 180)));
+ nh = (int)(h + Amplitude * cos (Frequency * h * (M_PI / 180)));
+ }
+
+ offset = getOffset(Width, w, h, bytesDepth);
+ offsetOther = getOffsetAdjusted(Width, Height, (int)nw, (int)nh, bytesDepth);
+
+ // read color
+ color.setColor(data + offsetOther, sixteenBit);
+ // write color to destination
+ color.setPixel(pResBits + offset);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int) (((double)w * 100.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+/* Function to apply the tile effect
+ *
+ * data => The image data in RGBA mode.
+ * Width => Width of image.
+ * Height => Height of image.
+ * WSize => Tile Width
+ * HSize => Tile Height
+ * Random => Maximum random value
+ *
+ * Theory => Similar to Tile effect from Photoshop and very easy to
+ * understand. We get a rectangular area using WSize and HSize and
+ * replace in a position with a random distance from the original
+ * position.
+ */
+void DistortionFX::tile(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ int WSize, int HSize, int Random)
+{
+ if (WSize < 1) WSize = 1;
+ if (HSize < 1) HSize = 1;
+ if (Random < 1) Random = 1;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+
+ TQDateTime dt = TQDateTime::currentDateTime();
+ TQDateTime Y2000( TQDate(2000, 1, 1), TQTime(0, 0, 0) );
+ uint seed = dt.secsTo(Y2000);
+
+ int tx, ty, h, w, progress;
+
+ for (h = 0; !m_cancel && (h < Height); h += HSize)
+ {
+ for (w = 0; !m_cancel && (w < Width); w += WSize)
+ {
+ tx = (int)(rand_r(&seed) % Random) - (Random / 2);
+ ty = (int)(rand_r(&seed) % Random) - (Random / 2);
+ destImage->bitBltImage(orgImage, w, h, WSize, HSize, w + tx, h + ty);
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int)(((double)h * 100.0) / Height);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+// UNUSED
+/* Function to return the maximum radius with a determined angle
+ *
+ * Height => Height of the image
+ * Width => Width of the image
+ * Angle => Angle to analize the maximum radius
+ *
+ * Theory => This function calcule the maximum radius to that angle
+ * so, we can build an oval circunference
+ */
+ /*
+double DistortionFX::maximumRadius(int Height, int Width, double Angle)
+{
+ double MaxRad, MinRad;
+ double Radius, DegAngle = fabs (Angle * 57.295); // Rads -> Degrees
+
+ MinRad = TQMIN (Height, Width) / 2.0; // Gets the minor radius
+ MaxRad = TQMAX (Height, Width) / 2.0; // Gets the major radius
+
+ // Find the quadrant between -PI/2 and PI/2
+ if (DegAngle > 90.0)
+ Radius = proportionalValue (MinRad, MaxRad, (DegAngle * (255.0 / 90.0)));
+ else
+ Radius = proportionalValue (MaxRad, MinRad, ((DegAngle - 90.0) * (255.0 / 90.0)));
+ return (Radius);
+}
+ */
+
+} // NameSpace DigikamDistortionFXImagesPlugin
diff --git a/src/imageplugins/distortionfx/distortionfx.h b/src/imageplugins/distortionfx/distortionfx.h
new file mode 100644
index 00000000..073f4df2
--- /dev/null
+++ b/src/imageplugins/distortionfx/distortionfx.h
@@ -0,0 +1,149 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-18
+ * Description : Distortion FX threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Distortion algorithms copyrighted 2004-2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef DISTORTION_FX_H
+#define DISTORTION_FX_H
+
+// TQt includes.
+
+#include <tqsize.h>
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamDistortionFXImagesPlugin
+{
+
+class DistortionFX : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ DistortionFX(Digikam::DImg *orgImage, TQObject *parent=0, int effectType=0,
+ int level=0, int iteration=0, bool antialiasing=true);
+
+ ~DistortionFX(){};
+
+public:
+
+ enum DistortionFXTypes
+ {
+ FishEye=0,
+ Twirl,
+ CilindricalHor,
+ CilindricalVert,
+ CilindricalHV,
+ Caricature,
+ MultipleCorners,
+ WavesHorizontal,
+ WavesVertical,
+ BlockWaves1,
+ BlockWaves2,
+ CircularWaves1,
+ CircularWaves2,
+ PolarCoordinates,
+ UnpolarCoordinates,
+ Tile
+ };
+
+private:
+
+ virtual void filterImage(void);
+
+ // Backported from ImageProcessing version 2
+ void fisheye(Digikam::DImg *orgImage, Digikam::DImg *destImage, double Coeff, bool AntiAlias=true);
+ void twirl(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Twirl, bool AntiAlias=true);
+ void cilindrical(Digikam::DImg *orgImage, Digikam::DImg *destImage, double Coeff,
+ bool Horizontal, bool Vertical, bool AntiAlias=true);
+ void multipleCorners(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Factor, bool AntiAlias=true);
+ void polarCoordinates(Digikam::DImg *orgImage, Digikam::DImg *destImage, bool Type, bool AntiAlias=true);
+ void circularWaves(Digikam::DImg *orgImage, Digikam::DImg *destImage, int X, int Y, double Amplitude,
+ double Frequency, double Phase, bool WavesType, bool AntiAlias=true);
+
+ // Backported from ImageProcessing version 1
+ void waves(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Amplitude, int Frequency,
+ bool FillSides, bool Direction);
+ void blockWaves(Digikam::DImg *orgImage, Digikam::DImg *destImage, int Amplitude, int Frequency, bool Mode);
+ void tile(Digikam::DImg *orgImage, Digikam::DImg *destImage, int WSize, int HSize, int Random);
+
+ void setPixelFromOther(int Width, int Height, bool sixteenBit, int bytesDepth,
+ uchar *data, uchar *pResBits,
+ int w, int h, double nw, double nh, bool AntiAlias);
+ /*
+ //UNUSED
+
+ inline double maximumRadius(int Height, int Width, double Angle);
+
+ // This function does the same thing that ShadeColors function but using double variables.
+ inline double proportionalValue (double DestValue, double SrcValue, double Shade)
+ {
+ if (Shade == 0.0) return DestValue;
+ if (Shade == 255.0) return SrcValue;
+ return ((DestValue * (255.0 - Shade) + SrcValue * Shade) / 256.0);
+ };
+ */
+
+ // Return the limit defined the max and min values.
+ inline int Lim_Max(int Now, int Up, int Max)
+ {
+ --Max;
+ while (Now > Max - Up) --Up;
+ return (Up);
+ };
+
+ inline bool isInside (int Width, int Height, int X, int Y)
+ {
+ bool bIsWOk = ((X < 0) ? false : (X >= Width ) ? false : true);
+ bool bIsHOk = ((Y < 0) ? false : (Y >= Height) ? false : true);
+ return (bIsWOk && bIsHOk);
+ };
+
+ inline int getOffset(int Width, int X, int Y, int bytesDepth)
+ {
+ return (Y * Width * bytesDepth) + (X * bytesDepth);
+ };
+
+ inline int getOffsetAdjusted(int Width, int Height, int X, int Y, int bytesDepth)
+ {
+ X = (X < 0) ? 0 : ((X >= Width ) ? (Width - 1) : X);
+ Y = (Y < 0) ? 0 : ((Y >= Height) ? (Height - 1) : Y);
+ return getOffset(Width, X, Y, bytesDepth);
+ };
+
+private:
+
+ bool m_antiAlias;
+
+ int m_level;
+ int m_iteration;
+ int m_effectType;
+};
+
+} // NameSpace DigikamDistortionFXImagesPlugin
+
+#endif /* DISTORTION_FX_H */
diff --git a/src/imageplugins/distortionfx/distortionfxtool.cpp b/src/imageplugins/distortionfx/distortionfxtool.cpp
new file mode 100644
index 00000000..45ff0e45
--- /dev/null
+++ b/src/imageplugins/distortionfx/distortionfxtool.cpp
@@ -0,0 +1,398 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-11
+ * Description : a plugin to apply Distortion FX to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Distortion algorithms copyrighted 2004-2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqframe.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqspinbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kprogress.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "editortoolsettings.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "distortionfx.h"
+#include "distortionfxtool.h"
+#include "distortionfxtool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamDistortionFXImagesPlugin
+{
+
+DistortionFXTool::DistortionFXTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("distortionfx");
+ setToolName(i18n("Distortion Effects"));
+ setToolIcon(SmallIcon("distortionfx"));
+
+ m_previewWidget = new ImageWidget("distortionfx Tool", 0,
+ i18n("<p>This is the preview of the distortion effect "
+ "applied to the photograph."),
+ false, ImageGuideWidget::HVGuideMode);
+
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel,
+ EditorToolSettings::ColorGuide);
+
+ TQGridLayout* gridSettings = new TQGridLayout(m_gboxSettings->plainPage(), 7, 2);
+
+ m_effectTypeLabel = new TQLabel(i18n("Type:"), m_gboxSettings->plainPage());
+
+ m_effectType = new RComboBox(m_gboxSettings->plainPage());
+ m_effectType->insertItem(i18n("Fish Eyes"));
+ m_effectType->insertItem(i18n("Twirl"));
+ m_effectType->insertItem(i18n("Cylindrical Hor."));
+ m_effectType->insertItem(i18n("Cylindrical Vert."));
+ m_effectType->insertItem(i18n("Cylindrical H/V."));
+ m_effectType->insertItem(i18n("Caricature"));
+ m_effectType->insertItem(i18n("Multiple Corners"));
+ m_effectType->insertItem(i18n("Waves Hor."));
+ m_effectType->insertItem(i18n("Waves Vert."));
+ m_effectType->insertItem(i18n("Block Waves 1"));
+ m_effectType->insertItem(i18n("Block Waves 2"));
+ m_effectType->insertItem(i18n("Circular Waves 1"));
+ m_effectType->insertItem(i18n("Circular Waves 2"));
+ m_effectType->insertItem(i18n("Polar Coordinates"));
+ m_effectType->insertItem(i18n("Unpolar Coordinates"));
+ m_effectType->insertItem(i18n("Tile"));
+ m_effectType->setDefaultItem(DistortionFX::FishEye);
+ TQWhatsThis::add( m_effectType, i18n("<p>Here, select the type of effect to apply to the image.<p>"
+ "<b>Fish Eyes</b>: warps the photograph around a 3D spherical shape to "
+ "reproduce the common photograph 'Fish Eyes' effect.<p>"
+ "<b>Twirl</b>: spins the photograph to produce a Twirl pattern.<p>"
+ "<b>Cylinder Hor.</b>: warps the photograph around a horizontal cylinder.<p>"
+ "<b>Cylinder Vert.</b>: warps the photograph around a vertical cylinder.<p>"
+ "<b>Cylinder H/V.</b>: warps the photograph around 2 cylinders, vertical "
+ "and horizontal.<p>"
+ "<b>Caricature</b>: distorts the photograph with the 'Fish Eyes' effect inverted.<p>"
+ "<b>Multiple Corners</b>: splits the photograph like a multiple corners pattern.<p>"
+ "<b>Waves Horizontal</b>: distorts the photograph with horizontal waves.<p>"
+ "<b>Waves Vertical</b>: distorts the photograph with vertical waves.<p>"
+ "<b>Block Waves 1</b>: divides the image into cells and makes it look as "
+ "if it is being viewed through glass blocks.<p>"
+ "<b>Block Waves 2</b>: like Block Waves 1 but with another version "
+ "of glass blocks distortion.<p>"
+ "<b>Circular Waves 1</b>: distorts the photograph with circular waves.<p>"
+ "<b>Circular Waves 2</b>: another variation of the Circular Waves effect.<p>"
+ "<b>Polar Coordinates</b>: converts the photograph from rectangular "
+ "to polar coordinates.<p>"
+ "<b>Unpolar Coordinates</b>: the Polar Coordinates effect inverted.<p>"
+ "<b>Tile</b>: splits the photograph into square blocks and moves "
+ "them randomly inside the image.<p>"
+ ));
+
+ m_levelLabel = new TQLabel(i18n("Level:"), m_gboxSettings->plainPage());
+ m_levelInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_levelInput->setRange(0, 100, 1);
+ m_levelInput->setDefaultValue(50);
+ TQWhatsThis::add( m_levelInput, i18n("<p>Set here the level of the effect."));
+
+
+ m_iterationLabel = new TQLabel(i18n("Iteration:"), m_gboxSettings->plainPage());
+ m_iterationInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_iterationInput->setRange(0, 100, 1);
+ m_iterationInput->setDefaultValue(10);
+ TQWhatsThis::add( m_iterationInput, i18n("<p>This value controls the iterations to use for Waves, "
+ "Tile, and Neon effects."));
+
+ gridSettings->addMultiCellWidget(m_effectTypeLabel, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_effectType, 1, 1, 0, 1);
+ gridSettings->addMultiCellWidget(m_levelLabel, 2, 2, 0, 1);
+ gridSettings->addMultiCellWidget(m_levelInput, 3, 3, 0, 1);
+ gridSettings->addMultiCellWidget(m_iterationLabel, 4, 4, 0, 1);
+ gridSettings->addMultiCellWidget(m_iterationInput, 5, 5, 0, 1);
+ gridSettings->setRowStretch(6, 10);
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_effectType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffectTypeChanged(int)));
+
+ connect(m_levelInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_iterationInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gboxSettings, TQ_SIGNAL(signalColorGuideChanged()),
+ this, TQ_SLOT(slotColorGuideChanged()));
+}
+
+DistortionFXTool::~DistortionFXTool()
+{
+}
+
+void DistortionFXTool::slotColorGuideChanged()
+{
+ m_previewWidget->slotChangeGuideColor(m_gboxSettings->guideColor());
+ m_previewWidget->slotChangeGuideSize(m_gboxSettings->guideSize());
+}
+
+void DistortionFXTool::renderingFinished()
+{
+ m_effectTypeLabel->setEnabled(true);
+ m_effectType->setEnabled(true);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ m_iterationInput->setEnabled(true);
+ m_iterationLabel->setEnabled(true);
+
+ switch (m_effectType->currentItem())
+ {
+ case DistortionFX::FishEye:
+ case DistortionFX::Twirl:
+ case DistortionFX::CilindricalHor:
+ case DistortionFX::CilindricalVert:
+ case DistortionFX::CilindricalHV:
+ case DistortionFX::Caricature:
+ case DistortionFX::MultipleCorners:
+ break;
+
+ case DistortionFX::PolarCoordinates:
+ case DistortionFX::UnpolarCoordinates:
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+ break;
+
+ case DistortionFX::WavesHorizontal:
+ case DistortionFX::WavesVertical:
+ case DistortionFX::BlockWaves1:
+ case DistortionFX::BlockWaves2:
+ case DistortionFX::CircularWaves1:
+ case DistortionFX::CircularWaves2:
+ case DistortionFX::Tile:
+ m_iterationInput->setEnabled(true);
+ m_iterationLabel->setEnabled(true);
+ break;
+ }
+}
+
+void DistortionFXTool::readSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("distortionfx Tool");
+
+ m_effectType->blockSignals(true);
+ m_iterationInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+
+ m_effectType->setCurrentItem(config->readNumEntry("EffectType",
+ m_effectType->defaultItem()));
+ m_iterationInput->setValue(config->readNumEntry("IterationAjustment",
+ m_iterationInput->defaultValue()));
+ m_levelInput->setValue(config->readNumEntry("LevelAjustment",
+ m_levelInput->defaultValue()));
+
+ m_effectType->blockSignals(false);
+ m_iterationInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void DistortionFXTool::writeSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("distortionfx Tool");
+ config->writeEntry("EffectType", m_effectType->currentItem());
+ config->writeEntry("IterationAjustment", m_iterationInput->value());
+ config->writeEntry("LevelAjustment", m_levelInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void DistortionFXTool::slotResetSettings()
+{
+ m_effectType->blockSignals(true);
+ m_levelInput->blockSignals(true);
+ m_iterationInput->blockSignals(true);
+
+ m_levelInput->slotReset();
+ m_iterationInput->slotReset();
+ m_effectType->slotReset();
+ slotEffectTypeChanged(m_effectType->defaultItem());
+
+ m_effectType->blockSignals(false);
+ m_levelInput->blockSignals(false);
+ m_iterationInput->blockSignals(false);
+}
+
+void DistortionFXTool::slotEffectTypeChanged(int type)
+{
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+
+ m_levelInput->blockSignals(true);
+ m_iterationInput->blockSignals(true);
+ m_levelInput->setRange(0, 100, 1);
+ m_levelInput->setValue(25);
+
+ switch (type)
+ {
+ case DistortionFX::Twirl:
+ m_levelInput->setRange(-50, 50, 1);
+ m_levelInput->setValue(10);
+ break;
+
+ case DistortionFX::FishEye:
+ case DistortionFX::CilindricalHor:
+ case DistortionFX::CilindricalVert:
+ case DistortionFX::CilindricalHV:
+ case DistortionFX::Caricature:
+ m_levelInput->setRange(0, 200, 1);
+ m_levelInput->setValue(50);
+ break;
+
+ case DistortionFX::MultipleCorners:
+ m_levelInput->setRange(1, 10, 1);
+ m_levelInput->setValue(4);
+ break;
+
+ case DistortionFX::WavesHorizontal:
+ case DistortionFX::WavesVertical:
+ case DistortionFX::BlockWaves1:
+ case DistortionFX::BlockWaves2:
+ case DistortionFX::CircularWaves1:
+ case DistortionFX::CircularWaves2:
+ case DistortionFX::Tile:
+ m_iterationInput->setEnabled(true);
+ m_iterationLabel->setEnabled(true);
+ m_iterationInput->setRange(0, 200, 1);
+ m_iterationInput->setValue(10);
+ break;
+
+ case DistortionFX::PolarCoordinates:
+ case DistortionFX::UnpolarCoordinates:
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+ break;
+ }
+
+ m_levelInput->blockSignals(false);
+ m_iterationInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void DistortionFXTool::prepareEffect()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+ m_iterationInput->setEnabled(false);
+ m_iterationLabel->setEnabled(false);
+
+ int l = m_levelInput->value();
+ int f = m_iterationInput->value();
+ int e = m_effectType->currentItem();
+
+ ImageIface* iface = m_previewWidget->imageIface();
+
+ uchar *data = iface->getPreviewImage();
+ DImg image(iface->previewWidth(), iface->previewHeight(), iface->previewSixteenBit(),
+ iface->previewHasAlpha(), data);
+ delete [] data;
+
+ setFilter(dynamic_cast<DImgThreadedFilter *> (new DistortionFX(&image, this, e, l, f)));
+}
+
+void DistortionFXTool::prepareFinal()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+ m_iterationInput->setEnabled(false);
+ m_iterationLabel->setEnabled(false);
+
+ int l = m_levelInput->value();
+ int f = m_iterationInput->value();
+ int e = m_effectType->currentItem();
+
+ ImageIface iface(0, 0);
+
+ setFilter(dynamic_cast<DImgThreadedFilter *> (new DistortionFX(iface.getOriginalImg(), this, e, l, f)));
+}
+
+void DistortionFXTool::putPreviewData(void)
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+
+ DImg imDest = filter()->getTargetImage()
+ .smoothScale(iface->previewWidth(), iface->previewHeight());
+ iface->putPreviewImage(imDest.bits());
+
+ m_previewWidget->updatePreview();
+}
+
+void DistortionFXTool::putFinalData(void)
+{
+ ImageIface iface(0, 0);
+ DImg targetImage = filter()->getTargetImage();
+ iface.putOriginalImage(i18n("Distortion Effects"),
+ targetImage.bits(),
+ targetImage.width(), targetImage.height());
+}
+
+} // NameSpace DigikamDistortionFXImagesPlugin
+
diff --git a/src/imageplugins/distortionfx/distortionfxtool.h b/src/imageplugins/distortionfx/distortionfxtool.h
new file mode 100644
index 00000000..bcdd6088
--- /dev/null
+++ b/src/imageplugins/distortionfx/distortionfxtool.h
@@ -0,0 +1,96 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-11
+ * Description : a plugin to apply Distortion FX to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Distortion algorithms copyrighted 2004-2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef DISTORTIONFXTOOL_H
+#define DISTORTIONFXTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQLabel;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class ImageWidget;
+}
+
+namespace DigikamDistortionFXImagesPlugin
+{
+
+class DistortionFXTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ DistortionFXTool(TQObject *parent);
+ ~DistortionFXTool();
+
+private slots:
+
+ void slotEffectTypeChanged(int type);
+ void slotResetSettings();
+ void slotColorGuideChanged();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+
+ TQLabel *m_effectTypeLabel;
+ TQLabel *m_levelLabel;
+ TQLabel *m_iterationLabel;
+
+ KDcrawIface::RComboBox *m_effectType;
+
+ KDcrawIface::RIntNumInput *m_levelInput;
+ KDcrawIface::RIntNumInput *m_iterationInput;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamDistortionFXImagesPlugin
+
+#endif /* DISTORTIONFXTOOL_H */
diff --git a/src/imageplugins/distortionfx/imageeffect_distortionfx.cpp b/src/imageplugins/distortionfx/imageeffect_distortionfx.cpp
new file mode 100644
index 00000000..695e7749
--- /dev/null
+++ b/src/imageplugins/distortionfx/imageeffect_distortionfx.cpp
@@ -0,0 +1,378 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-11
+ * Description : a plugin to apply Distortion FX to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Distortion algorithms copyrighted 2004-2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqimage.h>
+#include <tqspinbox.h>
+#include <tqcombobox.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <kcursor.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <tdeapplication.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "distortionfx.h"
+#include "imageeffect_distortionfx.h"
+#include "imageeffect_distortionfx.moc"
+
+namespace DigikamDistortionFXImagesPlugin
+{
+
+ImageEffect_DistortionFX::ImageEffect_DistortionFX(TQWidget* parent)
+ : Digikam::ImageGuideDlg(parent, i18n("Distortion Effects"),
+ "distortionfx", false, true, false,
+ Digikam::ImageGuideWidget::HVGuideMode)
+{
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Distortion Effects"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to apply distortion effects to an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2005, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Pieter Z. Voloshyn", I18N_NOOP("Distortion algorithms"),
+ "pieter dot voloshyn at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ TQWhatsThis::add( m_imagePreviewWidget, i18n("<p>This is the preview of the distortion effect "
+ "applied to the photograph.") );
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 5, 2, spacingHint());
+
+ m_effectTypeLabel = new TQLabel(i18n("Type:"), gboxSettings);
+
+ m_effectType = new TQComboBox( false, gboxSettings );
+ m_effectType->insertItem( i18n("Fish Eyes") );
+ m_effectType->insertItem( i18n("Twirl") );
+ m_effectType->insertItem( i18n("Cylindrical Hor.") );
+ m_effectType->insertItem( i18n("Cylindrical Vert.") );
+ m_effectType->insertItem( i18n("Cylindrical H/V.") );
+ m_effectType->insertItem( i18n("Caricature") );
+ m_effectType->insertItem( i18n("Multiple Corners") );
+ m_effectType->insertItem( i18n("Waves Hor.") );
+ m_effectType->insertItem( i18n("Waves Vert.") );
+ m_effectType->insertItem( i18n("Block Waves 1") );
+ m_effectType->insertItem( i18n("Block Waves 2") );
+ m_effectType->insertItem( i18n("Circular Waves 1") );
+ m_effectType->insertItem( i18n("Circular Waves 2") );
+ m_effectType->insertItem( i18n("Polar Coordinates") );
+ m_effectType->insertItem( i18n("Unpolar Coordinates") );
+ m_effectType->insertItem( i18n("Tile") );
+ TQWhatsThis::add( m_effectType, i18n("<p>Here, select the type of effect to apply to the image.<p>"
+ "<b>Fish Eyes</b>: warps the photograph around a 3D spherical shape to "
+ "reproduce the common photograph 'Fish Eyes' effect.<p>"
+ "<b>Twirl</b>: spins the photograph to produce a Twirl pattern.<p>"
+ "<b>Cylinder Hor.</b>: warps the photograph around a horizontal cylinder.<p>"
+ "<b>Cylinder Vert.</b>: warps the photograph around a vertical cylinder.<p>"
+ "<b>Cylinder H/V.</b>: warps the photograph around 2 cylinders, vertical "
+ "and horizontal.<p>"
+ "<b>Caricature</b>: distorts the photograph with the 'Fish Eyes' effect inverted.<p>"
+ "<b>Multiple Corners</b>: splits the photograph like a multiple corners pattern.<p>"
+ "<b>WavesQt Horizontal</b>: distorts the photograph with horizontal waves.<p>"
+ "<b>Waves Vertical</b>: distorts the photograph with vertical waves.<p>"
+ "<b>Block Waves 1</b>: divides the image into cells and makes it look as "
+ "if it is being viewed through glass blocks.<p>"
+ "<b>Block Waves 2</b>: like Block Waves 1 but with another version "
+ "of glass blocks distortion.<p>"
+ "<b>Circular Waves 1</b>: distorts the photograph with circular waves.<p>"
+ "<b>Circular Waves 2</b>: another variation of the Circular Waves effect.<p>"
+ "<b>Polar Coordinates</b>: converts the photograph from rectangular "
+ "to polar coordinates.<p>"
+ "<b>Unpolar Coordinates</b>: the Polar Coordinates effect inverted.<p>"
+ "<b>Tile</b>: splits the photograph into square blocks and moves "
+ "them randomly inside the image.<p>"
+ ));
+ gridSettings->addMultiCellWidget(m_effectTypeLabel, 0, 0, 0, 2);
+ gridSettings->addMultiCellWidget(m_effectType, 1, 1, 0, 2);
+
+ m_levelLabel = new TQLabel(i18n("Level:"), gboxSettings);
+ m_levelInput = new KIntNumInput(gboxSettings);
+ m_levelInput->setRange(0, 100, 1, true);
+ TQWhatsThis::add( m_levelInput, i18n("<p>Set here the level of the effect."));
+
+ gridSettings->addMultiCellWidget(m_levelLabel, 2, 2, 0, 2);
+ gridSettings->addMultiCellWidget(m_levelInput, 3, 3, 0, 2);
+
+ m_iterationLabel = new TQLabel(i18n("Iteration:"), gboxSettings);
+ m_iterationInput = new KIntNumInput(gboxSettings);
+ m_iterationInput->setRange(0, 100, 1, true);
+ TQWhatsThis::add( m_iterationInput, i18n("<p>This value controls the iterations to use for Waves, "
+ "Tile, and Neon effects."));
+
+ gridSettings->addMultiCellWidget(m_iterationLabel, 4, 4, 0, 2);
+ gridSettings->addMultiCellWidget(m_iterationInput, 5, 5, 0, 2);
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_effectType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffectTypeChanged(int)));
+
+ connect(m_levelInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_iterationInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_DistortionFX::~ImageEffect_DistortionFX()
+{
+}
+
+void ImageEffect_DistortionFX::renderingFinished()
+{
+ m_effectTypeLabel->setEnabled(true);
+ m_effectType->setEnabled(true);
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+ m_iterationInput->setEnabled(true);
+ m_iterationLabel->setEnabled(true);
+
+ switch (m_effectType->currentItem())
+ {
+ case DistortionFX::FishEye:
+ case DistortionFX::Twirl:
+ case DistortionFX::CilindricalHor:
+ case DistortionFX::CilindricalVert:
+ case DistortionFX::CilindricalHV:
+ case DistortionFX::Caricature:
+ case DistortionFX::MultipleCorners:
+ break;
+
+ case DistortionFX::PolarCoordinates:
+ case DistortionFX::UnpolarCoordinates:
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+ break;
+
+ case DistortionFX::WavesHorizontal:
+ case DistortionFX::WavesVertical:
+ case DistortionFX::BlockWaves1:
+ case DistortionFX::BlockWaves2:
+ case DistortionFX::CircularWaves1:
+ case DistortionFX::CircularWaves2:
+ case DistortionFX::Tile:
+ m_iterationInput->setEnabled(true);
+ m_iterationLabel->setEnabled(true);
+ break;
+ }
+}
+
+void ImageEffect_DistortionFX::readUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("distortionfx Tool Dialog");
+
+ m_effectType->blockSignals(true);
+ m_iterationInput->blockSignals(true);
+ m_levelInput->blockSignals(true);
+
+ m_effectType->setCurrentItem(config->readNumEntry("EffectType", DistortionFX::FishEye));
+ m_iterationInput->setValue(config->readNumEntry("IterationAjustment", 10));
+ m_levelInput->setValue(config->readNumEntry("LevelAjustment", 50));
+
+ m_effectType->blockSignals(false);
+ m_iterationInput->blockSignals(false);
+ m_levelInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ImageEffect_DistortionFX::writeUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("distortionfx Tool Dialog");
+ config->writeEntry("EffectType", m_effectType->currentItem());
+ config->writeEntry("IterationAjustment", m_iterationInput->value());
+ config->writeEntry("LevelAjustment", m_levelInput->value());
+ config->sync();
+}
+
+void ImageEffect_DistortionFX::resetValues()
+{
+ m_effectType->blockSignals(true);
+ m_effectType->setCurrentItem(DistortionFX::FishEye);
+ slotEffectTypeChanged(DistortionFX::FishEye);
+ m_effectType->blockSignals(false);
+}
+
+void ImageEffect_DistortionFX::slotEffectTypeChanged(int type)
+{
+ m_levelInput->setEnabled(true);
+ m_levelLabel->setEnabled(true);
+
+ m_levelInput->blockSignals(true);
+ m_iterationInput->blockSignals(true);
+ m_levelInput->setRange(0, 100, 1, true);
+ m_levelInput->setValue(25);
+
+ switch (type)
+ {
+ case DistortionFX::Twirl:
+ m_levelInput->setRange(-50, 50, 1, true);
+ m_levelInput->setValue(10);
+ break;
+
+ case DistortionFX::FishEye:
+ case DistortionFX::CilindricalHor:
+ case DistortionFX::CilindricalVert:
+ case DistortionFX::CilindricalHV:
+ case DistortionFX::Caricature:
+ m_levelInput->setRange(0, 200, 1, true);
+ m_levelInput->setValue(50);
+ break;
+
+ case DistortionFX::MultipleCorners:
+ m_levelInput->setRange(1, 10, 1, true);
+ m_levelInput->setValue(4);
+ break;
+
+ case DistortionFX::WavesHorizontal:
+ case DistortionFX::WavesVertical:
+ case DistortionFX::BlockWaves1:
+ case DistortionFX::BlockWaves2:
+ case DistortionFX::CircularWaves1:
+ case DistortionFX::CircularWaves2:
+ case DistortionFX::Tile:
+ m_iterationInput->setEnabled(true);
+ m_iterationLabel->setEnabled(true);
+ m_iterationInput->setRange(0, 200, 1, true);
+ m_iterationInput->setValue(10);
+ break;
+
+ case DistortionFX::PolarCoordinates:
+ case DistortionFX::UnpolarCoordinates:
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+ break;
+ }
+
+ m_levelInput->blockSignals(false);
+ m_iterationInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ImageEffect_DistortionFX::prepareEffect()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+ m_iterationInput->setEnabled(false);
+ m_iterationLabel->setEnabled(false);
+
+ int l = m_levelInput->value();
+ int f = m_iterationInput->value();
+ int e = m_effectType->currentItem();
+
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+
+ uchar *data = iface->getPreviewImage();
+ Digikam::DImg image(iface->previewWidth(), iface->previewHeight(), iface->previewSixteenBit(),
+ iface->previewHasAlpha(), data);
+ delete [] data;
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new DistortionFX(&image, this, e, l, f));
+}
+
+void ImageEffect_DistortionFX::prepareFinal()
+{
+ m_effectTypeLabel->setEnabled(false);
+ m_effectType->setEnabled(false);
+ m_levelInput->setEnabled(false);
+ m_levelLabel->setEnabled(false);
+ m_iterationInput->setEnabled(false);
+ m_iterationLabel->setEnabled(false);
+
+ int l = m_levelInput->value();
+ int f = m_iterationInput->value();
+ int e = m_effectType->currentItem();
+
+ Digikam::ImageIface iface(0, 0);
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new DistortionFX(iface.getOriginalImg(), this, e, l, f));
+}
+
+void ImageEffect_DistortionFX::putPreviewData(void)
+{
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage()
+ .smoothScale(iface->previewWidth(), iface->previewHeight());
+ iface->putPreviewImage(imDest.bits());
+
+ m_imagePreviewWidget->updatePreview();
+}
+
+void ImageEffect_DistortionFX::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Distortion Effects"),
+ m_threadedFilter->getTargetImage().bits());
+}
+
+} // NameSpace DigikamDistortionFXImagesPlugin
+
diff --git a/src/imageplugins/distortionfx/imageeffect_distortionfx.h b/src/imageplugins/distortionfx/imageeffect_distortionfx.h
new file mode 100644
index 00000000..652b372b
--- /dev/null
+++ b/src/imageplugins/distortionfx/imageeffect_distortionfx.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-11
+ * Description : a plugin to apply Distortion FX to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Distortion algorithms copyrighted 2004-2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_DISTORTIONFX_H
+#define IMAGEEFFECT_DISTORTIONFX_H
+
+// Digikam includes.
+
+#include "imageguidedlg.h"
+
+class TQComboBox;
+class TQLabel;
+
+class KIntNumInput;
+
+namespace DigikamDistortionFXImagesPlugin
+{
+
+class ImageEffect_DistortionFX : public Digikam::ImageGuideDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_DistortionFX(TQWidget *parent);
+ ~ImageEffect_DistortionFX();
+
+private slots:
+
+ void slotEffectTypeChanged(int type);
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQComboBox *m_effectType;
+
+ TQLabel *m_effectTypeLabel;
+ TQLabel *m_levelLabel;
+ TQLabel *m_iterationLabel;
+
+ KIntNumInput *m_levelInput;
+ KIntNumInput *m_iterationInput;
+};
+
+} // NameSpace DigikamDistortionFXImagesPlugin
+
+#endif /* IMAGEEFFECT_DISTORTIONFX_H */
diff --git a/src/imageplugins/distortionfx/imageplugin_distortionfx.cpp b/src/imageplugins/distortionfx/imageplugin_distortionfx.cpp
new file mode 100644
index 00000000..582e1b99
--- /dev/null
+++ b/src/imageplugins/distortionfx/imageplugin_distortionfx.cpp
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-11
+ * Description : a plugin to apply Distortion FX to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original Distortion algorithms copyrighted 2004-2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "distortionfxtool.h"
+#include "imageplugin_distortionfx.h"
+#include "imageplugin_distortionfx.moc"
+
+using namespace DigikamDistortionFXImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_distortionfx,
+ KGenericFactory<ImagePlugin_DistortionFX>("digikamimageplugin_distortionfx"));
+
+ImagePlugin_DistortionFX::ImagePlugin_DistortionFX(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_DistortionFX")
+{
+ m_distortionfxAction = new TDEAction(i18n("Distortion Effects..."), "distortionfx", 0,
+ this, TQ_SLOT(slotDistortionFX()),
+ actionCollection(), "imageplugin_distortionfx");
+
+ setXMLFile( "digikamimageplugin_distortionfx_ui.rc" );
+
+ DDebug() << "ImagePlugin_DistortionFX plugin loaded" << endl;
+}
+
+ImagePlugin_DistortionFX::~ImagePlugin_DistortionFX()
+{
+}
+
+void ImagePlugin_DistortionFX::setEnabledActions(bool enable)
+{
+ m_distortionfxAction->setEnabled(enable);
+}
+
+void ImagePlugin_DistortionFX::slotDistortionFX()
+{
+ DistortionFXTool *distortionfx = new DistortionFXTool(this);
+ loadTool(distortionfx);
+}
diff --git a/src/imageplugins/distortionfx/imageplugin_distortionfx.h b/src/imageplugins/distortionfx/imageplugin_distortionfx.h
new file mode 100644
index 00000000..2af33a14
--- /dev/null
+++ b/src/imageplugins/distortionfx/imageplugin_distortionfx.h
@@ -0,0 +1,59 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-11
+ * Description : a plugin to apply Distortion FX to an image.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original Distortion algorithms copyrighted 2004-2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_DISTORTIONFX_H
+#define IMAGEPLUGIN_DISTORTIONFX_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_DistortionFX : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_DistortionFX(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_DistortionFX();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotDistortionFX();
+
+private:
+
+ TDEAction *m_distortionfxAction;
+};
+
+#endif /* IMAGEPLUGIN_DISTORTIONFX_H */
diff --git a/src/imageplugins/emboss/Makefile.am b/src/imageplugins/emboss/Makefile.am
new file mode 100644
index 00000000..c595aa30
--- /dev/null
+++ b/src/imageplugins/emboss/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_emboss_la_SOURCES = imageplugin_emboss.cpp \
+ embosstool.cpp emboss.cpp
+
+digikamimageplugin_emboss_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_emboss_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_emboss.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_emboss.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_emboss_ui.rc
+
diff --git a/src/imageplugins/emboss/digikamimageplugin_emboss.desktop b/src/imageplugins/emboss/digikamimageplugin_emboss.desktop
new file mode 100644
index 00000000..414f235b
--- /dev/null
+++ b/src/imageplugins/emboss/digikamimageplugin_emboss.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Name=ImagePlugin_Emboss
+Name[bg]=Приставка за снимки - Релеф
+Name[da]=Billedplugin_Præg i relief
+Name[el]=ΠρόσθετοΕικόνας_Εμβάθυνση
+Name[fi]=Kohokuvio
+Name[hr]=Reljef
+Name[it]=PluginImmagini_Rilievo
+Name[nl]=Afbeeldingsplugin_Reliëf
+Name[sr]=Рељеф
+Name[sr@Latn]=Reljef
+Name[sv]=Insticksprogram för reliefeffekt
+Name[tr]=ResimEklentisi_Kabart
+Name[xx]=xxImagePlugin_Embossxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Emboss image effect plugin for digiKam
+Comment[bg]=Приставка на digiKam за добавяне на релеф към снимки
+Comment[ca]=Connector pel digiKam d'efecte d'imatge de relleu
+Comment[cs]=Efektový modul pro tvorbu reliéfu pro digiKam
+Comment[da]=Reliefprægnings-plugin for Digikam
+Comment[de]=digiKam-Modul zum Erzeugen eines Gravureffektes
+Comment[el]=Πρόσθετο εφέ εμβάθυνσης για το digiKam
+Comment[es]=Plugin para digiKam con efectos de bajo relieve
+Comment[et]=DigiKami kohrutuse pildiefektiplugin
+Comment[fa]=برجسته کردن وصلۀ جلوۀ تصویر برای digiKam
+Comment[fi]=Kohokuvioefekti kohteiden ääriviivoista
+Comment[gl]=Un plugin de digiKam para dar-lle relevo á imaxe
+Comment[hr]=digiKam dodatak za efekt reljefa
+Comment[is]=Íforrit fyrir digiKam sem framkallar upphleypingaráhrif
+Comment[it]=Plugin di effetto di rilievo delle immagini per digiKam
+Comment[ja]=digiKam エンボス効果プラグイン
+Comment[nds]=digiKam-Moduul för Ingraav-Effekten
+Comment[nl]=Digikam-plugin voor reliëf-afbeeldingen
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਈਮਬੋਸ ਚਿੱਤਰ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam oferująca efekty zniekształceń
+Comment[pt]=Um 'plugin' do digiKam para gravar em relevo a imagem
+Comment[pt_BR]=Plugin de efeito de estampa
+Comment[ru]=Модуль рельефного рисунка для digiKam
+Comment[sk]=digiKam plugin pre efekt reliéfu
+Comment[sr]=digiKam-ов прикључак за ефекат рељефа на сликама
+Comment[sr@Latn]=digiKam-ov priključak za efekat reljefa na slikama
+Comment[sv]=Digikam insticksprogram för reliefbildeffekt
+Comment[tr]=digiKam için resim kabartma etkisi eklentisi
+Comment[uk]=Втулок створення ефекту барельєфу для digiKam
+Comment[vi]=Phần bổ sung hiệu ứng chạm nổi ảnh cho digiKam
+Comment[xx]=xxEmboss image effect plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_emboss
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/emboss/digikamimageplugin_emboss_ui.rc b/src/imageplugins/emboss/digikamimageplugin_emboss_ui.rc
new file mode 100644
index 00000000..1a6943c6
--- /dev/null
+++ b/src/imageplugins/emboss/digikamimageplugin_emboss_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_emboss" >
+
+ <MenuBar>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_emboss" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_emboss" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/emboss/emboss.cpp b/src/imageplugins/emboss/emboss.cpp
new file mode 100644
index 00000000..d4225148
--- /dev/null
+++ b/src/imageplugins/emboss/emboss.cpp
@@ -0,0 +1,127 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Emboss threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Emboss algorithm copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "emboss.h"
+
+namespace DigikamEmbossImagesPlugin
+{
+
+Emboss::Emboss(Digikam::DImg *orgImage, TQObject *parent, int depth)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "Emboss")
+{
+ m_depth = depth;
+ initFilter();
+}
+
+void Emboss::filterImage(void)
+{
+ embossImage(&m_orgImage, &m_destImage, m_depth);
+}
+
+// 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 Emboss::embossImage(Digikam::DImg *orgImage, Digikam::DImg *destImage, int d)
+{
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ uchar* data = orgImage->bits();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar* Bits = destImage->bits();
+
+ // Initial copy
+ memcpy (Bits, data, destImage->numBytes());
+
+ double Depth = d / 10.0;
+
+ int progress;
+ int red, green, blue, gray;
+ Digikam::DColor color, colorOther;
+ int offset, offsetOther;
+
+ for (int h = 0 ; !m_cancel && (h < Height) ; h++)
+ {
+ for (int w = 0 ; !m_cancel && (w < Width) ; w++)
+ {
+ offset = getOffset(Width, w, h, bytesDepth);
+ offsetOther = getOffset(Width, w + Lim_Max (w, 1, Width), h + Lim_Max (h, 1, Height), bytesDepth);
+
+ color.setColor(Bits + offset, sixteenBit);
+ colorOther.setColor(Bits + offsetOther, sixteenBit);
+
+ if (sixteenBit)
+ {
+ red = abs ((int)((color.red() - colorOther.red()) * Depth + 32768));
+ green = abs ((int)((color.green() - colorOther.green()) * Depth + 32768));
+ blue = abs ((int)((color.blue() - colorOther.blue()) * Depth + 32768));
+
+ gray = CLAMP065535 ((red + green + blue) / 3);
+ }
+ else
+ {
+ red = abs ((int)((color.red() - colorOther.red()) * Depth + 128));
+ green = abs ((int)((color.green() - colorOther.green()) * Depth + 128));
+ blue = abs ((int)((color.blue() - colorOther.blue()) * Depth + 128));
+
+ gray = CLAMP0255 ((red + green + blue) / 3);
+ }
+
+ // Overwrite RGB values to destination. Alpha remains unchanged.
+ color.setRed(gray);
+ color.setGreen(gray);
+ color.setBlue(gray);
+ color.setPixel(Bits + offset);
+ }
+
+ progress = (int) (((double)h * 100.0) / Height);
+ if ( progress%5 == 0 )
+ postProgress( progress );
+ }
+}
+
+} // NameSpace DigikamEmbossImagesPlugin
diff --git a/src/imageplugins/emboss/emboss.h b/src/imageplugins/emboss/emboss.h
new file mode 100644
index 00000000..470755a6
--- /dev/null
+++ b/src/imageplugins/emboss/emboss.h
@@ -0,0 +1,75 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Emboss threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original Emboss algorithm copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef EMBOSS_H
+#define EMBOSS_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamEmbossImagesPlugin
+{
+
+class Emboss : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ Emboss(Digikam::DImg *orgImage, TQObject *parent=0, int depth=30);
+ ~Emboss(){};
+
+private:
+
+ virtual void filterImage(void);
+
+
+ void embossImage(Digikam::DImg *orgImage, Digikam::DImg *destImage, int d);
+
+ // Function to limit the max and min values defined by the developer.
+
+ inline int Lim_Max (int Now, int Up, int Max)
+ {
+ --Max;
+ while (Now > Max - Up)
+ --Up;
+ return (Up);
+ };
+
+ inline int getOffset(int Width, int X, int Y, int bytesDepth)
+ {
+ return (Y * Width * bytesDepth) + (X * bytesDepth);
+ };
+
+private:
+
+ int m_depth;
+};
+
+} // NameSpace DigikamEmbossImagesPlugin
+
+#endif /* EMBOSS_H */
diff --git a/src/imageplugins/emboss/embosstool.cpp b/src/imageplugins/emboss/embosstool.cpp
new file mode 100644
index 00000000..f16ef4de
--- /dev/null
+++ b/src/imageplugins/emboss/embosstool.cpp
@@ -0,0 +1,167 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin to emboss
+ * an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "emboss.h"
+#include "embosstool.h"
+#include "embosstool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamEmbossImagesPlugin
+{
+
+EmbossTool::EmbossTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("emboss");
+ setToolName(i18n("Emboss"));
+ setToolIcon(SmallIcon("embosstool"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::PanIcon);
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 2, 1);
+ TQLabel *label1 = new TQLabel(i18n("Depth:"), m_gboxSettings->plainPage());
+
+ m_depthInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_depthInput->setRange(10, 300, 1);
+ m_depthInput->setDefaultValue(30);
+ TQWhatsThis::add( m_depthInput, i18n("<p>Set here the depth of the embossing image effect.") );
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 1);
+ grid->addMultiCellWidget(m_depthInput, 1, 1, 0, 1);
+ grid->setRowStretch(2, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "emboss Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_depthInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+EmbossTool::~EmbossTool()
+{
+}
+
+void EmbossTool::renderingFinished()
+{
+ m_depthInput->setEnabled(true);
+}
+
+void EmbossTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("emboss Tool");
+ m_depthInput->blockSignals(true);
+ m_depthInput->setValue(config->readNumEntry("DepthAjustment", m_depthInput->defaultValue()));
+ m_depthInput->blockSignals(false);
+}
+
+void EmbossTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("emboss Tool");
+ config->writeEntry("DepthAjustment", m_depthInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void EmbossTool::slotResetSettings()
+{
+ m_depthInput->blockSignals(true);
+ m_depthInput->slotReset();
+ m_depthInput->blockSignals(false);
+}
+
+void EmbossTool::prepareEffect()
+{
+ m_depthInput->setEnabled(false);
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+ int depth = m_depthInput->value();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Emboss(&image, this, depth)));
+}
+
+void EmbossTool::prepareFinal()
+{
+ m_depthInput->setEnabled(false);
+
+ int depth = m_depthInput->value();
+ ImageIface iface(0, 0);
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Emboss(iface.getOriginalImg(), this, depth)));
+}
+
+void EmbossTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void EmbossTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Emboss"), filter()->getTargetImage().bits());
+}
+
+} // NameSpace DigikamEmbossImagesPlugin
diff --git a/src/imageplugins/emboss/embosstool.h b/src/imageplugins/emboss/embosstool.h
new file mode 100644
index 00000000..224858f7
--- /dev/null
+++ b/src/imageplugins/emboss/embosstool.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin to emboss
+ * an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef EMBOSSTOOL_H
+#define EMBOSSTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamEmbossImagesPlugin
+{
+
+class EmbossTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ EmbossTool(TQObject* parent);
+ ~EmbossTool();
+
+private slots:
+
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KDcrawIface::RIntNumInput *m_depthInput;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamEmbossImagesPlugin
+
+#endif /* EMBOSSTOOL_H */
diff --git a/src/imageplugins/emboss/imageeffect_emboss.cpp b/src/imageplugins/emboss/imageeffect_emboss.cpp
new file mode 100644
index 00000000..b4557c80
--- /dev/null
+++ b/src/imageplugins/emboss/imageeffect_emboss.cpp
@@ -0,0 +1,170 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin to emboss
+ * an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "version.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "emboss.h"
+#include "imageeffect_emboss.h"
+#include "imageeffect_emboss.moc"
+
+namespace DigikamEmbossImagesPlugin
+{
+
+ImageEffect_Emboss::ImageEffect_Emboss(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Emboss Image"), "emboss", false, false, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Emboss Image"),
+ digikam_version,
+ I18N_NOOP("Emboss image effect plugin for digiKam."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2006, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Pieter Z. Voloshyn", I18N_NOOP("Emboss algorithm"),
+ "pieter dot voloshyn at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 1, 1, 0, spacingHint());
+ TQLabel *label1 = new TQLabel(i18n("Depth:"), gboxSettings);
+
+ m_depthInput = new KIntNumInput(gboxSettings);
+ m_depthInput->setRange(10, 300, 1, true);
+ TQWhatsThis::add( m_depthInput, i18n("<p>Set here the depth of the embossing image effect.") );
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_depthInput, 1, 1, 0, 1);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_depthInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_Emboss::~ImageEffect_Emboss()
+{
+}
+
+void ImageEffect_Emboss::renderingFinished()
+{
+ m_depthInput->setEnabled(true);
+}
+
+void ImageEffect_Emboss::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("emboss Tool Dialog");
+ m_depthInput->blockSignals(true);
+ m_depthInput->setValue(config->readNumEntry("DepthAjustment", 30));
+ m_depthInput->blockSignals(false);
+}
+
+void ImageEffect_Emboss::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("emboss Tool Dialog");
+ config->writeEntry("DepthAjustment", m_depthInput->value());
+ config->sync();
+}
+
+void ImageEffect_Emboss::resetValues()
+{
+ m_depthInput->blockSignals(true);
+ m_depthInput->setValue(30);
+ m_depthInput->blockSignals(false);
+}
+
+void ImageEffect_Emboss::prepareEffect()
+{
+ m_depthInput->setEnabled(false);
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+
+ int depth = m_depthInput->value();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new Emboss(&image, this, depth));
+}
+
+void ImageEffect_Emboss::prepareFinal()
+{
+ m_depthInput->setEnabled(false);
+
+ int depth = m_depthInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new Emboss(iface.getOriginalImg(), this, depth));
+}
+
+void ImageEffect_Emboss::putPreviewData(void)
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_Emboss::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Emboss"),
+ m_threadedFilter->getTargetImage().bits());
+}
+
+} // NameSpace DigikamEmbossImagesPlugin
+
diff --git a/src/imageplugins/emboss/imageeffect_emboss.h b/src/imageplugins/emboss/imageeffect_emboss.h
new file mode 100644
index 00000000..19cf4f77
--- /dev/null
+++ b/src/imageplugins/emboss/imageeffect_emboss.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin to emboss
+ * an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_EMBOSS_H
+#define IMAGEEFFECT_EMBOSS_H
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+class KIntNumInput;
+
+namespace DigikamEmbossImagesPlugin
+{
+
+class ImageEffect_Emboss : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Emboss(TQWidget* parent);
+ ~ImageEffect_Emboss();
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KIntNumInput *m_depthInput;
+};
+
+} // NameSpace DigikamEmbossImagesPlugin
+
+#endif /* IMAGEEFFECT_EMBOSS_H */
diff --git a/src/imageplugins/emboss/imageplugin_emboss.cpp b/src/imageplugins/emboss/imageplugin_emboss.cpp
new file mode 100644
index 00000000..6bd616d6
--- /dev/null
+++ b/src/imageplugins/emboss/imageplugin_emboss.cpp
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin to emboss
+ * an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "embosstool.h"
+#include "imageplugin_emboss.h"
+#include "imageplugin_emboss.moc"
+
+using namespace DigikamEmbossImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_emboss,
+ KGenericFactory<ImagePlugin_Emboss>("digikamimageplugin_emboss"));
+
+ImagePlugin_Emboss::ImagePlugin_Emboss(TQObject *parent, const char*,
+ const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_Emboss")
+{
+ m_embossAction = new TDEAction(i18n("Emboss..."), "embosstool", 0,
+ this, TQ_SLOT(slotEmboss()),
+ actionCollection(), "imageplugin_emboss");
+
+ setXMLFile( "digikamimageplugin_emboss_ui.rc" );
+
+ DDebug() << "ImagePlugin_Emboss plugin loaded" << endl;
+}
+
+ImagePlugin_Emboss::~ImagePlugin_Emboss()
+{
+}
+
+void ImagePlugin_Emboss::setEnabledActions(bool enable)
+{
+ m_embossAction->setEnabled(enable);
+}
+
+void ImagePlugin_Emboss::slotEmboss()
+{
+ EmbossTool *tool = new EmbossTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/emboss/imageplugin_emboss.h b/src/imageplugins/emboss/imageplugin_emboss.h
new file mode 100644
index 00000000..1ccac064
--- /dev/null
+++ b/src/imageplugins/emboss/imageplugin_emboss.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin to emboss
+ * an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_EMBOSS_H
+#define IMAGEPLUGIN_EMBOSS_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_Emboss : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_Emboss(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_Emboss();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotEmboss();
+
+private:
+
+ TDEAction *m_embossAction;
+};
+
+#endif /* IMAGEPLUGIN_EMBOSS_H */
diff --git a/src/imageplugins/filmgrain/Makefile.am b/src/imageplugins/filmgrain/Makefile.am
new file mode 100644
index 00000000..c23c9d8e
--- /dev/null
+++ b/src/imageplugins/filmgrain/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_filmgrain_la_SOURCES = imageplugin_filmgrain.cpp \
+ filmgraintool.cpp filmgrain.cpp
+
+digikamimageplugin_filmgrain_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_filmgrain_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_filmgrain.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_filmgrain.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_filmgrain_ui.rc
+
diff --git a/src/imageplugins/filmgrain/digikamimageplugin_filmgrain.desktop b/src/imageplugins/filmgrain/digikamimageplugin_filmgrain.desktop
new file mode 100644
index 00000000..5ad6582b
--- /dev/null
+++ b/src/imageplugins/filmgrain/digikamimageplugin_filmgrain.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_FilmGrain
+Name[bg]=Приставка за снимки - Филмово зърно
+Name[da]=Billedplugin_Filmkorn
+Name[el]=ΠρόσθετοΕικόνας_ΚόκκοςΦιλμ
+Name[fi]=Filmirakeet
+Name[hr]=Zrnatost
+Name[it]=PluginImmagini_GranaPellicola
+Name[nl]=Afbeeldingsplugin_Filmkorrel
+Name[sr]=Зрнаст филм
+Name[sr@Latn]=Zrnast film
+Name[sv]=Insticksprogram för filmkorn
+Name[tr]=ResimEklentisi_FilmTanecikleri
+Name[xx]=xxImagePlugin_FilmGrainxx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Film grain image effect plugin for digiKam
+Comment[bg]=Приставка на digiKam за наподобяване на филмово зърно
+Comment[ca]=Connector pel digiKam d'efecte d'imatge de gra de pel·lícula
+Comment[cs]=Efektový modul pro tvorbu filmového zrna pro digiKam
+Comment[da]=Plugin til filmkorn-effekt på billeder i Digikam
+Comment[de]=digiKam-Modul zum Erzeugen eines Effektes von körnigem Film
+Comment[el]=Πρόσθετο εφέ κόκκου φιλμ για το digiKam
+Comment[es]=Plugin para digiKam de efectos de imagen tipo grano fino de película
+Comment[et]=DigiKami teralisuse pildiefektiplugin
+Comment[fa]=وصلۀ جلوۀ تصویر خرده فیلم برای digiKam
+Comment[fi]=Filmikuvien rakeisuuden jäljittelijä
+Comment[gl]=Un plugin de digiKam para o efeito de grao de filme
+Comment[hr]=digiKam dodatak za efekt zrnatosti filma
+Comment[is]=Íforrit fyrir digiKam sem líkir eftir filmukornum
+Comment[it]=Plugin per l'effetto di grana della pellicola delle immagini per digiKam
+Comment[ja]=digiKam フィルム粒子効果プラグイン
+Comment[nds]=digiKam-Moduul för Effekten vun körnig Film
+Comment[nl]=Digikam-plugin voor filmkorrel
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਫਿਲਮ ਗਰੇਨ ਚਿੱਤਰ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam oferująca efekty zniekształceń
+Comment[pt]=Um 'plugin' do digiKam para o efeito de grão de filme
+Comment[pt_BR]=Um 'plugin' do digiKam para o efeito de grão de filme
+Comment[ru]=Модуль зернистости изображения для digiKam
+Comment[sk]=digiKam obrázkový plugin pre efekt filmového zrna
+Comment[sr]=digiKam-ов прикључак за ефекат зрнастости филма
+Comment[sr@Latn]=digiKam-ov priključak za efekat zrnastosti filma
+Comment[sv]=Digikam insticksprogram för filmkornsbildeffekt
+Comment[tr]=digiKam için film tanecikleri etkisi eklentisi
+Comment[uk]=Втулок digiKam для створення ефекту фільму на зображеннях
+Comment[vi]=Phần bổ sung hiệu ứng chạm mịn mặt màng ảnh cho digiKam
+Comment[xx]=xxFilm grain image effect plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_filmgrain
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/filmgrain/digikamimageplugin_filmgrain_ui.rc b/src/imageplugins/filmgrain/digikamimageplugin_filmgrain_ui.rc
new file mode 100644
index 00000000..770c2dbd
--- /dev/null
+++ b/src/imageplugins/filmgrain/digikamimageplugin_filmgrain_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_filmgrain" >
+
+ <MenuBar>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_filmgrain" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_filmgrain" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/filmgrain/filmgrain.cpp b/src/imageplugins/filmgrain/filmgrain.cpp
new file mode 100644
index 00000000..57616eb9
--- /dev/null
+++ b/src/imageplugins/filmgrain/filmgrain.cpp
@@ -0,0 +1,202 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : FilmGrain threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqdatetime.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimggaussianblur.h"
+#include "imagecurves.h"
+#include "imagehistogram.h"
+#include "dimgimagefilters.h"
+#include "filmgrain.h"
+
+namespace DigikamFilmGrainImagesPlugin
+{
+
+FilmGrain::FilmGrain(Digikam::DImg *orgImage, TQObject *parent, int sensibility)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "FilmGrain")
+{
+ m_sensibility = sensibility;
+ initFilter();
+}
+
+void FilmGrain::filterImage(void)
+{
+ filmgrainImage(&m_orgImage, m_sensibility);
+}
+
+// This method is based on the Simulate Film grain tutorial from GimpGuru.org web site
+// available at this url : http://www.gimpguru.org/Tutorials/FilmGrain
+
+void FilmGrain::filmgrainImage(Digikam::DImg *orgImage, int Sensibility)
+{
+ // Sensibility: 800..6400
+
+ if (Sensibility <= 0) return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ int bytesDepth = orgImage->bytesDepth();
+ bool sixteenBit = orgImage->sixteenBit();
+ uchar* data = orgImage->bits();
+
+ Digikam::DImg grain(Width, Height, sixteenBit); // Grain blured without curves adjustment.
+ Digikam::DImg mask(Width, Height, sixteenBit); // Grain mask with curves adjustment.
+ uchar* pGrainBits = grain.bits();
+ uchar* pMaskBits = mask.bits();
+ uchar* pOutBits = m_destImage.bits(); // Destination image with merged grain mask and original.
+
+ int Noise, Shade, nRand, component, progress;
+ uchar *ptr;
+ Digikam::DColor blendData, grainData, maskData, outData;
+
+ if (sixteenBit)
+ Noise = (Sensibility / 10 + 1) * 256 - 1;
+ else
+ Noise = Sensibility / 10;
+
+ // This value controls the shading pixel effect between original image and grain mask.
+ if (sixteenBit)
+ Shade = (52 + 1) * 256 - 1;
+ else
+ Shade = 52;
+
+ TQDateTime dt = TQDateTime::currentDateTime();
+ TQDateTime Y2000( TQDate(2000, 1, 1), TQTime(0, 0, 0) );
+ uint seed = (uint) dt.secsTo(Y2000);
+
+ // Make gray grain mask.
+
+ grainData.setSixteenBit(sixteenBit);
+
+ for (int x = 0; !m_cancel && x < Width; x++)
+ {
+ for (int y = 0; !m_cancel && y < Height; y++)
+ {
+ ptr = pGrainBits + x*bytesDepth + (y*Width*bytesDepth);
+
+ nRand = (rand_r(&seed) % Noise) - (Noise / 2);
+ if (sixteenBit)
+ component = CLAMP(32768 + nRand, 0, 65535);
+ else
+ component = CLAMP(128 + nRand, 0, 255);
+
+ grainData.setRed (component);
+ grainData.setGreen(component);
+ grainData.setBlue (component);
+ grainData.setAlpha(0);
+
+ grainData.setPixel(ptr);
+ }
+
+ // Update progress bar in dialog.
+ progress = (int) (((double)x * 25.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress( progress );
+ }
+
+ // Smooth grain mask using gaussian blur with radius 1.
+ Digikam::DImgGaussianBlur(this, grain, grain, 25, 30, 1);
+
+ // Normally, film grain tends to be most noticeable in the midtones, and much less
+ // so in the shadows and highlights. Adjust histogram curve to adjust grain like this.
+
+ Digikam::ImageCurves *grainCurves = new Digikam::ImageCurves(sixteenBit);
+
+ // We modify only global luminosity of the grain.
+ if (sixteenBit)
+ {
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 0, TQPoint(0, 0));
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 8, TQPoint(32768, 32768));
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 16, TQPoint(65535, 0));
+ }
+ else
+ {
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 0, TQPoint(0, 0));
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 8, TQPoint(128, 128));
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 16, TQPoint(255, 0));
+ }
+
+ // Calculate curves and lut to apply on grain.
+ grainCurves->curvesCalculateCurve(Digikam::ImageHistogram::ValueChannel);
+ grainCurves->curvesLutSetup(Digikam::ImageHistogram::AlphaChannel);
+ grainCurves->curvesLutProcess(pGrainBits, pMaskBits, Width, Height);
+
+ grain.reset();
+ delete grainCurves;
+
+ // Update progress bar in dialog.
+ postProgress( 40 );
+
+ // Merge src image with grain using shade coefficient.
+
+ int alpha;
+ // get composer for default blending
+ Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(Digikam::DColorComposer::PorterDuffNone);
+
+ for (int x = 0; !m_cancel && x < Width; x++)
+ {
+ for (int y = 0; !m_cancel && y < Height; y++)
+ {
+ int offset = x*bytesDepth + (y*Width*bytesDepth);
+
+ // read color from orig image
+ blendData.setColor(data + offset, sixteenBit);
+ // read color from mask
+ maskData.setColor(pMaskBits + offset, sixteenBit);
+ // set shade as alpha value - it will be used as source alpha when blending
+ maskData.setAlpha(Shade);
+
+ // compose, write result to blendData.
+ // Preserve alpha, do not blend it (taken from old algorithm - correct?)
+ alpha = blendData.alpha();
+ composer->compose(blendData, maskData);
+ blendData.setAlpha(alpha);
+
+ // write to destination
+ blendData.setPixel(pOutBits + offset);
+ }
+
+ // Update progress bar in dialog.
+ progress = (int) (50.0 + ((double)x * 50.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress( progress );
+ }
+
+ delete composer;
+}
+
+} // NameSpace DigikamFilmGrainImagesPlugin
diff --git a/src/imageplugins/filmgrain/filmgrain.h b/src/imageplugins/filmgrain/filmgrain.h
new file mode 100644
index 00000000..42bcf03c
--- /dev/null
+++ b/src/imageplugins/filmgrain/filmgrain.h
@@ -0,0 +1,58 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : FilmGrain threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+
+#ifndef FILMGRAIN_H
+#define FILMGRAIN_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamFilmGrainImagesPlugin
+{
+
+class FilmGrain : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ FilmGrain(Digikam::DImg *orgImage, TQObject *parent=0, int sensibility=12);
+
+ ~FilmGrain(){};
+
+private:
+
+ virtual void filterImage(void);
+
+ void filmgrainImage(Digikam::DImg *orgImage, int Sensibility);
+
+private:
+
+ int m_sensibility;
+};
+
+} // NameSpace DigikamFilmGrainImagesPlugin
+
+#endif /* FILMGRAIN_H */
diff --git a/src/imageplugins/filmgrain/filmgraintool.cpp b/src/imageplugins/filmgrain/filmgraintool.cpp
new file mode 100644
index 00000000..5799d814
--- /dev/null
+++ b/src/imageplugins/filmgrain/filmgraintool.cpp
@@ -0,0 +1,195 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin for add film
+ * grain on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlcdnumber.h>
+#include <tqslider.h>
+#include <tqlayout.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "filmgrain.h"
+#include "filmgraintool.h"
+#include "filmgraintool.moc"
+
+using namespace Digikam;
+
+namespace DigikamFilmGrainImagesPlugin
+{
+
+FilmGrainTool::FilmGrainTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("filmgrain");
+ setToolName(i18n("Film Grain"));
+ setToolIcon(SmallIcon("filmgrain"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 2, 1);
+ TQLabel *label1 = new TQLabel(i18n("Sensitivity (ISO):"), m_gboxSettings->plainPage());
+
+ m_sensibilitySlider = new TQSlider(2, 30, 1, 12, TQt::Horizontal, m_gboxSettings->plainPage());
+ m_sensibilitySlider->setTracking(false);
+ m_sensibilitySlider->setTickInterval(1);
+ m_sensibilitySlider->setTickmarks(TQSlider::Below);
+
+ m_sensibilityLCDValue = new TQLCDNumber(4, m_gboxSettings->plainPage());
+ m_sensibilityLCDValue->setSegmentStyle(TQLCDNumber::Flat);
+ m_sensibilityLCDValue->display(TQString::number(2400));
+ TQString whatsThis = i18n("<p>Set here the film ISO-sensitivity to "
+ "use for simulating the film graininess.");
+
+ TQWhatsThis::add(m_sensibilityLCDValue, whatsThis);
+ TQWhatsThis::add(m_sensibilitySlider, whatsThis);
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 1);
+ grid->addMultiCellWidget(m_sensibilitySlider, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_sensibilityLCDValue, 1, 1, 1, 1);
+ grid->setRowStretch(2, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "filmgrain Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect( m_sensibilitySlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()) );
+
+ // this connection is necessary to change the LCD display when
+ // the value is changed by single clicking on the slider
+ connect( m_sensibilitySlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotSliderMoved(int)) );
+
+ connect( m_sensibilitySlider, TQ_SIGNAL(sliderMoved(int)),
+ this, TQ_SLOT(slotSliderMoved(int)) );
+}
+
+FilmGrainTool::~FilmGrainTool()
+{
+}
+
+void FilmGrainTool::renderingFinished()
+{
+ m_sensibilitySlider->setEnabled(true);
+}
+
+void FilmGrainTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("filmgrain Tool");
+ m_sensibilitySlider->blockSignals(true);
+ m_sensibilitySlider->setValue(config->readNumEntry("SensitivityAjustment", 12));
+ m_sensibilitySlider->blockSignals(false);
+ slotSliderMoved(m_sensibilitySlider->value());
+}
+
+void FilmGrainTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("filmgrain Tool");
+ config->writeEntry("SensitivityAjustment", m_sensibilitySlider->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void FilmGrainTool::slotResetSettings()
+{
+ m_sensibilitySlider->blockSignals(true);
+ m_sensibilitySlider->setValue(12);
+ m_sensibilitySlider->blockSignals(false);
+}
+
+void FilmGrainTool::slotSliderMoved(int v)
+{
+ m_sensibilityLCDValue->display( TQString::number(400+200*v) );
+}
+
+void FilmGrainTool::prepareEffect()
+{
+ m_sensibilitySlider->setEnabled(false);
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+ int s = 400 + 200 * m_sensibilitySlider->value();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new FilmGrain(&image, this, s)));
+}
+
+void FilmGrainTool::prepareFinal()
+{
+ m_sensibilitySlider->setEnabled(false);
+
+ int s = 400 + 200 * m_sensibilitySlider->value();
+
+ ImageIface iface(0, 0);
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new FilmGrain(iface.getOriginalImg(), this, s)));
+}
+
+void FilmGrainTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void FilmGrainTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Film Grain"), filter()->getTargetImage().bits());
+}
+
+} // NameSpace DigikamFilmGrainImagesPlugin
diff --git a/src/imageplugins/filmgrain/filmgraintool.h b/src/imageplugins/filmgrain/filmgraintool.h
new file mode 100644
index 00000000..1a179b53
--- /dev/null
+++ b/src/imageplugins/filmgrain/filmgraintool.h
@@ -0,0 +1,83 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin for add film
+ * grain on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef FILMGRAINTOOL_H
+#define FILMGRAINTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQSlider;
+class TQLCDNumber;
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamFilmGrainImagesPlugin
+{
+
+class FilmGrainTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ FilmGrainTool(TQObject* parent);
+ ~FilmGrainTool();
+
+private slots:
+
+ void slotSliderMoved(int);
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQSlider *m_sensibilitySlider;
+
+ TQLCDNumber *m_sensibilityLCDValue;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamFilmGrainImagesPlugin
+
+#endif /* FILMGRAINTOOL_H */
diff --git a/src/imageplugins/filmgrain/imageeffect_filmgrain.cpp b/src/imageplugins/filmgrain/imageeffect_filmgrain.cpp
new file mode 100644
index 00000000..e008095a
--- /dev/null
+++ b/src/imageplugins/filmgrain/imageeffect_filmgrain.cpp
@@ -0,0 +1,195 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin for add film
+ * grain on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlcdnumber.h>
+#include <tqslider.h>
+#include <tqlayout.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "filmgrain.h"
+#include "imageeffect_filmgrain.h"
+#include "imageeffect_filmgrain.moc"
+
+namespace DigikamFilmGrainImagesPlugin
+{
+
+ImageEffect_FilmGrain::ImageEffect_FilmGrain(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Add Film Grain to Photograph"),
+ "filmgrain", false, false, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Film Grain"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to apply a film grain "
+ "effect to an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2005, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 1, 1, 0, spacingHint());
+ TQLabel *label1 = new TQLabel(i18n("Sensitivity (ISO):"), gboxSettings);
+
+ m_sensibilitySlider = new TQSlider(2, 30, 1, 12, TQt::Horizontal, gboxSettings);
+ m_sensibilitySlider->setTracking ( false );
+ m_sensibilitySlider->setTickInterval(1);
+ m_sensibilitySlider->setTickmarks(TQSlider::Below);
+
+ m_sensibilityLCDValue = new TQLCDNumber (4, gboxSettings);
+ m_sensibilityLCDValue->setSegmentStyle ( TQLCDNumber::Flat );
+ m_sensibilityLCDValue->display( TQString::number(2400) );
+ whatsThis = i18n("<p>Set here the film ISO-sensitivity to use for simulating the film graininess.");
+
+ TQWhatsThis::add( m_sensibilityLCDValue, whatsThis);
+ TQWhatsThis::add( m_sensibilitySlider, whatsThis);
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_sensibilitySlider, 1, 1, 0, 0);
+ gridSettings->addMultiCellWidget(m_sensibilityLCDValue, 1, 1, 1, 1);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect( m_sensibilitySlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()) );
+
+ // this connection is necessary to change the LCD display when
+ // the value is changed by single clicking on the slider
+ connect( m_sensibilitySlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotSliderMoved(int)) );
+
+ connect( m_sensibilitySlider, TQ_SIGNAL(sliderMoved(int)),
+ this, TQ_SLOT(slotSliderMoved(int)) );
+}
+
+ImageEffect_FilmGrain::~ImageEffect_FilmGrain()
+{
+}
+
+void ImageEffect_FilmGrain::renderingFinished()
+{
+ m_sensibilitySlider->setEnabled(true);
+}
+
+void ImageEffect_FilmGrain::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("filmgrain Tool Dialog");
+ m_sensibilitySlider->blockSignals(true);
+ m_sensibilitySlider->setValue(config->readNumEntry("SensitivityAjustment", 12));
+ m_sensibilitySlider->blockSignals(false);
+ slotSliderMoved(m_sensibilitySlider->value());
+}
+
+void ImageEffect_FilmGrain::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("filmgrain Tool Dialog");
+ config->writeEntry("SensitivityAjustment", m_sensibilitySlider->value());
+ config->sync();
+}
+
+void ImageEffect_FilmGrain::resetValues()
+{
+ m_sensibilitySlider->blockSignals(true);
+ m_sensibilitySlider->setValue(12);
+ m_sensibilitySlider->blockSignals(false);
+}
+
+void ImageEffect_FilmGrain::slotSliderMoved(int v)
+{
+ m_sensibilityLCDValue->display( TQString::number(400+200*v) );
+}
+
+void ImageEffect_FilmGrain::prepareEffect()
+{
+ m_sensibilitySlider->setEnabled(false);
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+ int s = 400 + 200 * m_sensibilitySlider->value();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new FilmGrain(&image, this, s));
+}
+
+void ImageEffect_FilmGrain::prepareFinal()
+{
+ m_sensibilitySlider->setEnabled(false);
+
+ int s = 400 + 200 * m_sensibilitySlider->value();
+
+ Digikam::ImageIface iface(0, 0);
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new FilmGrain(iface.getOriginalImg(), this, s));
+}
+
+void ImageEffect_FilmGrain::putPreviewData(void)
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_FilmGrain::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Film Grain"), m_threadedFilter->getTargetImage().bits());
+}
+
+} // NameSpace DigikamFilmGrainImagesPlugin
+
diff --git a/src/imageplugins/filmgrain/imageeffect_filmgrain.h b/src/imageplugins/filmgrain/imageeffect_filmgrain.h
new file mode 100644
index 00000000..ba66e0a2
--- /dev/null
+++ b/src/imageplugins/filmgrain/imageeffect_filmgrain.h
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-26
+ * Description : a digiKam image editor plugin for add film
+ * grain on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+
+#ifndef IMAGEEFFECT_FILMGRAIN_H
+#define IMAGEEFFECT_FILMGRAIN_H
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+class TQSlider;
+class TQLCDNumber;
+
+namespace DigikamFilmGrainImagesPlugin
+{
+
+class ImageEffect_FilmGrain : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_FilmGrain(TQWidget* parent);
+ ~ImageEffect_FilmGrain();
+
+private slots:
+
+ void slotSliderMoved(int);
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQSlider *m_sensibilitySlider;
+
+ TQLCDNumber *m_sensibilityLCDValue;
+};
+
+} // NameSpace DigikamFilmGrainImagesPlugin
+
+#endif /* IMAGEEFFECT_FILMGRAIN_H */
diff --git a/src/imageplugins/filmgrain/imageplugin_filmgrain.cpp b/src/imageplugins/filmgrain/imageplugin_filmgrain.cpp
new file mode 100644
index 00000000..efa2c35d
--- /dev/null
+++ b/src/imageplugins/filmgrain/imageplugin_filmgrain.cpp
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-10-01
+ * Description : a digiKam image editor plugin for add film
+ * grain on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "filmgraintool.h"
+#include "imageplugin_filmgrain.h"
+#include "imageplugin_filmgrain.moc"
+
+using namespace DigikamFilmGrainImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_filmgrain,
+ KGenericFactory<ImagePlugin_FilmGrain>("digikamimageplugin_filmgrain"));
+
+ImagePlugin_FilmGrain::ImagePlugin_FilmGrain(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_FilmGrain")
+{
+ m_filmgrainAction = new TDEAction(i18n("Add Film Grain..."), "filmgrain", 0,
+ this, TQ_SLOT(slotFilmGrain()),
+ actionCollection(), "imageplugin_filmgrain");
+
+ setXMLFile( "digikamimageplugin_filmgrain_ui.rc" );
+
+ DDebug() << "ImagePlugin_FilmGrain plugin loaded" << endl;
+}
+
+ImagePlugin_FilmGrain::~ImagePlugin_FilmGrain()
+{
+}
+
+void ImagePlugin_FilmGrain::setEnabledActions(bool enable)
+{
+ m_filmgrainAction->setEnabled(enable);
+}
+
+void ImagePlugin_FilmGrain::slotFilmGrain()
+{
+ FilmGrainTool *tool = new FilmGrainTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/filmgrain/imageplugin_filmgrain.h b/src/imageplugins/filmgrain/imageplugin_filmgrain.h
new file mode 100644
index 00000000..495da122
--- /dev/null
+++ b/src/imageplugins/filmgrain/imageplugin_filmgrain.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-10-01
+ * Description : a digiKam image editor plugin for add film
+ * grain on an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_FILMGRAIN_H
+#define IMAGEPLUGIN_FILMGRAIN_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_FilmGrain : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_FilmGrain(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_FilmGrain();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotFilmGrain();
+
+private:
+
+ TDEAction *m_filmgrainAction;
+};
+
+#endif /* IMAGEPLUGIN_FILMGRAIN_H */
diff --git a/src/imageplugins/freerotation/Makefile.am b/src/imageplugins/freerotation/Makefile.am
new file mode 100644
index 00000000..e2b67283
--- /dev/null
+++ b/src/imageplugins/freerotation/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_freerotation_la_SOURCES = imageplugin_freerotation.cpp \
+ freerotationtool.cpp freerotation.cpp
+
+digikamimageplugin_freerotation_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_freerotation_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_freerotation.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_freerotation.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_freerotation_ui.rc
+
diff --git a/src/imageplugins/freerotation/digikamimageplugin_freerotation.desktop b/src/imageplugins/freerotation/digikamimageplugin_freerotation.desktop
new file mode 100644
index 00000000..47659a0d
--- /dev/null
+++ b/src/imageplugins/freerotation/digikamimageplugin_freerotation.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Name=ImagePlugin_FreeRotation
+Name[bg]=Приставка за снимки - Свободно завъртане
+Name[da]=Billedplugin_Fri rotation
+Name[el]=ΠρόσθετοΕικόνας_ΕλεύθερηΠεριστροφή
+Name[fi]=Kierto
+Name[hr]=Slobodno obrtanje
+Name[it]=PluginImmagini_RotazioneLibera
+Name[nl]=Afbeeldingsplugin_VrijeRotatie
+Name[sr]=Слободно окретање
+Name[sr@Latn]=Slobodno okretanje
+Name[sv]=Insticksprogram för bildrotation
+Name[tr]=ResimEklentisi_SerbestDöndürme
+Name[xx]=xxImagePlugin_FreeRotationxx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Free rotation plugin for digiKam
+Comment[bg]=Приставка на digiKam за свободно завъртане на снимки
+Comment[ca]=Connector pel digiKam de gir lliure
+Comment[da]=Plugin til fri rotation af billeder til Digikam
+Comment[de]=digiKam-Modul zur freien Drehung von Bildern
+Comment[el]=Πρόσθετο ελεύθερης περιστροφής για το digiKam
+Comment[es]=Plugin para digiKam de rotación
+Comment[et]=DigiKami pildi vaba pööramise plugin
+Comment[fa]=وصلۀ چرخش آزاد برای digiKam
+Comment[fi]=Kiertää kuvaa vapaasti määritettävien asteiden verran
+Comment[gl]=Un plugin de digiKam para a rotazón libre da imaxe
+Comment[hr]=digiKam dodatak za slobodno obrtanje
+Comment[is]=Íforrit fyrir digiKam sem leyfir frjálsan snúning mynda
+Comment[it]=Plugin per la rotazione libera per digiKam
+Comment[ja]=digiKam 画像自由回転プラグイン
+Comment[nds]=digiKam-Moduul för't fre'e Dreihen
+Comment[nl]=Digikam-plugin voor vrije rotatie
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਮੁਕਤ ਘੁੰਮਾਉਣ ਵਾਲੀ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam umożliwiająca swobodny obrót obrazu
+Comment[pt]=Um 'plugin' do digiKam para a rotação livre da imagem
+Comment[pt_BR]=Plugin de Rotação Livre
+Comment[ru]=Модуль свободного вращения для digiKam
+Comment[sk]=digiKam plugin voľného otáčania
+Comment[sr]=digiKam-ов прикључак за слободно окретање
+Comment[sr@Latn]=digiKam-ov priključak za slobodno okretanje
+Comment[sv]=Digikam insticksprogram för bildrotation
+Comment[tr]=digiKam için serbest döndürme eklentisi
+Comment[uk]=Втулок вільного обертання для digiKam
+Comment[vi]=Phần bổ sung xoay tự do cho digiKam
+Comment[xx]=xxFree rotation plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_freerotation
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/freerotation/digikamimageplugin_freerotation_ui.rc b/src/imageplugins/freerotation/digikamimageplugin_freerotation_ui.rc
new file mode 100644
index 00000000..fbbf9605
--- /dev/null
+++ b/src/imageplugins/freerotation/digikamimageplugin_freerotation_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="4" name="digikamimageplugin_freerotation" >
+
+ <MenuBar>
+
+ <Menu name="Transform" ><text>Tra&amp;nsform</text>
+ <Action name="imageplugin_freerotation" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_freerotation" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/freerotation/freerotation.cpp b/src/imageplugins/freerotation/freerotation.cpp
new file mode 100644
index 00000000..3f8803d5
--- /dev/null
+++ b/src/imageplugins/freerotation/freerotation.cpp
@@ -0,0 +1,263 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-18
+ * Description : Free rotation threaded image filter.
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Degrees to radian convertion coeff (PI/180). To optimize computation.
+#define DEG2RAD 0.017453292519943
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "freerotation.h"
+
+namespace DigikamFreeRotationImagesPlugin
+{
+
+FreeRotation::FreeRotation(Digikam::DImg *orgImage, TQObject *parent, double angle, bool antialiasing,
+ int autoCrop, TQColor backgroundColor, int orgW, int orgH)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "FreeRotation")
+{
+ m_angle = angle;
+ m_orgW = orgW;
+ m_orgH = orgH;
+ m_antiAlias = antialiasing;
+ m_autoCrop = autoCrop;
+ m_backgroundColor = backgroundColor;
+
+ initFilter();
+}
+
+void FreeRotation::filterImage(void)
+{
+ int progress;
+ int w, h, nw, nh, j, i = 0;
+ int nNewHeight, nNewWidth;
+ int nhdx, nhdy, nhsx, nhsy;
+ double lfSin, lfCos, lfx, lfy;
+
+ int nWidth = m_orgImage.width();
+ int nHeight = m_orgImage.height();
+
+ uchar *pBits = m_orgImage.bits();
+ unsigned short *pBits16 = (unsigned short*)m_orgImage.bits();
+
+ // first of all, we need to calcule the sin and cos of the given angle
+
+ lfSin = sin (m_angle * -DEG2RAD);
+ lfCos = cos (m_angle * -DEG2RAD);
+
+ // now, we have to calc the new size for the destination image
+
+ if ((lfSin * lfCos) < 0)
+ {
+ nNewWidth = ROUND (fabs (nWidth * lfCos - nHeight * lfSin));
+ nNewHeight = ROUND (fabs (nWidth * lfSin - nHeight * lfCos));
+ }
+ else
+ {
+ nNewWidth = ROUND (fabs (nWidth * lfCos + nHeight * lfSin));
+ nNewHeight = ROUND (fabs (nWidth * lfSin + nHeight * lfCos));
+ }
+
+ // getting the destination's center position
+
+ nhdx = nNewWidth / 2;
+ nhdy = nNewHeight / 2;
+
+ // getting the source's center position
+
+ nhsx = nWidth / 2;
+ nhsy = nHeight / 2;
+
+ // now, we have to alloc a new image
+
+ bool sixteenBit = m_orgImage.sixteenBit();
+
+ m_destImage = Digikam::DImg(nNewWidth, nNewHeight, sixteenBit, m_orgImage.hasAlpha());
+ m_destImage.fill( Digikam::DColor(m_backgroundColor.rgb(), sixteenBit) );
+
+ uchar *pResBits = m_destImage.bits();
+ unsigned short *pResBits16 = (unsigned short *)m_destImage.bits();
+
+ Digikam::DImgImageFilters filters;
+
+ // main loop
+
+ for (h = 0; !m_cancel && (h < nNewHeight); h++)
+ {
+ nh = h - nhdy;
+
+ for (w = 0; !m_cancel && (w < nNewWidth); w++)
+ {
+ nw = w - nhdx;
+
+ i = setPosition (nNewWidth, w, h);
+
+ lfx = (double)nw * lfCos - (double)nh * lfSin + nhsx;
+ lfy = (double)nw * lfSin + (double)nh * lfCos + nhsy;
+
+ if (isInside (nWidth, nHeight, (int)lfx, (int)lfy))
+ {
+ if (m_antiAlias)
+ {
+ if (!sixteenBit)
+ filters.pixelAntiAliasing(pBits, nWidth, nHeight, lfx, lfy,
+ &pResBits[i+3], &pResBits[i+2],
+ &pResBits[i+1], &pResBits[i]);
+ else
+ filters.pixelAntiAliasing16(pBits16, nWidth, nHeight, lfx, lfy,
+ &pResBits16[i+3], &pResBits16[i+2],
+ &pResBits16[i+1], &pResBits16[i]);
+ }
+ else
+ {
+ j = setPosition (nWidth, (int)lfx, (int)lfy);
+
+ for (int p = 0 ; p < 4 ; p++)
+ {
+ if (!sixteenBit)
+ pResBits[i] = pBits[j];
+ else
+ pResBits16[i] = pBits16[j];
+
+ i++;
+ j++;
+ }
+ }
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int)(((double)h * 100.0) / nNewHeight);
+ if (progress%5 == 0)
+ postProgress( progress );
+ }
+
+ // Compute the rotated destination image size using original image dimensions.
+ int W, H;
+ double absAngle = fabs(m_angle);
+
+ if (absAngle < 90.0)
+ {
+ W = (int)(m_orgW * cos(absAngle * DEG2RAD) + m_orgH * sin(absAngle * DEG2RAD));
+ H = (int)(m_orgH * cos(absAngle * DEG2RAD) + m_orgW * sin(absAngle * DEG2RAD));
+ }
+ else
+ {
+ H = (int)(m_orgW * cos((absAngle-90.0) * DEG2RAD) + m_orgH * sin((absAngle-90.0) * DEG2RAD));
+ W = (int)(m_orgH * cos((absAngle-90.0) * DEG2RAD) + m_orgW * sin((absAngle-90.0) * DEG2RAD));
+ }
+
+ // Auto-cropping destination image without black holes around.
+ TQRect autoCrop;
+
+ switch(m_autoCrop)
+ {
+ case WidestArea:
+ {
+ // 'Widest Area' method (by Renchi Raju).
+
+ autoCrop.setX( (int)(nHeight * sin(absAngle * DEG2RAD)) );
+ autoCrop.setY( (int)(nWidth * sin(absAngle * DEG2RAD)) );
+ autoCrop.setWidth( (int)(nNewWidth - 2*nHeight * sin(absAngle * DEG2RAD)) );
+ autoCrop.setHeight( (int)(nNewHeight - 2*nWidth * sin(absAngle * DEG2RAD)) );
+
+ if (!autoCrop.isValid())
+ {
+ m_destImage = Digikam::DImg(m_orgImage.width(), m_orgImage.height(),
+ m_orgImage.sixteenBit(), m_orgImage.hasAlpha());
+ m_destImage.fill( Digikam::DColor(m_backgroundColor.rgb(), sixteenBit) );
+ m_newSize = TQSize();
+ }
+ else
+ {
+ m_destImage = m_destImage.copy(autoCrop);
+ m_newSize.setWidth( (int)(W - 2*m_orgH * sin(absAngle * DEG2RAD)) );
+ m_newSize.setHeight( (int)(H - 2*m_orgW * sin(absAngle * DEG2RAD)) );
+ }
+ break;
+ }
+
+ case LargestArea:
+ {
+ // 'Largest Area' method (by Gerhard Kulzer).
+
+ float gamma = atan((float)nHeight / (float)nWidth);
+
+ if (absAngle < 90.0)
+ {
+ autoCrop.setWidth( (int)((float)nHeight / cos(absAngle*DEG2RAD) /
+ ( tan(gamma) + tan(absAngle*DEG2RAD) )) );
+ autoCrop.setHeight( (int)((float)autoCrop.width() * tan(gamma)) );
+ }
+ else
+ {
+ autoCrop.setHeight( (int)((float)nHeight / cos((absAngle-90.0)*DEG2RAD) /
+ ( tan(gamma) + tan((absAngle-90.0)*DEG2RAD) )) );
+ autoCrop.setWidth( (int)((float)autoCrop.height() * tan(gamma)) );
+ }
+
+ autoCrop.moveCenter( TQPoint(nNewWidth/2, nNewHeight/2));
+
+ if (!autoCrop.isValid())
+ {
+ m_destImage = Digikam::DImg(m_orgImage.width(), m_orgImage.height(),
+ m_orgImage.sixteenBit(), m_orgImage.hasAlpha());
+ m_destImage.fill( Digikam::DColor(m_backgroundColor.rgb(), sixteenBit) );
+ m_newSize = TQSize();
+ }
+ else
+ {
+ m_destImage = m_destImage.copy(autoCrop);
+ gamma = atan((float)m_orgH / (float)m_orgW);
+
+ if (absAngle < 90.0)
+ {
+ m_newSize.setWidth( (int)((float)m_orgH / cos(absAngle*DEG2RAD) /
+ ( tan(gamma) + tan(absAngle*DEG2RAD) )) );
+ m_newSize.setHeight( (int)((float)m_newSize.width() * tan(gamma)) );
+ }
+ else
+ {
+ m_newSize.setHeight( (int)((float)m_orgH / cos((absAngle-90.0)*DEG2RAD) /
+ ( tan(gamma) + tan((absAngle-90.0)*DEG2RAD) )) );
+ m_newSize.setWidth( (int)((float)m_newSize.height() * tan(gamma)) );
+ }
+ }
+ break;
+ }
+ default: // No auto croping.
+ {
+ m_newSize.setWidth( W );
+ m_newSize.setHeight( H );
+ break;
+ }
+ }
+}
+
+} // NameSpace DigikamFreeRotationImagesPlugin
diff --git a/src/imageplugins/freerotation/freerotation.h b/src/imageplugins/freerotation/freerotation.h
new file mode 100644
index 00000000..7dc4cc8c
--- /dev/null
+++ b/src/imageplugins/freerotation/freerotation.h
@@ -0,0 +1,94 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-18
+ * Description : Free rotation threaded image filter.
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef FREE_ROTATION_H
+#define FREE_ROTATION_H
+
+// TQt includes.
+
+#include <tqsize.h>
+#include <tqcolor.h>
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamFreeRotationImagesPlugin
+{
+
+class FreeRotation : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ FreeRotation(Digikam::DImg *orgImage, TQObject *parent=0, double angle=0.0,
+ bool antialiasing=true, int autoCrop=NoAutoCrop, TQColor backgroundColor=TQt::black,
+ int orgW=0, int orgH=0);
+
+ ~FreeRotation(){};
+
+ TQSize getNewSize(void){ return m_newSize; };
+
+public:
+
+ enum AutoCropTypes
+ {
+ NoAutoCrop=0,
+ WidestArea,
+ LargestArea
+ };
+
+private:
+
+ virtual void filterImage(void);
+
+ inline int setPosition (int Width, int X, int Y)
+ {
+ return (Y *Width*4 + 4*X);
+ };
+
+ inline bool isInside (int Width, int Height, int X, int Y)
+ {
+ bool bIsWOk = ((X < 0) ? false : (X >= Width ) ? false : true);
+ bool bIsHOk = ((Y < 0) ? false : (Y >= Height) ? false : true);
+ return (bIsWOk && bIsHOk);
+ };
+
+private:
+
+ bool m_antiAlias;
+
+ int m_autoCrop;
+ int m_orgW;
+ int m_orgH;
+
+ double m_angle;
+
+ TQSize m_newSize;
+
+ TQColor m_backgroundColor;
+};
+
+} // NameSpace DigikamFreeRotationImagesPlugin
+
+#endif /* FREE_ROTATION_H */
diff --git a/src/imageplugins/freerotation/freerotationtool.cpp b/src/imageplugins/freerotation/freerotationtool.cpp
new file mode 100644
index 00000000..b25f2196
--- /dev/null
+++ b/src/imageplugins/freerotation/freerotationtool.cpp
@@ -0,0 +1,318 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-11-28
+ * Description : a digiKam image editor plugin to process image
+ * free rotation.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kseparator.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "editortoolsettings.h"
+#include "freerotation.h"
+#include "freerotationtool.h"
+#include "freerotationtool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamFreeRotationImagesPlugin
+{
+
+FreeRotationTool::FreeRotationTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("freerotation");
+ setToolName(i18n("Free Rotation"));
+ setToolIcon(SmallIcon("freerotation"));
+
+ m_previewWidget = new ImageWidget("freerotation Tool", 0,
+ i18n("<p>This is the free rotation operation preview. "
+ "If you move the mouse cursor on this preview, "
+ "a vertical and horizontal dashed line will be drawn "
+ "to guide you in adjusting the free rotation correction. "
+ "Release the left mouse button to freeze the dashed "
+ "line's position."),
+ false, ImageGuideWidget::HVGuideMode);
+
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQString temp;
+ Digikam::ImageIface iface(0, 0);
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel,
+ EditorToolSettings::ColorGuide);
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 9, 2);
+
+ TQLabel *label1 = new TQLabel(i18n("New width:"), m_gboxSettings->plainPage());
+ m_newWidthLabel = new TQLabel(temp.setNum( iface.originalWidth()) + i18n(" px"), m_gboxSettings->plainPage());
+ m_newWidthLabel->setAlignment( AlignBottom | AlignRight );
+
+ TQLabel *label2 = new TQLabel(i18n("New height:"), m_gboxSettings->plainPage());
+ m_newHeightLabel = new TQLabel(temp.setNum( iface.originalHeight()) + i18n(" px"), m_gboxSettings->plainPage());
+ m_newHeightLabel->setAlignment( AlignBottom | AlignRight );
+
+ KSeparator *line = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ TQLabel *label3 = new TQLabel(i18n("Main angle:"), m_gboxSettings->plainPage());
+ m_angleInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_angleInput->setRange(-180, 180, 1);
+ m_angleInput->setDefaultValue(0);
+ TQWhatsThis::add( m_angleInput, i18n("<p>An angle in degrees by which to rotate the image. "
+ "A positive angle rotates the image clockwise; "
+ "a negative angle rotates it counter-clockwise."));
+
+ TQLabel *label4 = new TQLabel(i18n("Fine angle:"), m_gboxSettings->plainPage());
+ m_fineAngleInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_fineAngleInput->setRange(-5.0, 5.0, 0.01);
+ m_fineAngleInput->setDefaultValue(0);
+ TQWhatsThis::add( m_fineAngleInput, i18n("<p>This value in degrees will be added to main angle value "
+ "to set fine target angle."));
+
+ m_antialiasInput = new TQCheckBox(i18n("Anti-Aliasing"), m_gboxSettings->plainPage());
+ TQWhatsThis::add( m_antialiasInput, i18n("<p>Enable this option to apply the anti-aliasing filter "
+ "to the rotated image. "
+ "In order to smooth the target image, it will be blurred a little."));
+
+ TQLabel *label5 = new TQLabel(i18n("Auto-crop:"), m_gboxSettings->plainPage());
+ m_autoCropCB = new RComboBox(m_gboxSettings->plainPage());
+ m_autoCropCB->insertItem( i18n("None") );
+ m_autoCropCB->insertItem( i18n("Widest Area") );
+ m_autoCropCB->insertItem( i18n("Largest Area") );
+ m_autoCropCB->setDefaultItem(FreeRotation::NoAutoCrop);
+ TQWhatsThis::add( m_autoCropCB, i18n("<p>Select the method to process image auto-cropping "
+ "to remove black frames around a rotated image."));
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 0);
+ grid->addMultiCellWidget(m_newWidthLabel, 0, 0, 1, 2);
+ grid->addMultiCellWidget(label2, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_newHeightLabel, 1, 1, 1, 2);
+ grid->addMultiCellWidget(line, 2, 2, 0, 2);
+ grid->addMultiCellWidget(label3, 3, 3, 0, 2);
+ grid->addMultiCellWidget(m_angleInput, 4, 4, 0, 2);
+ grid->addMultiCellWidget(label4, 5, 5, 0, 2);
+ grid->addMultiCellWidget(m_fineAngleInput, 6, 6, 0, 2);
+ grid->addMultiCellWidget(m_antialiasInput, 7, 7, 0, 2);
+ grid->addMultiCellWidget(label5, 8, 8, 0, 0);
+ grid->addMultiCellWidget(m_autoCropCB, 8, 8, 1, 2);
+ grid->setRowStretch(9, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_angleInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_fineAngleInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_antialiasInput, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_autoCropCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_gboxSettings, TQ_SIGNAL(signalColorGuideChanged()),
+ this, TQ_SLOT(slotColorGuideChanged()));
+}
+
+FreeRotationTool::~FreeRotationTool()
+{
+}
+
+void FreeRotationTool::slotColorGuideChanged()
+{
+ m_previewWidget->slotChangeGuideColor(m_gboxSettings->guideColor());
+ m_previewWidget->slotChangeGuideSize(m_gboxSettings->guideSize());
+}
+
+void FreeRotationTool::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("freerotation Tool");
+ m_angleInput->setValue(config->readNumEntry("Main Angle", m_angleInput->defaultValue()));
+ m_fineAngleInput->setValue(config->readDoubleNumEntry("Fine Angle", m_fineAngleInput->defaultValue()));
+ m_autoCropCB->setCurrentItem(config->readNumEntry("Auto Crop Type", m_autoCropCB->defaultItem()));
+ m_antialiasInput->setChecked(config->readBoolEntry("Anti Aliasing", true));
+ m_gboxSettings->setGuideColor(config->readColorEntry("Guide Color", &TQt::red));
+ m_gboxSettings->setGuideSize(config->readNumEntry("Guide Width", 1));
+
+ slotColorGuideChanged();
+ slotEffect();
+}
+
+void FreeRotationTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("freerotation Tool");
+ config->writeEntry("Main Angle", m_angleInput->value());
+ config->writeEntry("Fine Angle", m_fineAngleInput->value());
+ config->writeEntry("Auto Crop Type", m_autoCropCB->currentItem());
+ config->writeEntry("Anti Aliasing", m_antialiasInput->isChecked());
+ config->writeEntry("Guide Color", m_gboxSettings->guideColor());
+ config->writeEntry("Guide Width", m_gboxSettings->guideSize());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void FreeRotationTool::slotResetSettings()
+{
+ m_angleInput->blockSignals(true);
+ m_antialiasInput->blockSignals(true);
+ m_autoCropCB->blockSignals(true);
+
+ m_angleInput->slotReset();
+ m_fineAngleInput->slotReset();
+ m_antialiasInput->setChecked(true);
+ m_autoCropCB->slotReset();
+
+ m_angleInput->blockSignals(false);
+ m_antialiasInput->blockSignals(false);
+ m_autoCropCB->blockSignals(false);
+}
+
+void FreeRotationTool::prepareEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ m_angleInput->setEnabled(false);
+ m_fineAngleInput->setEnabled(false);
+ m_antialiasInput->setEnabled(false);
+ m_autoCropCB->setEnabled(false);
+
+ double angle = m_angleInput->value() + m_fineAngleInput->value();
+ bool antialiasing = m_antialiasInput->isChecked();
+ int autocrop = m_autoCropCB->currentItem();
+ TQColor background = toolView()->paletteBackgroundColor().rgb();
+ ImageIface* iface = m_previewWidget->imageIface();
+ int orgW = iface->originalWidth();
+ int orgH = iface->originalHeight();
+
+ uchar *data = iface->getPreviewImage();
+ DImg image(iface->previewWidth(), iface->previewHeight(), iface->previewSixteenBit(),
+ iface->previewHasAlpha(), data);
+ delete [] data;
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new FreeRotation(&image, this, angle, antialiasing,
+ autocrop, background, orgW, orgH)));
+}
+
+void FreeRotationTool::prepareFinal()
+{
+ m_angleInput->setEnabled(false);
+ m_fineAngleInput->setEnabled(false);
+ m_antialiasInput->setEnabled(false);
+ m_autoCropCB->setEnabled(false);
+
+ double angle = m_angleInput->value() + m_fineAngleInput->value();
+ bool antialiasing = m_antialiasInput->isChecked();
+ int autocrop = m_autoCropCB->currentItem();
+ TQColor background = TQt::black;
+
+ ImageIface iface(0, 0);
+ int orgW = iface.originalWidth();
+ int orgH = iface.originalHeight();
+
+ uchar *data = iface.getOriginalImage();
+ DImg orgImage(orgW, orgH, iface.originalSixteenBit(), iface.originalHasAlpha(), data);
+ delete [] data;
+
+ setFilter(dynamic_cast<DImgThreadedFilter *>(new FreeRotation(&orgImage, this, angle, antialiasing,
+ autocrop, background, orgW, orgH)));
+}
+
+void FreeRotationTool::putPreviewData()
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+
+ DImg imTemp = filter()->getTargetImage().smoothScale(w, h, TQSize::ScaleMin);
+ DImg imDest( w, h, filter()->getTargetImage().sixteenBit(),
+ filter()->getTargetImage().hasAlpha() );
+
+ imDest.fill(DColor(toolView()->paletteBackgroundColor().rgb(),
+ filter()->getTargetImage().sixteenBit()) );
+ imDest.bitBltImage(&imTemp, (w-imTemp.width())/2, (h-imTemp.height())/2);
+
+ iface->putPreviewImage((imDest.smoothScale(iface->previewWidth(),
+ iface->previewHeight())).bits());
+
+ m_previewWidget->updatePreview();
+ TQSize newSize = dynamic_cast<FreeRotation*>(filter())->getNewSize();
+ TQString temp;
+ m_newWidthLabel->setText(temp.setNum( newSize.width()) + i18n(" px") );
+ m_newHeightLabel->setText(temp.setNum( newSize.height()) + i18n(" px") );
+}
+
+void FreeRotationTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ DImg targetImage = filter()->getTargetImage();
+ iface.putOriginalImage(i18n("Free Rotation"),
+ targetImage.bits(),
+ targetImage.width(), targetImage.height());
+}
+
+void FreeRotationTool::renderingFinished()
+{
+ m_angleInput->setEnabled(true);
+ m_fineAngleInput->setEnabled(true);
+ m_antialiasInput->setEnabled(true);
+ m_autoCropCB->setEnabled(true);
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamFreeRotationImagesPlugin
diff --git a/src/imageplugins/freerotation/freerotationtool.h b/src/imageplugins/freerotation/freerotationtool.h
new file mode 100644
index 00000000..fd17f4ff
--- /dev/null
+++ b/src/imageplugins/freerotation/freerotationtool.h
@@ -0,0 +1,97 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-11-28
+ * Description : a digiKam image editor plugin to process image
+ * free rotation.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef FREEROTATIONTOOL_H
+#define FREEROTATIONTOOL_H
+
+// Local includes.
+
+#include "editortool.h"
+
+class TQFrame;
+class TQLabel;
+class TQCheckBox;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RDoubleNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImageWidget;
+}
+
+namespace DigikamFreeRotationImagesPlugin
+{
+
+class FreeRotationTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ FreeRotationTool(TQObject *parent);
+ ~FreeRotationTool();
+
+private slots:
+
+ void slotResetSettings();
+ void slotColorGuideChanged();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQLabel *m_newWidthLabel;
+ TQLabel *m_newHeightLabel;
+
+ TQCheckBox *m_antialiasInput;
+
+ KDcrawIface::RComboBox *m_autoCropCB;
+
+ KDcrawIface::RIntNumInput *m_angleInput;
+
+ KDcrawIface::RDoubleNumInput *m_fineAngleInput;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamFreeRotationImagesPlugin
+
+#endif /* FREEROTATIONTOOL_H */
diff --git a/src/imageplugins/freerotation/imageeffect_freerotation.cpp b/src/imageplugins/freerotation/imageeffect_freerotation.cpp
new file mode 100644
index 00000000..bce50f07
--- /dev/null
+++ b/src/imageplugins/freerotation/imageeffect_freerotation.cpp
@@ -0,0 +1,308 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-11-28
+ * Description : a digiKam image editor plugin to process image
+ * free rotation.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqcheckbox.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqimage.h>
+#include <tqcombobox.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+#include <kcursor.h>
+#include <kseparator.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "freerotation.h"
+#include "imageeffect_freerotation.h"
+#include "imageeffect_freerotation.moc"
+
+namespace DigikamFreeRotationImagesPlugin
+{
+
+ImageEffect_FreeRotation::ImageEffect_FreeRotation(TQWidget* parent)
+ : Digikam::ImageGuideDlg(parent, i18n("Free Rotation"), "freerotation",
+ false, true, true, Digikam::ImageGuideWidget::HVGuideMode)
+{
+ // No need Abort button action.
+ showButton(User1, false);
+
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Free Rotation"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to process free image "
+ "rotation."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Pieter Z. Voloshyn", I18N_NOOP("Free Rotation algorithm"),
+ "pieter dot voloshyn at gmail dot com");
+
+ setAboutData(about);
+
+ TQWhatsThis::add( m_imagePreviewWidget, i18n("<p>This is the free image operation preview. "
+ "If you move the mouse cursor on this preview, "
+ "a vertical and horizontal dashed line will be drawn "
+ "to guide you in adjusting the free rotation correction. "
+ "Release the left mouse button to freeze the dashed "
+ "line's position."));
+
+ // -------------------------------------------------------------
+
+ TQString temp;
+ Digikam::ImageIface iface(0, 0);
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 9, 2, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("New width:"), gboxSettings);
+ m_newWidthLabel = new TQLabel(temp.setNum( iface.originalWidth()) + i18n(" px"), gboxSettings);
+ m_newWidthLabel->setAlignment( AlignBottom | AlignRight );
+
+ TQLabel *label2 = new TQLabel(i18n("New height:"), gboxSettings);
+ m_newHeightLabel = new TQLabel(temp.setNum( iface.originalHeight()) + i18n(" px"), gboxSettings);
+ m_newHeightLabel->setAlignment( AlignBottom | AlignRight );
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridSettings->addMultiCellWidget(m_newWidthLabel, 0, 0, 1, 2);
+ gridSettings->addMultiCellWidget(label2, 1, 1, 0, 0);
+ gridSettings->addMultiCellWidget(m_newHeightLabel, 1, 1, 1, 2);
+
+ KSeparator *line = new KSeparator(Horizontal, gboxSettings);
+ gridSettings->addMultiCellWidget(line, 2, 2, 0, 2);
+
+ TQLabel *label3 = new TQLabel(i18n("Main angle:"), gboxSettings);
+ m_angleInput = new KIntNumInput(gboxSettings);
+ m_angleInput->setRange(-180, 180, 1, true);
+ m_angleInput->setValue(0);
+ TQWhatsThis::add( m_angleInput, i18n("<p>An angle in degrees by which to rotate the image. "
+ "A positive angle rotates the image clockwise; "
+ "a negative angle rotates it counter-clockwise."));
+
+ gridSettings->addMultiCellWidget(label3, 3, 3, 0, 2);
+ gridSettings->addMultiCellWidget(m_angleInput, 4, 4, 0, 2);
+
+ TQLabel *label4 = new TQLabel(i18n("Fine angle:"), gboxSettings);
+ m_fineAngleInput = new KDoubleNumInput(gboxSettings);
+ m_fineAngleInput->setRange(-5.0, 5.0, 0.01, true);
+ m_fineAngleInput->setValue(0);
+ TQWhatsThis::add( m_fineAngleInput, i18n("<p>This value in degrees will be added to main angle value "
+ "to set fine target angle."));
+
+ gridSettings->addMultiCellWidget(label4, 5, 5, 0, 2);
+ gridSettings->addMultiCellWidget(m_fineAngleInput, 6, 6, 0, 2);
+
+ m_antialiasInput = new TQCheckBox(i18n("Anti-Aliasing"), gboxSettings);
+ TQWhatsThis::add( m_antialiasInput, i18n("<p>Enable this option to apply the anti-aliasing filter "
+ "to the rotated image. "
+ "In order to smooth the target image, it will be blurred a little."));
+ gridSettings->addMultiCellWidget(m_antialiasInput, 7, 7, 0, 2);
+
+ TQLabel *label5 = new TQLabel(i18n("Auto-crop:"), gboxSettings);
+ m_autoCropCB = new TQComboBox(false, gboxSettings);
+ m_autoCropCB->insertItem( i18n("None") );
+ m_autoCropCB->insertItem( i18n("Widest Area") );
+ m_autoCropCB->insertItem( i18n("Largest Area") );
+ TQWhatsThis::add( m_autoCropCB, i18n("<p>Select the method to process image auto-cropping "
+ "to remove black frames around a rotated image."));
+ gridSettings->addMultiCellWidget(label5, 8, 8, 0, 0);
+ gridSettings->addMultiCellWidget(m_autoCropCB, 8, 8, 1, 2);
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_angleInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_fineAngleInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_antialiasInput, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_autoCropCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+}
+
+ImageEffect_FreeRotation::~ImageEffect_FreeRotation()
+{
+}
+
+void ImageEffect_FreeRotation::readUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("freerotation Tool Dialog");
+ m_angleInput->setValue(config->readNumEntry("Main Angle", 0));
+ m_fineAngleInput->setValue(config->readDoubleNumEntry("Fine Angle", 0.0));
+ m_autoCropCB->setCurrentItem(config->readNumEntry("Auto Crop Type", FreeRotation::NoAutoCrop));
+ m_antialiasInput->setChecked(config->readBoolEntry("Anti Aliasing", true));
+ slotEffect();
+}
+
+void ImageEffect_FreeRotation::writeUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("freerotation Tool Dialog");
+ config->writeEntry("Main Angle", m_angleInput->value());
+ config->writeEntry("Fine Angle", m_fineAngleInput->value());
+ config->writeEntry( "Auto Crop Type", m_autoCropCB->currentItem() );
+ config->writeEntry( "Anti Aliasing", m_antialiasInput->isChecked() );
+ config->sync();
+}
+
+void ImageEffect_FreeRotation::resetValues()
+{
+ m_angleInput->blockSignals(true);
+ m_antialiasInput->blockSignals(true);
+ m_autoCropCB->blockSignals(true);
+ m_angleInput->setValue(0);
+ m_fineAngleInput->setValue(0.0);
+ m_antialiasInput->setChecked(true);
+ m_autoCropCB->setCurrentItem(FreeRotation::NoAutoCrop);
+ m_angleInput->blockSignals(false);
+ m_antialiasInput->blockSignals(false);
+ m_autoCropCB->blockSignals(false);
+}
+
+void ImageEffect_FreeRotation::prepareEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ m_angleInput->setEnabled(false);
+ m_fineAngleInput->setEnabled(false);
+ m_antialiasInput->setEnabled(false);
+ m_autoCropCB->setEnabled(false);
+
+ double angle = m_angleInput->value() + m_fineAngleInput->value();
+ bool antialiasing = m_antialiasInput->isChecked();
+ int autocrop = m_autoCropCB->currentItem();
+ TQColor background = paletteBackgroundColor().rgb();
+
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+ int orgW = iface->originalWidth();
+ int orgH = iface->originalHeight();
+
+ uchar *data = iface->getPreviewImage();
+ Digikam::DImg image(iface->previewWidth(), iface->previewHeight(), iface->previewSixteenBit(),
+ iface->previewHasAlpha(), data);
+ delete [] data;
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new FreeRotation(&image, this, angle, antialiasing, autocrop,
+ background, orgW, orgH));
+}
+
+void ImageEffect_FreeRotation::prepareFinal()
+{
+ m_angleInput->setEnabled(false);
+ m_fineAngleInput->setEnabled(false);
+ m_antialiasInput->setEnabled(false);
+ m_autoCropCB->setEnabled(false);
+
+ double angle = m_angleInput->value() + m_fineAngleInput->value();
+ bool antialiasing = m_antialiasInput->isChecked();
+ int autocrop = m_autoCropCB->currentItem();
+ TQColor background = TQt::black;
+
+ Digikam::ImageIface iface(0, 0);
+ int orgW = iface.originalWidth();
+ int orgH = iface.originalHeight();
+
+ uchar *data = iface.getOriginalImage();
+ Digikam::DImg orgImage(orgW, orgH, iface.originalSixteenBit(),
+ iface.originalHasAlpha(), data);
+ delete [] data;
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new FreeRotation(&orgImage, this, angle, antialiasing, autocrop,
+ background, orgW, orgH));
+}
+
+void ImageEffect_FreeRotation::putPreviewData(void)
+{
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+
+ Digikam::DImg imTemp = m_threadedFilter->getTargetImage().smoothScale(w, h, TQSize::ScaleMin);
+ Digikam::DImg imDest( w, h, m_threadedFilter->getTargetImage().sixteenBit(),
+ m_threadedFilter->getTargetImage().hasAlpha() );
+
+ imDest.fill( Digikam::DColor(paletteBackgroundColor().rgb(),
+ m_threadedFilter->getTargetImage().sixteenBit()) );
+ imDest.bitBltImage(&imTemp, (w-imTemp.width())/2, (h-imTemp.height())/2);
+
+ iface->putPreviewImage((imDest.smoothScale(iface->previewWidth(),
+ iface->previewHeight())).bits());
+
+ m_imagePreviewWidget->updatePreview();
+ TQSize newSize = dynamic_cast<FreeRotation *>(m_threadedFilter)->getNewSize();
+ TQString temp;
+ m_newWidthLabel->setText(temp.setNum( newSize.width()) + i18n(" px") );
+ m_newHeightLabel->setText(temp.setNum( newSize.height()) + i18n(" px") );
+}
+
+void ImageEffect_FreeRotation::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ Digikam::DImg targetImage = m_threadedFilter->getTargetImage();
+ iface.putOriginalImage(i18n("Free Rotation"),
+ targetImage.bits(),
+ targetImage.width(), targetImage.height());
+}
+
+void ImageEffect_FreeRotation::renderingFinished()
+{
+ m_angleInput->setEnabled(true);
+ m_fineAngleInput->setEnabled(true);
+ m_antialiasInput->setEnabled(true);
+ m_autoCropCB->setEnabled(true);
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamFreeRotationImagesPlugin
+
diff --git a/src/imageplugins/freerotation/imageeffect_freerotation.h b/src/imageplugins/freerotation/imageeffect_freerotation.h
new file mode 100644
index 00000000..a90be09d
--- /dev/null
+++ b/src/imageplugins/freerotation/imageeffect_freerotation.h
@@ -0,0 +1,83 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-11-28
+ * Description : a digiKam image editor plugin to process image
+ * free rotation.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_FREEROTATION_H
+#define IMAGEEFFECT_FREEROTATION_H
+
+// Local includes.
+
+#include "imageguidedlg.h"
+
+class TQFrame;
+class TQLabel;
+class TQCheckBox;
+class TQComboBox;
+
+class KIntNumInput;
+class KDoubleNumInput;
+
+namespace DigikamFreeRotationImagesPlugin
+{
+
+class ImageEffect_FreeRotation : public Digikam::ImageGuideDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_FreeRotation(TQWidget *parent);
+ ~ImageEffect_FreeRotation();
+
+private slots:
+
+ void readUserSettings(void);
+
+protected:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQLabel *m_newWidthLabel;
+ TQLabel *m_newHeightLabel;
+
+ TQCheckBox *m_antialiasInput;
+
+ TQComboBox *m_autoCropCB;
+
+ KIntNumInput *m_angleInput;
+
+ KDoubleNumInput *m_fineAngleInput;
+};
+
+} // NameSpace DigikamFreeRotationImagesPlugin
+
+#endif /* IMAGEEFFECT_FREEROTATION_H */
diff --git a/src/imageplugins/freerotation/imageplugin_freerotation.cpp b/src/imageplugins/freerotation/imageplugin_freerotation.cpp
new file mode 100644
index 00000000..0c04a2ca
--- /dev/null
+++ b/src/imageplugins/freerotation/imageplugin_freerotation.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-11-28
+ * Description : a digiKam image editor plugin to process image
+ * free rotation.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "freerotationtool.h"
+#include "imageplugin_freerotation.h"
+#include "imageplugin_freerotation.moc"
+
+using namespace DigikamFreeRotationImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_freerotation,
+ KGenericFactory<ImagePlugin_FreeRotation>("digikamimageplugin_freerotation"));
+
+ImagePlugin_FreeRotation::ImagePlugin_FreeRotation(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_FreeRotation")
+{
+ m_freerotationAction = new TDEAction(i18n("Free Rotation..."), "freerotation", 0,
+ this, TQ_SLOT(slotFreeRotation()),
+ actionCollection(), "imageplugin_freerotation");
+
+ setXMLFile("digikamimageplugin_freerotation_ui.rc");
+
+ DDebug() << "ImagePlugin_FreeRotation plugin loaded" << endl;
+}
+
+ImagePlugin_FreeRotation::~ImagePlugin_FreeRotation()
+{
+}
+
+void ImagePlugin_FreeRotation::setEnabledActions(bool enable)
+{
+ m_freerotationAction->setEnabled(enable);
+}
+
+void ImagePlugin_FreeRotation::slotFreeRotation()
+{
+ FreeRotationTool *tool = new FreeRotationTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/freerotation/imageplugin_freerotation.h b/src/imageplugins/freerotation/imageplugin_freerotation.h
new file mode 100644
index 00000000..2a0c2627
--- /dev/null
+++ b/src/imageplugins/freerotation/imageplugin_freerotation.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-11-28
+ * Description : a digiKam image editor plugin to process image
+ * free rotation.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_FREEROTATION_H
+#define IMAGEPLUGIN_FREEROTATION_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_FreeRotation : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_FreeRotation(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_FreeRotation();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotFreeRotation();
+
+private:
+
+ TDEAction *m_freerotationAction;
+};
+
+#endif /* IMAGEPLUGIN_FREEROTATION_H */
diff --git a/src/imageplugins/hotpixels/Makefile.am b/src/imageplugins/hotpixels/Makefile.am
new file mode 100644
index 00000000..711fe84e
--- /dev/null
+++ b/src/imageplugins/hotpixels/Makefile.am
@@ -0,0 +1,36 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/threadimageio \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_hotpixels_la_SOURCES = blackframeparser.cpp weights.cpp \
+ hotpixelfixer.cpp imageplugin_hotpixels.cpp \
+ blackframelistview.cpp hotpixelstool.cpp
+
+digikamimageplugin_hotpixels_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_hotpixels_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_hotpixels.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_hotpixels.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_hotpixels_ui.rc
+
diff --git a/src/imageplugins/hotpixels/TODO b/src/imageplugins/hotpixels/TODO
new file mode 100644
index 00000000..880e1a36
--- /dev/null
+++ b/src/imageplugins/hotpixels/TODO
@@ -0,0 +1,4 @@
+- Store black frames. Include the fullsize image to be able to reedit it if necessary.
+- Add a hand hot-pixel editor for the hot pixels on the black frame
+- Use the same hot-pixel editor from the image view, to edit a new black frame with the added data
+
diff --git a/src/imageplugins/hotpixels/blackframelistview.cpp b/src/imageplugins/hotpixels/blackframelistview.cpp
new file mode 100644
index 00000000..1202b094
--- /dev/null
+++ b/src/imageplugins/hotpixels/blackframelistview.cpp
@@ -0,0 +1,176 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-05
+ * Description : a ListView to display black frames
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#define THUMB_WIDTH 150
+
+// TQt includes.
+
+#include <tqpainter.h>
+#include <tqtooltip.h>
+
+// Local includes.
+
+#include "blackframelistview.h"
+#include "blackframelistview.moc"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+BlackFrameListView::BlackFrameListView(TQWidget* parent)
+ : TQListView(parent)
+{
+ addColumn(i18n("Preview"));
+ addColumn(i18n("Size"));
+ addColumn(i18n("This is a column which will contain the amount of HotPixels "
+ "found in the black frame file", "HP"));
+ setAllColumnsShowFocus(true);
+ setResizeMode(TQListView::LastColumn);
+ setSelectionMode(TQListView::Single);
+}
+
+// --------------------------------------------------------------------------
+
+BlackFrameListViewItem::BlackFrameListViewItem(BlackFrameListView* parent, const KURL &url)
+ : TQObject(parent), TQListViewItem(parent)
+{
+ m_parent = parent;
+ m_blackFrameURL = url;
+ m_parser = new BlackFrameParser(parent);
+ m_parser->parseBlackFrame(url);
+
+ connect(m_parser, TQ_SIGNAL(parsed(TQValueList<HotPixel>)),
+ this, TQ_SLOT(slotParsed(TQValueList<HotPixel>)));
+
+ connect(this, TQ_SIGNAL(parsed(TQValueList<HotPixel>, const KURL&)),
+ parent, TQ_SLOT(slotParsed(TQValueList<HotPixel>, const KURL&)));
+
+ connect(m_parser, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SIGNAL(signalLoadingProgress(float)));
+
+ connect(m_parser, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SIGNAL(signalLoadingComplete()));
+}
+
+void BlackFrameListViewItem::activate()
+{
+ TQToolTip::add( m_parent, m_blackFrameDesc);
+ emit parsed(m_hotPixels, m_blackFrameURL);
+}
+
+TQString BlackFrameListViewItem::text(int column)const
+{
+ switch (column)
+ {
+ case 0:
+ {
+ // First column includes the pixmap
+ break;
+ }
+ case 1:
+ {
+ // The image size.
+ if (!m_imageSize.isEmpty())
+ return (TQString("%1x%2").arg(m_imageSize.width()).arg(m_imageSize.height()));
+ break;
+ }
+ case 2:
+ {
+ // The amount of hot pixels found in the black frame.
+ return (TQString::number(m_hotPixels.count()));
+ break;
+ }
+ }
+
+ return TQString();
+}
+
+void BlackFrameListViewItem::paintCell(TQPainter* p, const TQColorGroup& cg, int column, int width, int align)
+{
+ //Let the normal listview item draw it all for now
+ TQListViewItem::paintCell(p, cg, column, width, align);
+}
+
+void BlackFrameListViewItem::slotParsed(TQValueList<HotPixel> hotPixels)
+{
+ m_hotPixels = hotPixels;
+ m_image = m_parser->image();
+ m_imageSize = m_image.size();
+ m_thumb = thumb(TQSize(THUMB_WIDTH, THUMB_WIDTH/3*2));
+ setPixmap(0, m_thumb);
+
+ m_blackFrameDesc = TQString("<p><b>" + m_blackFrameURL.fileName() + "</b>:<p>");
+ TQValueList <HotPixel>::Iterator end(m_hotPixels.end());
+ for (TQValueList <HotPixel>::Iterator it = m_hotPixels.begin() ; it != end ; ++it)
+ m_blackFrameDesc.append( TQString("[%1,%2] ").arg((*it).x()).arg((*it).y()) );
+
+ emit parsed(m_hotPixels, m_blackFrameURL);
+}
+
+TQPixmap BlackFrameListViewItem::thumb(const TQSize& size)
+{
+ TQPixmap thumb;
+
+ //First scale it down to the size
+ thumb = m_image.smoothScale(size, TQImage::ScaleMin);
+
+ //And draw the hot pixel positions on the thumb
+ TQPainter p(&thumb);
+
+ //Take scaling into account
+ float xRatio, yRatio;
+ float hpThumbX, hpThumbY;
+ TQRect hpRect;
+
+ xRatio = (float)size.width()/(float)m_image.width();
+ yRatio = (float)size.height()/(float)m_image.height();
+
+ //Draw hot pixels one by one
+ TQValueList <HotPixel>::Iterator it;
+ TQValueList <HotPixel>::Iterator end(m_hotPixels.end());
+ for (it=m_hotPixels.begin() ; it!=end ; ++it)
+ {
+ hpRect = (*it).rect;
+ hpThumbX = (hpRect.x()+hpRect.width()/2)*xRatio;
+ hpThumbY = (hpRect.y()+hpRect.height()/2)*yRatio;
+
+ p.setPen(TQPen(TQt::black));
+ p.drawLine((int)hpThumbX, (int)hpThumbY-1, (int)hpThumbX, (int)hpThumbY+1);
+ p.drawLine((int)hpThumbX-1, (int)hpThumbY, (int)hpThumbX+1, (int)hpThumbY);
+ p.setPen(TQPen(TQt::white));
+ p.drawPoint((int)hpThumbX-1, (int)hpThumbY-1);
+ p.drawPoint((int)hpThumbX+1, (int)hpThumbY+1);
+ p.drawPoint((int)hpThumbX-1, (int)hpThumbY+1);
+ p.drawPoint((int)hpThumbX+1, (int)hpThumbY-1);
+ }
+
+ return thumb;
+}
+
+int BlackFrameListViewItem::width(const TQFontMetrics& fm,const TQListView* lv,int c)const
+{
+ if (c==0) return THUMB_WIDTH;
+ else return TQListViewItem::width(fm,lv,c);
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/blackframelistview.h b/src/imageplugins/hotpixels/blackframelistview.h
new file mode 100644
index 00000000..977d226d
--- /dev/null
+++ b/src/imageplugins/hotpixels/blackframelistview.h
@@ -0,0 +1,127 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-05
+ * Description : a ListView to display black frames
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef BLACKFRAMELISTVIEW_H
+#define BLACKFRAMELISTVIEW_H
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqstring.h>
+#include <tqsize.h>
+#include <tqpoint.h>
+#include <tqvaluelist.h>
+#include <tqlistview.h>
+
+// KDE includes.
+
+#include <kurl.h>
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "blackframeparser.h"
+#include "hotpixel.h"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class BlackFrameListView : public TQListView
+{
+ TQ_OBJECT
+
+
+public:
+
+ BlackFrameListView(TQWidget* parent=0);
+ ~BlackFrameListView(){};
+
+signals:
+
+ void blackFrameSelected(TQValueList<HotPixel>, const KURL&);
+
+private slots:
+
+ void slotParsed(TQValueList<HotPixel> hotPixels, const KURL& blackFrameURL)
+ {
+ emit blackFrameSelected(hotPixels, blackFrameURL);
+ };
+};
+
+// --------------------------------------------------------------------------
+
+class BlackFrameListViewItem : public TQObject, TQListViewItem
+{
+TQ_OBJECT
+
+
+public:
+
+ BlackFrameListViewItem(BlackFrameListView* parent, const KURL &url);
+ ~BlackFrameListViewItem(){};
+
+ virtual TQString text(int column)const;
+ virtual void paintCell(TQPainter* p, const TQColorGroup& cg, int column, int width, int align);
+ virtual int width(const TQFontMetrics& fm, const TQListView* lv, int c)const;
+
+signals:
+
+ void parsed(TQValueList<HotPixel>, const KURL&);
+ void signalLoadingProgress(float);
+ void signalLoadingComplete();
+
+protected:
+
+ void activate();
+
+private:
+
+ TQPixmap thumb(const TQSize& size);
+
+private slots:
+
+ void slotParsed(TQValueList<HotPixel>);
+
+private:
+
+ // Data contained within each listview item
+ TQImage m_thumb;
+ TQImage m_image;
+
+ TQSize m_imageSize;
+
+ TQValueList <HotPixel> m_hotPixels;
+
+ TQString m_blackFrameDesc;
+
+ KURL m_blackFrameURL;
+
+ BlackFrameParser *m_parser;
+
+ BlackFrameListView *m_parent;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // BLACKFRAMELISTVIEW_H
diff --git a/src/imageplugins/hotpixels/blackframeparser.cpp b/src/imageplugins/hotpixels/blackframeparser.cpp
new file mode 100644
index 00000000..7306f4e6
--- /dev/null
+++ b/src/imageplugins/hotpixels/blackframeparser.cpp
@@ -0,0 +1,211 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : black frames parser
+ *
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Part of the algorithm for finding the hot pixels was based on
+ * the code of jpegpixi, which was released under the GPL license,
+ * and is Copyright (C) 2003, 2004 Martin Dickopp
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Denominator for relative quantities.
+#define DENOM (DENOM_STQRT * DENOM_STQRT)
+
+// Square root of denominator for relative quantities.
+#define DENOM_STQRT 10000
+
+// Convert relative to absolute numbers. Care must be taken not to overflow integers.
+#define REL_TO_ABS(n,m) \
+ ((((n) / DENOM_STQRT) * (m) + ((n) % DENOM_STQRT) * (m) / DENOM_STQRT) / DENOM_STQRT)
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqstringlist.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <tdeversion.h>
+#include <tdeio/netaccess.h>
+#include <tdeio/job.h>
+
+// Local includes.
+
+#include "blackframeparser.h"
+#include "blackframeparser.moc"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+BlackFrameParser::BlackFrameParser(TQObject *parent)
+ : TQObject(parent)
+{
+ m_imageLoaderThread = 0;
+}
+
+BlackFrameParser::~BlackFrameParser()
+{
+ delete m_imageLoaderThread;
+}
+
+void BlackFrameParser::parseHotPixels(const TQString &file)
+{
+ parseBlackFrame(KURL(file));
+}
+
+void BlackFrameParser::parseBlackFrame(const KURL &url)
+{
+#if KDE_IS_VERSION(3,2,0)
+ TDEIO::NetAccess::download(url, m_localFile, kapp->activeWindow());
+#else
+ TDEIO::NetAccess::download(url, m_localFile);
+#endif
+
+ if (!m_imageLoaderThread)
+ {
+ m_imageLoaderThread = new LoadSaveThread();
+
+ connect(m_imageLoaderThread, TQ_SIGNAL(signalLoadingProgress(const LoadingDescription&, float)),
+ this, TQ_SLOT(slotLoadingProgress(const LoadingDescription&, float)));
+
+ connect(m_imageLoaderThread, TQ_SIGNAL(signalImageLoaded(const LoadingDescription&, const DImg&)),
+ this, TQ_SLOT(slotLoadImageFromUrlComplete(const LoadingDescription&, const DImg&)));
+ }
+
+ LoadingDescription desc = LoadingDescription(m_localFile, DRawDecoding());
+ m_imageLoaderThread->load(desc);
+}
+
+void BlackFrameParser::slotLoadingProgress(const LoadingDescription&, float v)
+{
+ emit signalLoadingProgress(v);
+}
+
+void BlackFrameParser::slotLoadImageFromUrlComplete(const LoadingDescription&, const DImg& img)
+{
+ DImg image(img);
+ m_Image = image.copyTQImage();
+ blackFrameParsing();
+ emit signalLoadingComplete();
+}
+
+void BlackFrameParser::parseBlackFrame(TQImage& img)
+{
+ m_Image = img;
+ blackFrameParsing();
+}
+
+// Parses black frames
+
+void BlackFrameParser::blackFrameParsing()
+{
+ // Now find the hot pixels and store them in a list
+ TQValueList<HotPixel> hpList;
+
+ for (int y=0 ; y < m_Image.height() ; ++y)
+ {
+ for (int x=0 ; x < m_Image.width() ; ++x)
+ {
+ //Get each point in the image
+ TQRgb pixrgb = m_Image.pixel(x,y);
+ TQColor color; color.setRgb(pixrgb);
+
+ // Find maximum component value.
+ int maxValue;
+ int threshold = DENOM/10;
+ const int threshold_value = REL_TO_ABS(threshold, 255);
+ maxValue = (color.red()>color.blue()) ? color.red() : color.blue();
+ if (color.green() > maxValue) maxValue = color.green();
+
+ // If the component is bigger than the threshold, add the point
+ if (maxValue > threshold_value)
+ {
+ HotPixel point;
+ point.rect = TQRect (x, y, 1, 1);
+ //TODO:check this
+ point.luminosity = ((2 * DENOM) / 255 ) * maxValue / 2;
+
+ hpList.append(point);
+ }
+ }
+ }
+
+ //Now join points together into groups
+ consolidatePixels (hpList);
+
+ //And notify
+ emit parsed(hpList);
+}
+
+// Consolidate adjacent points into larger points.
+
+void BlackFrameParser::consolidatePixels (TQValueList<HotPixel>& list)
+{
+ if (list.isEmpty())
+ return;
+
+ /* Consolidate horizontally. */
+
+ TQValueList<HotPixel>::iterator it, prevPointIt;
+
+ prevPointIt = list.begin();
+ it = list.begin();
+ ++it;
+
+ HotPixel tmp;
+ HotPixel point;
+ HotPixel point_below;
+ TQValueList<HotPixel>::iterator end(list.end());
+ for (; it != end; ++it )
+ {
+ while (1)
+ {
+ point = (*it);
+ tmp = point;
+
+ TQValueList<HotPixel>::Iterator point_below_it;
+ point_below_it = list.find (tmp); //find any intersecting hotp below tmp
+ if (point_below_it != list.end())
+ {
+ point_below =* point_below_it;
+ validateAndConsolidate (&point, &point_below);
+
+ point.rect.setX(MIN(point.x(), point_below.x()));
+ point.rect.setWidth(MAX(point.x() + point.width(),
+ point_below.x() + point_below.width()) - point.x());
+ point.rect.setHeight(MAX(point.y() + point.height(),
+ point_below.y() + point_below.height()) - point.y());
+ *it = point;
+ list.remove (point_below_it); //TODO: Check! this could remove it++?
+ }
+ else
+ break;
+ }
+ }
+}
+
+void BlackFrameParser::validateAndConsolidate (HotPixel *a, HotPixel *b)
+{
+ a->luminosity = MAX (a->luminosity, b->luminosity);
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/blackframeparser.h b/src/imageplugins/hotpixels/blackframeparser.h
new file mode 100644
index 00000000..f13ebdc4
--- /dev/null
+++ b/src/imageplugins/hotpixels/blackframeparser.h
@@ -0,0 +1,102 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : black frames parser
+ *
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge dot net>
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Part of the algorithm for finding the hot pixels was based on
+ * the code of jpegpixi, which was released under the GPL license,
+ * and is Copyright (C) 2003, 2004 Martin Dickopp
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef BLACKFRAMEPARSER_H
+#define BLACKFRAMEPARSER_H
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqobject.h>
+#include <tqvaluelist.h>
+#include <tqstring.h>
+#include <tqrect.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "loadsavethread.h"
+#include "hotpixel.h"
+
+using namespace Digikam;
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class BlackFrameParser: public TQObject
+{
+ TQ_OBJECT
+
+
+public:
+
+ BlackFrameParser(TQObject *parent);
+ ~BlackFrameParser();
+
+ void parseHotPixels(const TQString &file);
+ void parseBlackFrame(const KURL &url);
+ void parseBlackFrame(TQImage& img);
+ TQImage image(){return m_Image;}
+
+signals:
+
+ void parsed(TQValueList<HotPixel>);
+ void signalLoadingProgress(float);
+ void signalLoadingComplete();
+
+private slots:
+
+ void slotLoadingProgress(const LoadingDescription&, float);
+ void slotLoadImageFromUrlComplete(const LoadingDescription&, const DImg&);
+
+private:
+
+ void blackFrameParsing();
+ void consolidatePixels(TQValueList<HotPixel>& list);
+ void validateAndConsolidate(HotPixel *a, HotPixel *b);
+
+private:
+
+ TQString m_OutputString;
+ TQString m_localFile;
+
+ TQImage m_Image;
+
+ LoadSaveThread *m_imageLoaderThread;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // BLACKFRAMEPARSER_H
diff --git a/src/imageplugins/hotpixels/digikamimageplugin_hotpixels.desktop b/src/imageplugins/hotpixels/digikamimageplugin_hotpixels.desktop
new file mode 100644
index 00000000..5b12fe2c
--- /dev/null
+++ b/src/imageplugins/hotpixels/digikamimageplugin_hotpixels.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Name=ImagePlugin_HotPixels
+Name[bg]=Приставка за снимки - Горещи пиксели
+Name[el]=ΠρόσθετοΕικόνας_ΈντοναΕικονοστοιχεία
+Name[fi]=KuumatPikselit
+Name[hr]=Vrući pikseli
+Name[it]=PluginImmagini_PixelBruciati
+Name[ms]=ImagePlugin_PikselPanas
+Name[nl]=Afbeeldingsplugin_HotPixels
+Name[sr]=Врући пиксели
+Name[sr@Latn]=Vrući pikseli
+Name[sv]=Insticksprogram för heta bildpunkter
+Name[tr]=ResimEklentisi_Çekirdek
+Name[xx]=xxImagePlugin_HotPixelsxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Hot pixel correction plugin for digiKam
+Comment[ca]=Connector per al digiKam de correcció de píxels cremats
+Comment[da]=Hot pixel rettelsesplugin for Digikam
+Comment[de]=digiKam-Modul zur Korrektur von heißen (defekten) Pixeln
+Comment[el]=Πρόσθετο διόρθωσης έντονων εικονοστοιχείων για το digiKam
+Comment[es]=Plugin para digiKampara corregir los píxeles quemados de la imagen
+Comment[et]=DigiKami kuumade pikslite korrigeerimise plugin
+Comment[fa]=وصلۀ اصلاح تصویردانۀ Hot برای digiKam
+Comment[fi]=Digitaalisen rakeisuushäiriön korjaus
+Comment[gl]=Un plugin de digiKam para corrixir os pixels queimados da imaxe
+Comment[hr]=digiKam dodatak za ispravljanje vrućih piksela
+Comment[is]=Íforrit fyrir digiKam sem fjarlægir skemmda díla (hot pixels)
+Comment[it]=Plugin di correzione dei pixel bruciati per digiKam
+Comment[ja]=digiKam ホットピクセル除去プラグイン
+Comment[ms]=Plugin pembetulan piksel panas untuk digiKam
+Comment[nds]=digiKam-Moduul för't Richten vun hitte Pixels
+Comment[nl]=Digikam-plugin voor het corrigeren van de hotpixels
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਹਾਟ ਪਿਕਸਲ ਸੋਧ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam usuwająca "gorące piksele"
+Comment[pt]=Um 'plugin' do digiKam para corrigir os pixels queimados da imagem
+Comment[pt_BR]=Plugin de Correção de hot pixel para o digiKam
+Comment[ru]=Модуль коррекции ярких пикселей для digiKam
+Comment[sk]=digiKam plugin pre korekciu vypálených pixelov
+Comment[sr]=digiKam-ов прикључак исправку врућих пиксела
+Comment[sr@Latn]=digiKam-ov priključak ispravku vrućih piksela
+Comment[sv]=Digikam insticksprogram för korrigering av heta bildpunkter
+Comment[tr]=digiKam için beyaz dengesini düzeltme eklentisi
+Comment[uk]=Втулок виправлення гарячих пікселів для Digikam
+Comment[vi]=Phần bổ sung sửa điểm ảnh nóng cho digiKam
+Comment[xx]=xxHot pixel correction plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_hotpixels
+author=Unai Garro, ugarro at sourceforge dot net
diff --git a/src/imageplugins/hotpixels/digikamimageplugin_hotpixels_ui.rc b/src/imageplugins/hotpixels/digikamimageplugin_hotpixels_ui.rc
new file mode 100644
index 00000000..b80d7f5a
--- /dev/null
+++ b/src/imageplugins/hotpixels/digikamimageplugin_hotpixels_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="4" name="digikamimageplugin_hotpixels" >
+
+ <MenuBar>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ <Action name="imageplugin_hotpixels" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_hotpixels" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/hotpixels/hotpixel.h b/src/imageplugins/hotpixels/hotpixel.h
new file mode 100644
index 00000000..bceb539f
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixel.h
@@ -0,0 +1,74 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : Threaded image filter to fix hot pixels
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef HOTPIXEL_H
+#define HOTPIXEL_H
+
+// TQt includes.
+
+#include <tqrect.h>
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class HotPixel
+{
+
+public:
+
+ TQRect rect;
+ int luminosity;
+ int y() const {return rect.y(); };
+ int x() const {return rect.x(); };
+ int width()const {return rect.width(); };
+ int height()const {return rect.height();};
+
+ bool operator==(const HotPixel p) const
+ {
+ //we can say they're same hotpixel spot if they
+ //touch(next to) each other horizontally or vertically, not diagonal corners
+ //return (rect.intersects(p.rect));
+ return (rect != p.rect) && (x() + width() >= p.x() && x() <= p.x() + p.width()
+ && y() + height() >= p.y() && y() <= p.y() + p.height())
+ && !diagonal(rect, p.rect);
+ }
+
+private:
+
+ bool diagonal(TQRect r1,TQRect r2) const
+ {
+ //locate next-to positions
+
+ bool top = r1.y() + height()-1 == r2.y()-1; //r1 is on the top of r2
+ bool left = r1.x() + width()-1 == r2.x()-1; //r1 is on the left of r2
+ bool right = r1.x() == r2.x() + r2.width();
+ bool bottom = r1.y() == r2.y() + r2.height();
+
+ return ((top && left) || (top && right) || (bottom && left) || (bottom && right));
+ }
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // HOTPIXEL_H
diff --git a/src/imageplugins/hotpixels/hotpixelfixer.cpp b/src/imageplugins/hotpixels/hotpixelfixer.cpp
new file mode 100644
index 00000000..d29b8525
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixelfixer.cpp
@@ -0,0 +1,302 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : Threaded image filter to fix hot pixels
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqregexp.h>
+#include <tqstringlist.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "ddebug.h"
+#include "hotpixelfixer.h"
+
+#ifdef HAVE_FLOAT_H
+#if HAVE_FLOAT_H
+# include <float.h>
+#endif
+#endif
+
+#ifndef DBL_MIN
+# define DBL_MIN 1e-37
+#endif
+#ifndef DBL_MAX
+# define DBL_MAX 1e37
+#endif
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+HotPixelFixer::HotPixelFixer(Digikam::DImg *orgImage, TQObject *parent, const TQValueList<HotPixel>& hpList,
+ int interpolationMethod)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "HotPixels")
+{
+ m_hpList = hpList;
+ m_interpolationMethod = interpolationMethod;
+ mWeightList.clear();
+
+ initFilter();
+}
+
+HotPixelFixer::~HotPixelFixer()
+{
+}
+
+void HotPixelFixer::filterImage(void)
+{
+ TQValueList <HotPixel>::ConstIterator it;
+ TQValueList <HotPixel>::ConstIterator end(m_hpList.end());
+ for (it = m_hpList.begin() ; it != end ; ++it)
+ {
+ HotPixel hp = *it;
+ interpolate(m_orgImage, hp, m_interpolationMethod);
+ }
+
+ m_destImage = m_orgImage;
+}
+
+// Interpolates a pixel block
+void HotPixelFixer::interpolate (Digikam::DImg &img, HotPixel &hp, int method)
+{
+ const int xPos = hp.x();
+ const int yPos = hp.y();
+ bool sixtBits = img.sixteenBit();
+
+ // Interpolate pixel.
+ switch (method)
+ {
+ case AVERAGE_INTERPOLATION:
+ {
+ // We implement the bidimendional one first.
+ // TODO: implement the rest of directions (V & H) here
+
+ //case twodim:
+ // {
+ int sum_weight = 0;
+ double vr=0.0,vg=0.0,vb=0.0;
+ int x, y;
+ Digikam::DColor col;
+
+ for (x = xPos; x < xPos+hp.width(); ++x)
+ {
+ if (validPoint(img,TQPoint(x,yPos-1)))
+ {
+ col=img.getPixelColor(x,yPos-1);
+ vr += col.red();
+ vg += col.green();
+ vb += col.blue();
+ ++sum_weight;
+ }
+ if (validPoint(img,TQPoint(x,yPos+hp.height())))
+ {
+ col=img.getPixelColor(x,yPos+hp.height());
+ vr += col.red();
+ vg += col.green();
+ vb += col.blue();
+ ++sum_weight;
+ }
+ }
+
+ for (y = yPos; y < hp.height(); ++y)
+ {
+ if (validPoint(img,TQPoint(xPos-1,y)))
+ {
+ col=img.getPixelColor(xPos,y);
+ vr += col.red();
+ vg += col.green();
+ vb += col.blue();
+ ++sum_weight;
+ }
+ if (validPoint(img,TQPoint(xPos+hp.width(),y)))
+ {
+ col=img.getPixelColor(xPos+hp.width(),y);
+ vr += col.red();
+ vg += col.green();
+ vb += col.blue();
+ ++sum_weight;
+ }
+ }
+
+ if (sum_weight > 0)
+ {
+ vr /= (double)sum_weight;
+ vg /= (double)sum_weight;
+ vb /= (double)sum_weight;
+
+
+ for (x = 0; x < hp.width(); ++x)
+ for (y = 0; y < hp.height(); ++y)
+ if (validPoint(img,TQPoint(xPos+x,yPos+y)))
+ {
+ int alpha=sixtBits ? 65535 : 255;
+ int ir=(int )round(vr),ig=(int) round(vg),ib=(int) round(vb);
+ img.setPixelColor(xPos+x,yPos+y,Digikam::DColor(ir,ig,ib,alpha,sixtBits));
+ }
+ }
+ break;
+ } //Case average
+
+ case LINEAR_INTERPOLATION:
+ //(Bi)linear interpolation.
+ weightPixels (img,hp,LINEAR_INTERPOLATION,TWODIM_DIRECTION,sixtBits ? 65535: 255);
+ break;
+
+ case QUADRATIC_INTERPOLATION:
+ // (Bi)quadratic interpolation.
+ weightPixels (img,hp,QUADRATIC_INTERPOLATION,TWODIM_DIRECTION,sixtBits ? 65535 : 255);
+ break;
+
+ case CUBIC_INTERPOLATION:
+ // (Bi)cubic interpolation.
+ weightPixels (img,hp,CUBIC_INTERPOLATION,TWODIM_DIRECTION,sixtBits ? 65535 : 255);
+ break;
+ } //switch
+}
+
+void HotPixelFixer::weightPixels (Digikam::DImg &img, HotPixel &px, int method, Direction dir,int maxComponent)
+{
+ //TODO: implement direction here too
+
+ for (int iComp = 0; iComp < 3; ++iComp)
+ {
+ // Obtain weight data block.
+
+ Weights w;
+ int polynomeOrder=-1;
+
+ switch (method)
+ {
+ case AVERAGE_INTERPOLATION: // Gilles: to prevent warnings from compiler.
+ break;
+ case LINEAR_INTERPOLATION:
+ polynomeOrder=1;
+ break;
+ case QUADRATIC_INTERPOLATION:
+ polynomeOrder=2;
+ break;
+ case CUBIC_INTERPOLATION:
+ polynomeOrder=3;
+ break;
+ }
+ if (polynomeOrder<0) return;
+
+ // In the one-dimensional case, the width must be 1,
+ // and the size must be stored in height
+
+ w.setWidth(dir == TWODIM_DIRECTION ? px.width() : 1);
+ w.setHeight(dir == HORIZONTAL_DIRECTION ? px.width() : px.height());
+ w.setPolynomeOrder(polynomeOrder);
+ w.setTwoDim(dir == TWODIM_DIRECTION);
+
+ //TODO: check this, it must not recalculate existing calculated weights
+ //for now I don't think it is finding the duplicates fine, so it uses
+ //the previous one always...
+
+ //if (mWeightList.find(w)==mWeightList.end())
+ //{
+ w.calculateWeights();
+
+ // mWeightList.append(w);
+
+ //}
+
+ // Calculate weighted pixel sum.
+ for (int y = 0; y<px.height(); ++y)
+ {
+ for (int x = 0; x < px.width(); ++x)
+ {
+ if (validPoint (img,TQPoint(px.x()+x,px.y()+y)))
+ {
+ double sum_weight = 0.0, v = 0.0;
+ size_t i;
+
+ for (i = 0; i < w.positions().count(); ++i)
+ {
+ // In the one-dimensional case, only the y coordinate is used.
+ const int xx = px.x()+(dir == VERTICAL_DIRECTION ? x :
+ dir== HORIZONTAL_DIRECTION ? w.positions()[i].y() : w.positions()[i].x());
+ const int yy = px.y()+(dir == HORIZONTAL_DIRECTION ? y :
+ w.positions()[i].y());
+
+ if (validPoint (img,TQPoint(xx, yy)))
+ {
+ //TODO: check this. I think it is broken
+ double weight;
+ if (dir==VERTICAL_DIRECTION)
+ {
+ weight = w[i][y][0];
+ }
+ else if (dir==HORIZONTAL_DIRECTION)
+ {
+ weight=w[i][0][x];
+ }
+ else
+ {
+ weight=w[i][y][x];
+ }
+
+ if (iComp==0) v += weight * img.getPixelColor(xx, yy).red();
+ else if (iComp==1) v += weight * img.getPixelColor(xx, yy).green();
+ else v += weight * img.getPixelColor(xx, yy).blue();
+
+ sum_weight += weight;
+ }
+ }
+
+ Digikam::DColor color=img.getPixelColor(px.x()+x,px.y()+y);
+ int component;
+ if (fabs (v) <= DBL_MIN)
+ component=0;
+ else if (sum_weight >= DBL_MIN)
+ {
+ component=(int) (v/sum_weight);
+ //Clamp value
+ if (component<0) component=0;
+ if (component>maxComponent) component=maxComponent;
+ }
+ else if (v >= 0.0)
+ component=maxComponent;
+ else
+ component=0;
+
+ if (iComp==0) color.setRed(component);
+ else if (iComp==1) color.setGreen(component);
+ else color.setBlue(component);
+
+
+ img.setPixelColor(px.x()+x,px.y()+y,color);
+ }
+ }
+ }
+ }
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/hotpixelfixer.h b/src/imageplugins/hotpixels/hotpixelfixer.h
new file mode 100644
index 00000000..2bf8131c
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixelfixer.h
@@ -0,0 +1,98 @@
+/* ============================================================
+ * Authors: Unai Garro <ugarro at users dot sourceforge dot net>
+ * Gilles Caulier <caulier dot gilles at free dot fr>
+ * Date : 2005-03-27
+ * Description : Threaded image filter to fix hot pixels
+ *
+ * Copyright 2005-2007 by Unai Garro and Gilles Caulier
+ *
+ * The algorithm for fixing the hot pixels was based on
+ * the code of jpegpixi, which was released under the GPL license,
+ * and is Copyright (C) 2003, 2004 Martin Dickopp
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================*/
+
+#ifndef HOTPIXELFIXER_H
+#define HOTPIXELFIXER_H
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqobject.h>
+#include <tqvaluelist.h>
+#include <tqrect.h>
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+// Local includes.
+
+#include "hotpixel.h"
+#include "weights.h"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class HotPixelFixer : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ enum InterpolationMethod
+ {
+ AVERAGE_INTERPOLATION = 0,
+ LINEAR_INTERPOLATION = 1,
+ QUADRATIC_INTERPOLATION = 2,
+ CUBIC_INTERPOLATION = 3
+ };
+
+ enum Direction
+ {
+ TWODIM_DIRECTION = 0,
+ VERTICAL_DIRECTION = 1,
+ HORIZONTAL_DIRECTION = 2
+ };
+
+public:
+
+ HotPixelFixer(Digikam::DImg *orgImage, TQObject *parent,
+ const TQValueList<HotPixel>& hpList, int interpolationMethod);
+ ~HotPixelFixer();
+
+private:
+
+ virtual void filterImage(void);
+
+ void interpolate (Digikam::DImg &img,HotPixel &hp, int method);
+ void weightPixels (Digikam::DImg &img, HotPixel &px, int method, Direction dir, int maxComponent);
+
+ inline bool validPoint(Digikam::DImg &img, TQPoint p)
+ {
+ return (p.x()>=0 && p.y()>=0 && p.x()<(long) img.width() && p.y()<(long) img.height());
+ };
+
+ TQValueList <Weights> mWeightList;
+
+private:
+
+ int m_interpolationMethod;
+
+ TQValueList<HotPixel> m_hpList;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // HOTPIXELFIXER_H
diff --git a/src/imageplugins/hotpixels/hotpixelstool.cpp b/src/imageplugins/hotpixels/hotpixelstool.cpp
new file mode 100644
index 00000000..fbcc6c9f
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixelstool.cpp
@@ -0,0 +1,276 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+#include <tqpushbutton.h>
+#include <tqpointarray.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <kimageio.h>
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdefiledialog.h>
+#include <kprogress.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortooliface.h"
+#include "editortoolsettings.h"
+#include "imagedialog.h"
+#include "blackframelistview.h"
+#include "hotpixelstool.h"
+#include "hotpixelstool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+HotPixelsTool::HotPixelsTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("hotpixels");
+ setToolName(i18n("Hot Pixels"));
+ setToolIcon(SmallIcon("hotpixels"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Ok|
+ EditorToolSettings::Try|
+ EditorToolSettings::Cancel,
+ EditorToolSettings::PanIcon);
+
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 3, 2);
+
+ TQLabel *filterMethodLabel = new TQLabel(i18n("Filter:"), m_gboxSettings->plainPage());
+ m_filterMethodCombo = new RComboBox(m_gboxSettings->plainPage());
+ m_filterMethodCombo->insertItem(i18n("Average"));
+ m_filterMethodCombo->insertItem(i18n("Linear"));
+ m_filterMethodCombo->insertItem(i18n("Quadratic"));
+ m_filterMethodCombo->insertItem(i18n("Cubic"));
+ m_filterMethodCombo->setDefaultItem(HotPixelFixer::QUADRATIC_INTERPOLATION);
+
+ m_blackFrameButton = new TQPushButton(i18n("Black Frame..."), m_gboxSettings->plainPage());
+ TQWhatsThis::add(m_blackFrameButton, i18n("<p>Use this button to "
+ "add a new black frame file which will be used by the hot pixels removal filter."));
+
+ m_blackFrameListView = new BlackFrameListView(m_gboxSettings->plainPage());
+
+ grid->addMultiCellWidget(filterMethodLabel, 0, 0, 0, 0);
+ grid->addMultiCellWidget(m_filterMethodCombo, 0, 0, 1, 1);
+ grid->addMultiCellWidget(m_blackFrameButton, 0, 0, 2, 2);
+ grid->addMultiCellWidget(m_blackFrameListView, 1, 2, 0, 2);
+ grid->setRowStretch(3, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "hotpixels Tool", m_gboxSettings->panIconView(),
+ 0, ImagePanelWidget::SeparateViewDuplicate);
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_filterMethodCombo, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_blackFrameButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotAddBlackFrame()));
+
+ connect(m_blackFrameListView, TQ_SIGNAL(blackFrameSelected(TQValueList<HotPixel>, const KURL&)),
+ this, TQ_SLOT(slotBlackFrame(TQValueList<HotPixel>, const KURL&)));
+}
+
+HotPixelsTool::~HotPixelsTool()
+{
+}
+
+void HotPixelsTool::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("hotpixels Tool");
+ m_blackFrameURL = KURL(config->readEntry("Last Black Frame File", TQString()));
+ m_filterMethodCombo->setCurrentItem(config->readNumEntry("Filter Method",
+ m_filterMethodCombo->defaultItem()));
+
+ if (m_blackFrameURL.isValid())
+ {
+ EditorToolIface::editorToolIface()->setToolStartProgress(i18n("Loading: "));
+ BlackFrameListViewItem *item = new BlackFrameListViewItem(m_blackFrameListView, m_blackFrameURL);
+
+ connect(item, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SLOT(slotLoadingProgress(float)));
+
+ connect(item, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SLOT(slotLoadingComplete()));
+ }
+}
+
+void HotPixelsTool::slotLoadingProgress(float v)
+{
+ EditorToolIface::editorToolIface()->setToolProgress((int)(v*100));
+}
+
+void HotPixelsTool::slotLoadingComplete()
+{
+ EditorToolIface::editorToolIface()->setToolStopProgress();
+}
+
+void HotPixelsTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("hotpixels Tool");
+ config->writeEntry("Last Black Frame File", m_blackFrameURL.url());
+ config->writeEntry("Filter Method", m_filterMethodCombo->currentItem());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void HotPixelsTool::slotResetSettings()
+{
+ m_filterMethodCombo->blockSignals(true);
+ m_filterMethodCombo->slotReset();
+ m_filterMethodCombo->blockSignals(false);
+}
+
+void HotPixelsTool::slotAddBlackFrame()
+{
+ KURL url = ImageDialog::getImageURL(kapp->activeWindow(), m_blackFrameURL, i18n("Select Black Frame Image"));
+
+ if (!url.isEmpty())
+ {
+ // Load the selected file and insert into the list.
+
+ m_blackFrameURL = url;
+ m_blackFrameListView->clear();
+ BlackFrameListViewItem *item = new BlackFrameListViewItem(m_blackFrameListView, m_blackFrameURL);
+
+ connect(item, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SLOT(slotLoadingProgress(float)));
+
+ connect(item, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SLOT(slotLoadingComplete()));
+ }
+}
+
+void HotPixelsTool::renderingFinished()
+{
+ m_filterMethodCombo->setEnabled(true);
+ m_blackFrameListView->setEnabled(true);
+}
+
+void HotPixelsTool::prepareEffect()
+{
+ m_filterMethodCombo->setEnabled(false);
+ m_blackFrameListView->setEnabled(false);
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+ int interpolationMethod = m_filterMethodCombo->currentItem();
+
+ TQValueList<HotPixel> hotPixelsRegion;
+ TQRect area = m_previewWidget->getOriginalImageRegionToRender();
+ TQValueList<HotPixel>::Iterator end(m_hotPixelsList.end());
+
+ for (TQValueList<HotPixel>::Iterator it = m_hotPixelsList.begin() ; it != end ; ++it )
+ {
+ HotPixel hp = (*it);
+
+ if ( area.contains( hp.rect ) )
+ {
+ hp.rect.moveTopLeft(TQPoint( hp.rect.x()-area.x(), hp.rect.y()-area.y() ));
+ hotPixelsRegion.append(hp);
+ }
+ }
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(&image, this, hotPixelsRegion, interpolationMethod)));
+}
+
+void HotPixelsTool::prepareFinal()
+{
+ m_filterMethodCombo->setEnabled(false);
+ m_blackFrameListView->setEnabled(false);
+
+ int interpolationMethod = m_filterMethodCombo->currentItem();
+
+ ImageIface iface(0, 0);
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new HotPixelFixer(iface.getOriginalImg(), this,m_hotPixelsList,interpolationMethod)));
+}
+
+void HotPixelsTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void HotPixelsTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Hot Pixels Correction"), filter()->getTargetImage().bits());
+}
+
+void HotPixelsTool::slotBlackFrame(TQValueList<HotPixel> hpList, const KURL& blackFrameURL)
+{
+ m_blackFrameURL = blackFrameURL;
+ m_hotPixelsList = hpList;
+
+ TQPointArray pointList(m_hotPixelsList.size());
+ TQValueList <HotPixel>::Iterator it;
+ int i = 0;
+ TQValueList <HotPixel>::Iterator end(m_hotPixelsList.end());
+
+ for (it = m_hotPixelsList.begin() ; it != end ; ++it, i++)
+ pointList.setPoint(i, (*it).rect.center());
+
+ m_previewWidget->setPanIconHighLightPoints(pointList);
+
+ slotEffect();
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/hotpixelstool.h b/src/imageplugins/hotpixels/hotpixelstool.h
new file mode 100644
index 00000000..727c6387
--- /dev/null
+++ b/src/imageplugins/hotpixels/hotpixelstool.h
@@ -0,0 +1,113 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_HOTPIXELS_H
+#define IMAGEEFFECT_HOTPIXELS_H
+
+#define MAX_PIXEL_DEPTH 4
+
+// TQt includes.
+
+#include <tqvaluelist.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+// Local includes.
+
+#include "hotpixelfixer.h"
+
+class TQPushButton;
+
+namespace KDcrawIface
+{
+class RComboBox;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class BlackFrameListView;
+
+class HotPixelsTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ HotPixelsTool(TQObject *parent);
+ ~HotPixelsTool();
+
+private slots:
+
+ void slotBlackFrame(TQValueList<HotPixel> hpList, const KURL& blackFrameURL);
+ void slotResetSettings();
+ void slotAddBlackFrame();
+ void slotLoadingProgress(float);
+ void slotLoadingComplete();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQPushButton *m_blackFrameButton;
+
+ TQValueList<HotPixel> m_hotPixelsList;
+
+ KURL m_blackFrameURL;
+
+ BlackFrameListView *m_blackFrameListView;
+
+ KDcrawIface::RComboBox *m_filterMethodCombo;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif /* IMAGEEFFECT_HOTPIXELS_H */
diff --git a/src/imageplugins/hotpixels/imageeffect_hotpixels.cpp b/src/imageplugins/hotpixels/imageeffect_hotpixels.cpp
new file mode 100644
index 00000000..67e9a1b2
--- /dev/null
+++ b/src/imageplugins/hotpixels/imageeffect_hotpixels.cpp
@@ -0,0 +1,279 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+#include <tqpushbutton.h>
+#include <tqpointarray.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <kimageio.h>
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdefiledialog.h>
+#include <kprogress.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagedialog.h"
+#include "blackframelistview.h"
+#include "imageeffect_hotpixels.h"
+#include "imageeffect_hotpixels.moc"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+ImageEffect_HotPixels::ImageEffect_HotPixels(TQWidget* parent)
+ : CtrlPanelDlg(parent, i18n("Hot Pixels Correction"),
+ "hotpixels", false, false, false,
+ Digikam::ImagePannelWidget::SeparateViewDuplicate)
+{
+ // No need Abort button action.
+ showButton(User1, false);
+
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Hot Pixels Correction"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin for fixing dots produced by "
+ "hot/stuck/dead pixels from a CCD."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2006, Unai Garro\n(c) 2005-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Unai Garro", I18N_NOOP("Author and maintainer"),
+ "ugarro at sourceforge dot net");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Developer"),
+ "caulier dot gilles at gmail dot com");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings, 3, 2, 0, spacingHint());
+
+ TQLabel *filterMethodLabel = new TQLabel(i18n("Filter:"), gboxSettings);
+ m_filterMethodCombo = new TQComboBox(gboxSettings);
+ m_filterMethodCombo->insertItem(i18n("Average"));
+ m_filterMethodCombo->insertItem(i18n("Linear"));
+ m_filterMethodCombo->insertItem(i18n("Quadratic"));
+ m_filterMethodCombo->insertItem(i18n("Cubic"));
+
+ m_blackFrameButton = new TQPushButton(i18n("Black Frame..."), gboxSettings);
+ setButtonWhatsThis( Apply, i18n("<p>Use this button to add a new black frame file which will "
+ "be used by the hot pixels removal filter.") );
+
+ m_blackFrameListView = new BlackFrameListView(gboxSettings);
+ m_progressBar = new KProgress(100, gboxSettings);
+ m_progressBar->setValue(0);
+ m_progressBar->hide();
+
+ gridSettings->addMultiCellWidget(filterMethodLabel, 0, 0, 0, 0);
+ gridSettings->addMultiCellWidget(m_filterMethodCombo, 0, 0, 1, 1);
+ gridSettings->addMultiCellWidget(m_blackFrameButton, 0, 0, 2, 2);
+ gridSettings->addMultiCellWidget(m_blackFrameListView, 1, 2, 0, 2);
+ gridSettings->addMultiCellWidget(m_progressBar, 3, 3, 0, 2);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_filterMethodCombo, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_blackFrameButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotAddBlackFrame()));
+
+ connect(m_blackFrameListView, TQ_SIGNAL(blackFrameSelected(TQValueList<HotPixel>, const KURL&)),
+ this, TQ_SLOT(slotBlackFrame(TQValueList<HotPixel>, const KURL&)));
+}
+
+ImageEffect_HotPixels::~ImageEffect_HotPixels()
+{
+}
+
+void ImageEffect_HotPixels::readUserSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("hotpixels Tool Dialog");
+ m_blackFrameURL = KURL(config->readEntry("Last Black Frame File", TQString()));
+ m_filterMethodCombo->setCurrentItem(config->readNumEntry("Filter Method",
+ HotPixelFixer::QUADRATIC_INTERPOLATION));
+
+ if (m_blackFrameURL.isValid())
+ {
+ BlackFrameListViewItem *item = new BlackFrameListViewItem(m_blackFrameListView, m_blackFrameURL);
+
+ connect(item, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SLOT(slotLoadingProgress(float)));
+
+ connect(item, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SLOT(slotLoadingComplete()));
+ }
+}
+
+void ImageEffect_HotPixels::writeUserSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("hotpixels Tool Dialog");
+ config->writeEntry("Last Black Frame File", m_blackFrameURL.url());
+ config->writeEntry("Filter Method", m_filterMethodCombo->currentItem());
+ config->sync();
+}
+
+void ImageEffect_HotPixels::resetValues()
+{
+ m_filterMethodCombo->blockSignals(true);
+ m_filterMethodCombo->setCurrentItem(HotPixelFixer::QUADRATIC_INTERPOLATION);
+ m_filterMethodCombo->blockSignals(false);
+}
+
+void ImageEffect_HotPixels::slotAddBlackFrame()
+{
+ KURL url = Digikam::ImageDialog::getImageURL(this, m_blackFrameURL,
+ i18n("Select Black Frame Image"));
+
+ if (!url.isEmpty())
+ {
+ // Load the selected file and insert into the list.
+
+ m_blackFrameURL = url;
+ m_blackFrameListView->clear();
+ BlackFrameListViewItem *item = new BlackFrameListViewItem(m_blackFrameListView, m_blackFrameURL);
+
+ connect(item, TQ_SIGNAL(signalLoadingProgress(float)),
+ this, TQ_SLOT(slotLoadingProgress(float)));
+
+ connect(item, TQ_SIGNAL(signalLoadingComplete()),
+ this, TQ_SLOT(slotLoadingComplete()));
+ }
+}
+
+void ImageEffect_HotPixels::slotLoadingProgress(float v)
+{
+ m_progressBar->show();
+ m_progressBar->setValue((int)(v*100));
+}
+
+void ImageEffect_HotPixels::slotLoadingComplete()
+{
+ m_progressBar->hide();
+}
+
+void ImageEffect_HotPixels::renderingFinished()
+{
+ m_filterMethodCombo->setEnabled(true);
+ m_blackFrameListView->setEnabled(true);
+ enableButton(Apply, true);
+}
+
+void ImageEffect_HotPixels::prepareEffect()
+{
+ m_filterMethodCombo->setEnabled(false);
+ m_blackFrameListView->setEnabled(false);
+ enableButton(Apply, false);
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+ int interpolationMethod = m_filterMethodCombo->currentItem();
+
+ TQValueList<HotPixel> hotPixelsRegion;
+ TQRect area = m_imagePreviewWidget->getOriginalImageRegionToRender();
+ TQValueList<HotPixel>::Iterator end(m_hotPixelsList.end());
+
+ for (TQValueList<HotPixel>::Iterator it = m_hotPixelsList.begin() ; it != end ; ++it )
+ {
+ HotPixel hp = (*it);
+
+ if ( area.contains( hp.rect ) )
+ {
+ hp.rect.moveTopLeft(TQPoint( hp.rect.x()-area.x(), hp.rect.y()-area.y() ));
+ hotPixelsRegion.append(hp);
+ }
+ }
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new HotPixelFixer(&image, this, hotPixelsRegion, interpolationMethod));
+}
+
+void ImageEffect_HotPixels::prepareFinal()
+{
+ m_filterMethodCombo->setEnabled(false);
+ m_blackFrameListView->setEnabled(false);
+ enableButton(Apply, false);
+
+ int interpolationMethod = m_filterMethodCombo->currentItem();
+
+ Digikam::ImageIface iface(0, 0);
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new HotPixelFixer(iface.getOriginalImg(), this,m_hotPixelsList,interpolationMethod));
+}
+
+void ImageEffect_HotPixels::putPreviewData()
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_HotPixels::putFinalData()
+{
+ Digikam::ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Hot Pixels Correction"), m_threadedFilter->getTargetImage().bits());
+}
+
+void ImageEffect_HotPixels::slotBlackFrame(TQValueList<HotPixel> hpList, const KURL& blackFrameURL)
+{
+ m_blackFrameURL = blackFrameURL;
+ m_hotPixelsList = hpList;
+
+ TQPointArray pointList(m_hotPixelsList.size());
+ TQValueList <HotPixel>::Iterator it;
+ int i = 0;
+ TQValueList <HotPixel>::Iterator end(m_hotPixelsList.end());
+
+ for (it = m_hotPixelsList.begin() ; it != end ; ++it, i++)
+ pointList.setPoint(i, (*it).rect.center());
+
+ m_imagePreviewWidget->setPanIconHighLightPoints(pointList);
+
+ slotEffect();
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
diff --git a/src/imageplugins/hotpixels/imageeffect_hotpixels.h b/src/imageplugins/hotpixels/imageeffect_hotpixels.h
new file mode 100644
index 00000000..4a8b0868
--- /dev/null
+++ b/src/imageplugins/hotpixels/imageeffect_hotpixels.h
@@ -0,0 +1,104 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_HOTPIXELS_H
+#define IMAGEEFFECT_HOTPIXELS_H
+
+#define MAX_PIXEL_DEPTH 4
+
+// TQt includes.
+
+#include <tqvaluelist.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+// Local includes.
+
+#include "hotpixelfixer.h"
+
+class TQComboBox;
+class TQPushButton;
+
+class KProgress;
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class BlackFrameListView;
+
+class ImageEffect_HotPixels : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_HotPixels(TQWidget *parent);
+ ~ImageEffect_HotPixels();
+
+private slots:
+
+ void slotLoadingProgress(float v);
+ void slotLoadingComplete();
+
+ void slotBlackFrame(TQValueList<HotPixel> hpList, const KURL& blackFrameURL);
+ void slotAddBlackFrame();
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void abortPreview();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQComboBox *m_filterMethodCombo;
+
+ TQPushButton *m_blackFrameButton;
+
+ TQValueList<HotPixel> m_hotPixelsList;
+
+ KURL m_blackFrameURL;
+
+ KProgress *m_progressBar;
+
+ BlackFrameListView *m_blackFrameListView;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif /* IMAGEEFFECT_HOTPIXELS_H */
diff --git a/src/imageplugins/hotpixels/imageplugin_hotpixels.cpp b/src/imageplugins/hotpixels/imageplugin_hotpixels.cpp
new file mode 100644
index 00000000..864b59dc
--- /dev/null
+++ b/src/imageplugins/hotpixels/imageplugin_hotpixels.cpp
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "hotpixelstool.h"
+#include "imageplugin_hotpixels.h"
+#include "imageplugin_hotpixels.moc"
+
+using namespace DigikamHotPixelsImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_hotpixels,
+ KGenericFactory<ImagePlugin_HotPixels>("digikamimageplugin_hotpixels"));
+
+ImagePlugin_HotPixels::ImagePlugin_HotPixels(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_HotPixels")
+{
+ m_hotpixelsAction = new TDEAction(i18n("Hot Pixels..."), "hotpixels", 0,
+ this, TQ_SLOT(slotHotPixels()),
+ actionCollection(), "imageplugin_hotpixels");
+
+ setXMLFile("digikamimageplugin_hotpixels_ui.rc");
+
+ DDebug() << "ImagePlugin_HotPixels plugin loaded" << endl;
+}
+
+ImagePlugin_HotPixels::~ImagePlugin_HotPixels()
+{
+}
+
+void ImagePlugin_HotPixels::setEnabledActions(bool enable)
+{
+ m_hotpixelsAction->setEnabled(enable);
+}
+
+void ImagePlugin_HotPixels::slotHotPixels()
+{
+ HotPixelsTool *tool = new HotPixelsTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/hotpixels/imageplugin_hotpixels.h b/src/imageplugins/hotpixels/imageplugin_hotpixels.h
new file mode 100644
index 00000000..c639b830
--- /dev/null
+++ b/src/imageplugins/hotpixels/imageplugin_hotpixels.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a digiKam image plugin for fixing dots produced by
+ * hot/stuck/dead pixels from a CCD.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_HOTPIXELS_H
+#define IMAGEPLUGIN_HOTPIXELS_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_HotPixels : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_HotPixels(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_HotPixels();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotHotPixels();
+
+private:
+
+ TDEAction *m_hotpixelsAction;
+};
+
+#endif /* IMAGEPLUGIN_HOTPIXELS_H */
diff --git a/src/imageplugins/hotpixels/weights.cpp b/src/imageplugins/hotpixels/weights.cpp
new file mode 100644
index 00000000..e0d3f246
--- /dev/null
+++ b/src/imageplugins/hotpixels/weights.cpp
@@ -0,0 +1,283 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a class to calculate filter weights
+ *
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstring>
+
+// Local includes.
+
+#include "weights.h"
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+Weights::Weights(const Weights &w)
+{
+ (*this) = w;
+}
+
+void Weights::operator=(const Weights &w)
+{
+ mHeight=w.height();
+ mWidth=w.width();
+ mPositions=(w.positions());
+ mCoefficientNumber=w.coefficientNumber();
+ mTwoDim=w.twoDim();
+ mPolynomeOrder=w.polynomeOrder();
+
+ // Allocate memory and copy weights
+ // if the original one was calculated
+
+ if (!w.weightMatrices()) return;
+ else
+ {
+ double*** origMatrices=w.weightMatrices();
+ mWeightMatrices = new double**[mPositions.count()]; //allocate mPositions.count() matrices
+
+ for (uint i=0; i<mPositions.count(); i++)
+ {
+ mWeightMatrices[i]=new double*[mHeight]; //allocate mHeight rows on each position
+ for (unsigned int j=0; j<mHeight; j++)
+ {
+ mWeightMatrices[i][j]=new double[mWidth]; //Allocate mWidth columns on each row
+ for (unsigned int k=0; k<mWidth; k++)
+ {
+ mWeightMatrices[i][j][k]=origMatrices[i][j][k];
+ }
+ }
+ }
+ }
+}
+
+void Weights::calculateWeights()
+{
+ mCoefficientNumber = (mTwoDim
+ ? ((size_t)mPolynomeOrder + 1) * ((size_t)mPolynomeOrder + 1)
+ : (size_t)mPolynomeOrder + 1);
+ double *matrix; /* num_coeff * num_coeff */
+ double *vector0; /* mPositions.count() * num_coeff */
+ double *vector1; /* mPositions.count() * num_coeff */
+ size_t ix,iy,i,j;
+ int x, y;
+
+ // Determine coordinates of pixels to be sampled
+
+ if (mTwoDim)
+ {
+
+ int iPolynomeOrder=(int) mPolynomeOrder; //lets avoid signed/unsigned comparison warnings
+ int iHeight = (int) height(); //"
+ int iWidth = (int) width(); //"
+
+ for (y = -iPolynomeOrder; y < iHeight + iPolynomeOrder; ++y)
+ {
+ for (x = -iPolynomeOrder; x < iWidth + iPolynomeOrder; ++x)
+ {
+ if ((x < 0 && y < 0 && -x - y < iPolynomeOrder + 2)
+ || (x < 0 && y >= iHeight && -x + y - iHeight < iPolynomeOrder + 1)
+ || (x >= iWidth && y < 0 && x - y - iWidth < iPolynomeOrder + 1)
+ || (x >= iWidth && y >= iHeight && x + y - iWidth - iHeight < iPolynomeOrder)
+ || (x < 0 && y >= 0 && y < iHeight) || (x >= iWidth && y >= 0 && y < iHeight)
+ || (y < 0 && x >= 0 && x < iWidth ) || (y >= iHeight && x >= 0 && x < iWidth))
+ {
+ TQPoint position(x,y);
+ mPositions.append(position);
+ }
+ }
+ }
+ }
+ else
+ {
+ // In the one-dimensional case, only the y coordinate and y size is used. */
+
+ for (y = -mPolynomeOrder; y < 0; ++y)
+ {
+ TQPoint position(0,y);
+ mPositions.append(position);
+ }
+
+ for (y = (int) height(); y < (int) height() + (int) mPolynomeOrder; ++y)
+ {
+ TQPoint position(0,y);
+ mPositions.append(position);
+ }
+ }
+
+ // Allocate memory.
+
+ matrix = new double[mCoefficientNumber*mCoefficientNumber];
+ vector0 = new double[mPositions.count() * mCoefficientNumber];
+ vector1 = new double[mPositions.count() * mCoefficientNumber];
+
+ // Calculate coefficient matrix and vectors
+
+ for (iy = 0; iy < mCoefficientNumber; ++iy)
+ {
+ for (ix = 0; ix < mCoefficientNumber; ++ix)
+ matrix [iy*mCoefficientNumber+ix] = 0.0;
+
+ for (j = 0; j < mPositions.count(); ++j)
+ {
+ vector0 [iy * mPositions.count() + j] = polyTerm (iy, mPositions [j].x(),
+ mPositions [j].y(), mPolynomeOrder);
+
+ for (ix = 0; ix < mCoefficientNumber; ++ix)
+ matrix [iy * mCoefficientNumber + ix] += (vector0 [iy * mPositions.count() + j]
+ * polyTerm (ix, mPositions [j].x(), mPositions[j].y(), mPolynomeOrder));
+ }
+ }
+
+ // Invert matrix.
+
+ matrixInv (matrix, mCoefficientNumber);
+
+ // Multiply inverse matrix with vector.
+
+ for (iy = 0; iy < mCoefficientNumber; ++iy)
+ for (j = 0; j < mPositions.count(); ++j)
+ {
+ vector1 [iy * mPositions.count() + j] = 0.0;
+
+ for (ix = 0; ix < mCoefficientNumber; ++ix)
+ vector1 [iy * mPositions.count() + j] += matrix [iy * mCoefficientNumber + ix]
+ * vector0 [ix * mPositions.count() + j];
+ }
+
+ // Store weights
+
+ mWeightMatrices = new double**[mPositions.count()]; //allocate mPositions.count() matrices
+
+ for (i=0; i<mPositions.count(); i++)
+ {
+ mWeightMatrices[i] = new double*[mHeight]; //allocate mHeight rows on each position
+ for (j=0; j<mHeight; j++)
+ mWeightMatrices[i][j] = new double[mWidth]; //Allocate mWidth columns on each row
+ }
+
+ for (y = 0; y < (int) mHeight; ++y)
+ {
+ for (x = 0; x < (int) mWidth; ++x)
+ {
+ for (j = 0; j < mPositions.count(); ++j)
+ {
+ mWeightMatrices [j][y][x] = 0.0;
+
+ for (iy = 0; iy < mCoefficientNumber; ++iy)
+ mWeightMatrices [j][y][x] += vector1 [iy * mPositions.count() + j]
+ * polyTerm (iy, x, y, mPolynomeOrder);
+
+ mWeightMatrices [j][y][x] *= (double) mPositions.count();
+ }
+ }
+ }
+
+ delete[] vector1;
+ delete[] vector0;
+ delete[] matrix;
+}
+
+bool Weights::operator==(const Weights& ws) const
+{
+ return (mHeight==ws.height() &&
+ mWidth==ws.width() &&
+ mPolynomeOrder==ws.polynomeOrder() &&
+ mTwoDim==ws.twoDim()
+ );
+}
+
+ //Invert a quadratic matrix.
+void Weights::matrixInv (double *const a, const size_t size)
+{
+ double *const b = new double[size * size];
+ size_t ix, iy, j;
+
+ // Copy matrix to new location.
+
+ memcpy (b, a, sizeof (double) * size * size);
+
+ // Set destination matrix to unit matrix.
+
+ for (iy = 0; iy < size; ++iy)
+ for (ix = 0; ix < size; ++ix)
+ a [iy * size + ix] = ix == iy ? 1.0 : 0.0;
+
+ // Convert matrix to upper triangle form.
+
+ for (iy = 0; iy < size - 1; ++iy)
+ {
+ for (j = iy + 1; j < size; ++j)
+ {
+ const double factor = b [j * size + iy] / b [iy * size + iy];
+
+ for (ix = 0; ix < size; ++ix)
+ {
+ b [j * size + ix] -= factor * b [iy * size + ix];
+ a [j * size + ix] -= factor * a [iy * size + ix];
+ }
+ }
+ }
+
+ // Convert matrix to diagonal form.
+
+ for (iy = size - 1; iy > 0; --iy)
+ {
+ for (j = 0; j < iy; ++j)
+ {
+ const double factor = b [j * size + iy] / b [iy * size + iy];
+
+ for (ix = 0; ix < size; ++ix)
+ a [j * size + ix] -= factor * a [iy * size + ix];
+ }
+ }
+
+ // Convert matrix to unit matrix.
+
+ for (iy = 0; iy < size; ++iy)
+ for (ix = 0; ix < size; ++ix)
+ a [iy * size + ix] /= b [iy * size + iy];
+
+ delete [] b;
+}
+
+// Calculates one term of the polynomial
+double Weights::polyTerm (const size_t i_coeff, const int x, const int y, const int poly_order)
+{
+ const size_t x_power = i_coeff / ((size_t)poly_order + 1);
+ const size_t y_power = i_coeff % ((size_t)poly_order + 1);
+ int result;
+ size_t i;
+
+ result = 1;
+
+ for (i = 0; i < x_power; ++i)
+ result *= x;
+
+ for (i = 0; i < y_power; ++i)
+ result *= y;
+
+ return (double)result;
+}
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
diff --git a/src/imageplugins/hotpixels/weights.h b/src/imageplugins/hotpixels/weights.h
new file mode 100644
index 00000000..b82fde89
--- /dev/null
+++ b/src/imageplugins/hotpixels/weights.h
@@ -0,0 +1,90 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-27
+ * Description : a class to calculate filter weights
+ *
+ * Copyright (C) 2005-2006 by Unai Garro <ugarro at users dot sourceforge 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef WEIGHTS_H
+#define WEIGHTS_H
+
+// TQt includes.
+
+#include <tqrect.h>
+#include <tqvaluelist.h>
+
+namespace DigikamHotPixelsImagesPlugin
+{
+
+class Weights
+{
+public:
+
+ Weights(){};
+ Weights(const Weights &w);
+ void operator=(const Weights &w);
+
+ ~Weights()
+ {
+ if (!mWeightMatrices) return;
+ for (unsigned int i=0; i<mPositions.count(); i++)
+ {
+ for (unsigned int j=0; j<mHeight; j++) delete[] mWeightMatrices[i][j];
+ }
+ }
+
+ unsigned int height() const { return mHeight; };
+ unsigned int polynomeOrder() const { return mPolynomeOrder; };
+ bool twoDim() const { return mTwoDim; };
+ unsigned int width() const { return mWidth; };
+
+ void setHeight(int h) { mHeight=h; };
+ void setPolynomeOrder(int order) { mPolynomeOrder=order; };
+ void setTwoDim(bool td) { mTwoDim=td; };
+ void setWidth(int w) { mWidth=w; };
+
+ void calculateWeights();
+ bool operator==(const Weights& ws) const;
+ double** operator[](int n) const { return mWeightMatrices[n]; };
+ const TQValueList <TQPoint> positions() const { return mPositions; };
+
+protected:
+
+ int coefficientNumber() const { return mCoefficientNumber; };
+
+ double*** weightMatrices() const { return mWeightMatrices; };
+
+private:
+
+ double polyTerm (const size_t i_coeff, const int x, const int y, const int poly_order);
+ void matrixInv (double *const a, const size_t size);
+
+private:
+
+ unsigned int mHeight,mWidth;
+ unsigned int mCoefficientNumber;
+ bool mTwoDim;
+ unsigned int mPolynomeOrder;
+ double *** mWeightMatrices; //Stores a list of weight matrices
+ TQValueList <TQPoint> mPositions;
+};
+
+} // NameSpace DigikamHotPixelsImagesPlugin
+
+#endif // WEIGHTS_H
diff --git a/src/imageplugins/infrared/Makefile.am b/src/imageplugins/infrared/Makefile.am
new file mode 100644
index 00000000..1e9cd294
--- /dev/null
+++ b/src/imageplugins/infrared/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_infrared_la_SOURCES = imageplugin_infrared.cpp \
+ infraredtool.cpp infrared.cpp
+
+digikamimageplugin_infrared_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_infrared_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_infrared.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_infrared.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_infrared_ui.rc
+
diff --git a/src/imageplugins/infrared/digikamimageplugin_infrared.desktop b/src/imageplugins/infrared/digikamimageplugin_infrared.desktop
new file mode 100644
index 00000000..716de474
--- /dev/null
+++ b/src/imageplugins/infrared/digikamimageplugin_infrared.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_Infrared
+Name[bg]=Приставка за снимки - Инфрачервен филм
+Name[da]=Plugin for infrarødt
+Name[el]=ΠρόσθετοΕικόνας_Υπέρυθρο
+Name[fi]=Infrapuna
+Name[hr]=Infracrveno
+Name[it]=PluginImmagini_Infrarosso
+Name[ms]=ImagePlugin_Inframerah
+Name[nl]=Afbeeldingsplugin_Infrarood
+Name[sr]=Инфрацрвено
+Name[sr@Latn]=Infracrveno
+Name[sv]=Insticksprogram för infrarött
+Name[tr]=ResimEklentisi_Kızılötesi
+Name[xx]=xxImagePlugin_Infraredxx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Simulate infrared film plugin for digiKam
+Comment[bg]=Приставка на digiKam за наподобяване на снимка с инфрачервен филм
+Comment[ca]=Connector pel digiKam de simulació de pel·lícula d'infraroigs
+Comment[da]=Digikam plugin til at simulere infrarød film
+Comment[de]=digiKam-Modul für die Simulation eines Infrarot-Filmes
+Comment[el]=Πρόσθετο εξομοίωσης υπέρυθρου φιλμ για το digiKam
+Comment[es]=Plugin para digiKam para simular la película infrarroja
+Comment[et]=DigiKami infrapunafilmi matkimise plugin
+Comment[fa]=شبیه‌سازی وصلۀ فیلم مادون قرمز برای digiKam
+Comment[fi]=Jäljittelee infrapunafilmiä
+Comment[gl]=Un plugin de digiKam para simulazón de infravermellos
+Comment[hr]=digiKam dodatak za oponašanje IC filma
+Comment[is]=Íforrit fyrir digiKam sem líkir eftir innrauðri filmu
+Comment[it]=Plugin di simulazione di pellicola infrarossa per digiKam
+Comment[ja]=digiKam 赤外線フィルム効果プラグイン
+Comment[nds]=digiKam-Moduul för't Simuleren vun Infraroot-Filmen
+Comment[nl]=Digikam-plugin voor infraroodfilm-effect
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਸਿਮੂਲੇਸ਼ਨ ਇੰਫਰਾਰੈੱਡ ਫਿਲਮ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam symulująca efekt podczerwonej kliszy
+Comment[pt]=Um 'plugin' do digiKam para simulação de infravermelhos
+Comment[pt_BR]=Um 'plugin' do digiKam para simulação de infravermelhos
+Comment[ru]=Модуль имитирующий инфракрасное фильм для digiKam
+Comment[sk]=digiKam plugin pre napodobenie infračerveného filmu
+Comment[sr]=digiKam-ов прикључак који симулира инфрацрвени филм
+Comment[sr@Latn]=digiKam-ov priključak koji simulira infracrveni film
+Comment[sv]=Digikam insticksprogram för att simulera infraröd film
+Comment[tr]=digiKam için kızılötesi film benzetme eklentisi
+Comment[uk]=Втулок симуляції інфрачервоного фільму для digiKam
+Comment[vi]=Phần bổ sung mô phỏng phim ảnh hồng ngoại cho digiKam
+Comment[xx]=xxSimulate infrared film plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_infrared
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/infrared/digikamimageplugin_infrared_ui.rc b/src/imageplugins/infrared/digikamimageplugin_infrared_ui.rc
new file mode 100644
index 00000000..1df83fa6
--- /dev/null
+++ b/src/imageplugins/infrared/digikamimageplugin_infrared_ui.rc
@@ -0,0 +1,19 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_infrared" >
+ <MenuBar>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_infrared" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_infrared" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/infrared/imageeffect_infrared.cpp b/src/imageplugins/infrared/imageeffect_infrared.cpp
new file mode 100644
index 00000000..f8069255
--- /dev/null
+++ b/src/imageplugins/infrared/imageeffect_infrared.cpp
@@ -0,0 +1,227 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-22
+ * Description : a digiKam image editor plugin for simulate
+ * infrared film.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlcdnumber.h>
+#include <tqslider.h>
+#include <tqlayout.h>
+#include <tqdatetime.h>
+#include <tqcheckbox.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "infrared.h"
+#include "imageeffect_infrared.h"
+#include "imageeffect_infrared.moc"
+
+namespace DigikamInfraredImagesPlugin
+{
+
+ImageEffect_Infrared::ImageEffect_Infrared(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Simulate Infrared Film to Photograph"),
+ "infrared", false, false, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Infrared Film"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to simulate infrared film."),
+ TDEAboutData::License_GPL,
+ "(c) 2005, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 2, 1, 0, spacingHint());
+ TQLabel *label1 = new TQLabel(i18n("Sensitivity (ISO):"), gboxSettings);
+
+ m_sensibilitySlider = new TQSlider(1, 25, 1, 1, TQt::Horizontal, gboxSettings);
+ m_sensibilitySlider->setTracking ( false );
+ m_sensibilitySlider->setTickInterval(1);
+ m_sensibilitySlider->setTickmarks(TQSlider::Below);
+
+ m_sensibilityLCDValue = new TQLCDNumber (4, gboxSettings);
+ m_sensibilityLCDValue->setSegmentStyle ( TQLCDNumber::Flat );
+ m_sensibilityLCDValue->display( TQString::number(200) );
+ whatsThis = i18n("<p>Set here the ISO-sensitivity of the simulated infrared film. "
+ "Increasing this value will increase the proportion of green color in the mix. "
+ "It will also increase the halo effect on the hightlights, and the film "
+ "graininess (if that box is checked).</p>"
+ "<p>Note: to simulate an <b>Ilford SFX200</b> infrared film, use a sensitivity excursion of 200 to 800. "
+ "A sensitivity over 800 simulates <b>Kodak HIE</b> high-speed infrared film. This last one creates a more "
+ "dramatic photographic style.</p>");
+
+ TQWhatsThis::add( m_sensibilityLCDValue, whatsThis);
+ TQWhatsThis::add( m_sensibilitySlider, whatsThis);
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_sensibilitySlider, 1, 1, 0, 0);
+ gridSettings->addMultiCellWidget(m_sensibilityLCDValue, 1, 1, 1, 1);
+
+ // -------------------------------------------------------------
+
+ m_addFilmGrain = new TQCheckBox( i18n("Add film grain"), gboxSettings);
+ m_addFilmGrain->setChecked( true );
+ TQWhatsThis::add( m_addFilmGrain, i18n("<p>This option adds infrared film grain to "
+ "the image depending on ISO-sensitivity."));
+ gridSettings->addMultiCellWidget(m_addFilmGrain, 2, 2, 0, 1);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect( m_sensibilitySlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()) );
+
+ // this connection is necessary to change the LCD display when
+ // the value is changed by single clicking on the slider
+ connect( m_sensibilitySlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotSliderMoved(int)) );
+
+ connect( m_sensibilitySlider, TQ_SIGNAL(sliderMoved(int)),
+ this, TQ_SLOT(slotSliderMoved(int)) );
+
+ connect( m_addFilmGrain, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()) );
+}
+
+ImageEffect_Infrared::~ImageEffect_Infrared()
+{
+}
+
+void ImageEffect_Infrared::renderingFinished()
+{
+ m_sensibilitySlider->setEnabled(true);
+ m_addFilmGrain->setEnabled(true);
+}
+
+void ImageEffect_Infrared::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("infrared Tool Dialog");
+ m_sensibilitySlider->blockSignals(true);
+ m_addFilmGrain->blockSignals(true);
+ m_sensibilitySlider->setValue(config->readNumEntry("SensitivityAjustment", 1));
+ m_addFilmGrain->setChecked(config->readBoolEntry("AddFilmGrain", false));
+ m_sensibilitySlider->blockSignals(false);
+ m_addFilmGrain->blockSignals(false);
+ slotSliderMoved(m_sensibilitySlider->value());
+}
+
+void ImageEffect_Infrared::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("infrared Tool Dialog");
+ config->writeEntry("SensitivityAjustment", m_sensibilitySlider->value());
+ config->writeEntry("AddFilmGrain", m_addFilmGrain->isChecked());
+ config->sync();
+}
+
+void ImageEffect_Infrared::resetValues()
+{
+ m_sensibilitySlider->blockSignals(true);
+ m_addFilmGrain->blockSignals(true);
+ m_sensibilitySlider->setValue(1);
+ m_addFilmGrain->setChecked(false);
+ m_sensibilitySlider->blockSignals(false);
+ m_addFilmGrain->blockSignals(false);
+}
+
+void ImageEffect_Infrared::slotSliderMoved(int v)
+{
+ m_sensibilityLCDValue->display( TQString::number(100 + 100 * v) );
+}
+
+void ImageEffect_Infrared::prepareEffect()
+{
+ m_addFilmGrain->setEnabled(false);
+ m_sensibilitySlider->setEnabled(false);
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+ int s = 100 + 100 * m_sensibilitySlider->value();
+ bool g = m_addFilmGrain->isChecked();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Infrared(&image, this, s, g));
+}
+
+void ImageEffect_Infrared::prepareFinal()
+{
+ m_addFilmGrain->setEnabled(false);
+ m_sensibilitySlider->setEnabled(false);
+
+ int s = 100 + 100 * m_sensibilitySlider->value();
+ bool g = m_addFilmGrain->isChecked();
+
+ Digikam::ImageIface iface(0, 0);
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Infrared(iface.getOriginalImg(), this, s, g));
+}
+
+void ImageEffect_Infrared::putPreviewData(void)
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_Infrared::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Infrared"), m_threadedFilter->getTargetImage().bits());
+}
+
+} // NameSpace DigikamInfraredImagesPlugin
+
diff --git a/src/imageplugins/infrared/imageeffect_infrared.h b/src/imageplugins/infrared/imageeffect_infrared.h
new file mode 100644
index 00000000..d6c28237
--- /dev/null
+++ b/src/imageplugins/infrared/imageeffect_infrared.h
@@ -0,0 +1,76 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-22
+ * Description : a digiKam image editor plugin for simulate
+ * infrared film.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_INFRARED_H
+#define IMAGEEFFECT_INFRARED_H
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+class TQSlider;
+class TQLCDNumber;
+class TQCheckBox;
+
+namespace DigikamInfraredImagesPlugin
+{
+
+class ImageEffect_Infrared : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Infrared(TQWidget* parent);
+ ~ImageEffect_Infrared();
+
+private slots:
+
+ void slotSliderMoved(int);
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQCheckBox *m_addFilmGrain;
+
+ TQSlider *m_sensibilitySlider;
+
+ TQLCDNumber *m_sensibilityLCDValue;
+};
+
+} // NameSpace DigikamInfraredImagesPlugin
+
+#endif /* IMAGEEFFECT_INFRARED_H */
diff --git a/src/imageplugins/infrared/imageplugin_infrared.cpp b/src/imageplugins/infrared/imageplugin_infrared.cpp
new file mode 100644
index 00000000..4b845908
--- /dev/null
+++ b/src/imageplugins/infrared/imageplugin_infrared.cpp
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-22
+ * Description : a digiKam image editor plugin for simulate
+ * infrared film.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "infraredtool.h"
+#include "imageplugin_infrared.h"
+#include "imageplugin_infrared.moc"
+
+using namespace DigikamInfraredImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_infrared,
+ KGenericFactory<ImagePlugin_Infrared>("digikamimageplugin_infrared"));
+
+ImagePlugin_Infrared::ImagePlugin_Infrared(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_Infrared")
+{
+ m_infraredAction = new TDEAction(i18n("Infrared Film..."), "infrared", 0,
+ this, TQ_SLOT(slotInfrared()),
+ actionCollection(), "imageplugin_infrared");
+
+ setXMLFile( "digikamimageplugin_infrared_ui.rc" );
+
+ DDebug() << "ImagePlugin_Infrared plugin loaded" << endl;
+}
+
+ImagePlugin_Infrared::~ImagePlugin_Infrared()
+{
+}
+
+void ImagePlugin_Infrared::setEnabledActions(bool enable)
+{
+ m_infraredAction->setEnabled(enable);
+}
+
+void ImagePlugin_Infrared::slotInfrared()
+{
+ InfraredTool *tool = new InfraredTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/infrared/imageplugin_infrared.h b/src/imageplugins/infrared/imageplugin_infrared.h
new file mode 100644
index 00000000..7b6fa12a
--- /dev/null
+++ b/src/imageplugins/infrared/imageplugin_infrared.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-22
+ * Description : a digiKam image editor plugin for simulate
+ * infrared film.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_INFRARED_H
+#define IMAGEPLUGIN_INFRARED_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_Infrared : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_Infrared(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_Infrared();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotInfrared();
+
+private:
+
+ TDEAction *m_infraredAction;
+};
+
+#endif /* IMAGEPLUGIN_INFRARED_H */
diff --git a/src/imageplugins/infrared/infrared.cpp b/src/imageplugins/infrared/infrared.cpp
new file mode 100644
index 00000000..fa2983d5
--- /dev/null
+++ b/src/imageplugins/infrared/infrared.cpp
@@ -0,0 +1,367 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Infrared threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqdatetime.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimggaussianblur.h"
+#include "imagecurves.h"
+#include "imagehistogram.h"
+#include "dimgimagefilters.h"
+#include "infrared.h"
+
+namespace DigikamInfraredImagesPlugin
+{
+
+Infrared::Infrared(Digikam::DImg *orgImage, TQObject *parent, int sensibility, bool grain)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "Infrared")
+{
+ m_sensibility = sensibility;
+ m_grain = grain;
+ initFilter();
+}
+
+void Infrared::filterImage(void)
+{
+ infraredImage(&m_orgImage, m_sensibility, m_grain);
+}
+
+// This method is based on the Simulate Infrared Film tutorial from GimpGuru.org web site
+// available at this url : http://www.gimpguru.org/Tutorials/SimulatedInfrared/
+
+inline static int intMult8(uint a, uint b)
+{
+ uint t = a * b + 0x80;
+ return ((t >> 8) + t) >> 8;
+}
+
+inline static int intMult16(uint a, uint b)
+{
+ uint t = a * b + 0x8000;
+ return ((t >> 16) + t) >> 16;
+}
+
+/* More info about IR film can be seen at this url :
+
+http://www.pauck.de/marco/photo/infrared/comparison_of_films/comparison_of_films.html
+*/
+
+void Infrared::infraredImage(Digikam::DImg *orgImage, int Sensibility, bool Grain)
+{
+ // Sensibility: 200..2600
+
+ if (Sensibility <= 0) return;
+
+ int Width = orgImage->width();
+ int Height = orgImage->height();
+ int bytesDepth = orgImage->bytesDepth();
+ uint numBytes = orgImage->numBytes();
+ bool sixteenBit = orgImage->sixteenBit();
+ uchar* data = orgImage->bits();
+
+ // Infrared film variables depending on Sensibility.
+ // We can reproduce famous Ilford SFX200 infrared film
+ // http://www.ilford.com/html/us_english/prod_html/sfx200/sfx200.html
+ // This film have a sensibility escursion from 200 to 800 ISO.
+ // Over 800 ISO, we reproduce The Kodak HIE hight speed infrared film.
+
+ // Infrared film grain.
+ int Noise = (Sensibility + 3000) / 10;
+ if (sixteenBit)
+ Noise = (Noise + 1) * 256 - 1;
+
+ int blurRadius = (int)((Sensibility / 200.0) + 1.0); // Gaussian blur infrared hightlight effect
+ // [2 to 5].
+ float greenBoost = 2.1 - (Sensibility / 2000.0); // Infrared green color boost [1.7 to 2.0].
+
+ int nRand, offset, progress;
+
+ uchar* pBWBits = 0; // Black and White conversion.
+ uchar* pBWBlurBits = 0; // Black and White with blur.
+ uchar* pGrainBits = 0; // Grain blured without curves adjustment.
+ uchar* pMaskBits = 0; // Grain mask with curves adjustment.
+ uchar* pOverlayBits = 0; // Overlay to merge with original converted in gray scale.
+ uchar* pOutBits = m_destImage.bits(); // Destination image with merged grain mask and original.
+
+ Digikam::DColor bwData, bwBlurData, grainData, maskData, overData, outData;
+
+ //------------------------------------------
+ // 1 - Create GrayScale green boosted image.
+ //------------------------------------------
+
+ // Convert to gray scale with boosting Green channel.
+ // Infrared film increase green color.
+
+ Digikam::DImg BWImage(Width, Height, sixteenBit); // Black and White conversion.
+ pBWBits = BWImage.bits();
+ memcpy (pBWBits, data, numBytes);
+
+ Digikam::DImgImageFilters().channelMixerImage(pBWBits, Width, Height, sixteenBit, // Image data.
+ true, // Preserve luminosity.
+ true, // Monochrome.
+ 0.4, greenBoost, -0.8, // Red channel gains.
+ 0.0, 1.0, 0.0, // Green channel gains (not used).
+ 0.0, 0.0, 1.0); // Blue channel gains (not used).
+ postProgress( 10 );
+ if (m_cancel)
+ {
+ return;
+ }
+
+ // Apply a Gaussian blur to the black and white image.
+ // This way simulate Infrared film dispersion for the highlights.
+
+ Digikam::DImg BWBlurImage(Width, Height, sixteenBit);
+ pBWBlurBits = BWBlurImage.bits();
+
+ Digikam::DImgGaussianBlur(this, BWImage, BWBlurImage, 10, 20, blurRadius);
+
+ if (m_cancel)
+ {
+ return;
+ }
+
+ //-----------------------------------------------------------------
+ // 2 - Create Gaussian blured averlay mask with grain if necessary.
+ //-----------------------------------------------------------------
+
+
+ if (Grain)
+ {
+
+ // Create gray grain mask.
+
+ TQDateTime dt = TQDateTime::currentDateTime();
+ TQDateTime Y2000( TQDate(2000, 1, 1), TQTime(0, 0, 0) );
+ uint seed = ((uint) dt.secsTo(Y2000));
+
+ pGrainBits = new uchar[numBytes]; // Grain blured without curves adjustment.
+ uchar *ptr;
+ int component;
+ grainData.setSixteenBit(sixteenBit);
+
+ for (int x = 0; !m_cancel && x < Width; x++)
+ {
+ for (int y = 0; !m_cancel && y < Height; y++)
+ {
+ ptr = pGrainBits + x*bytesDepth + (y*Width*bytesDepth);
+
+ nRand = (rand_r(&seed) % Noise) - (Noise / 2);
+ if (sixteenBit)
+ component = CLAMP(32768 + nRand, 0, 65535);
+ else
+ component = CLAMP(128 + nRand, 0, 255);
+
+ grainData.setRed (component);
+ grainData.setGreen(component);
+ grainData.setBlue (component);
+ grainData.setAlpha(0);
+
+ grainData.setPixel(ptr);
+ }
+
+ // Update progress bar in dialog.
+ progress = (int) (30.0 + ((double)x * 10.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress( progress );
+ }
+
+ // Smooth grain mask using gaussian blur.
+
+ Digikam::DImgImageFilters().gaussianBlurImage(pGrainBits, Width, Height, sixteenBit, 1);
+
+ postProgress( 40 );
+ if (m_cancel)
+ {
+ delete [] pGrainBits;
+ return;
+ }
+ }
+
+ postProgress( 50 );
+ if (m_cancel)
+ {
+ delete [] pGrainBits;
+ return;
+ }
+
+ // Normally, film grain tends to be most noticeable in the midtones, and much less
+ // so in the shadows and highlights. Adjust histogram curve to adjust grain like this.
+
+ if (Grain)
+ {
+ Digikam::ImageCurves *grainCurves = new Digikam::ImageCurves(sixteenBit);
+ pMaskBits = new uchar[numBytes]; // Grain mask with curves adjustment.
+
+ // We modify only global luminosity of the grain.
+ if (sixteenBit)
+ {
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 0, TQPoint(0, 0));
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 8, TQPoint(32768, 32768));
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 16, TQPoint(65535, 0));
+ }
+ else
+ {
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 0, TQPoint(0, 0));
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 8, TQPoint(128, 128));
+ grainCurves->setCurvePoint(Digikam::ImageHistogram::ValueChannel, 16, TQPoint(255, 0));
+ }
+
+ // Calculate curves and lut to apply on grain.
+ grainCurves->curvesCalculateCurve(Digikam::ImageHistogram::ValueChannel);
+ grainCurves->curvesLutSetup(Digikam::ImageHistogram::AlphaChannel);
+ grainCurves->curvesLutProcess(pGrainBits, pMaskBits, Width, Height);
+ delete grainCurves;
+
+ // delete it here, not used any more
+ delete [] pGrainBits;
+ pGrainBits = 0;
+ }
+
+ postProgress( 60 );
+ if (m_cancel)
+ {
+ delete [] pGrainBits;
+ delete [] pMaskBits;
+ return;
+ }
+
+ // Merge gray scale image with grain using shade coefficient.
+
+ if (Grain)
+ {
+ pOverlayBits = new uchar[numBytes]; // Overlay to merge with original converted in gray scale.
+
+ // get composer for default blending
+ Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(Digikam::DColorComposer::PorterDuffNone);
+ int alpha;
+
+ int Shade = 52; // This value control the shading pixel effect between original image and grain mask.
+ if (sixteenBit)
+ Shade = (Shade + 1) * 256 - 1;
+
+ for (int x = 0; !m_cancel && x < Width; x++)
+ {
+ for (int y = 0; !m_cancel && y < Height; y++)
+ {
+ int offset = x*bytesDepth + (y*Width*bytesDepth);
+
+ // read color from orig image
+ bwBlurData.setColor(pBWBlurBits + offset, sixteenBit);
+ // read color from mask
+ maskData.setColor(pMaskBits + offset, sixteenBit);
+ // set shade as alpha value - it will be used as source alpha when blending
+ maskData.setAlpha(Shade);
+
+ // compose, write result to blendData.
+ // Preserve alpha, do not blend it (taken from old algorithm - correct?)
+ alpha = bwBlurData.alpha();
+ composer->compose(bwBlurData, maskData);
+ bwBlurData.setAlpha(alpha);
+
+ // write to destination
+ bwBlurData.setPixel(pOverlayBits + offset);
+ }
+
+ // Update progress bar in dialog.
+ progress = (int) (70.0 + ((double)x * 10.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress( progress );
+ }
+
+ delete composer;
+
+ // delete it here, not used any more
+ BWBlurImage.reset();
+ delete [] pMaskBits;
+ pMaskBits = 0;
+ }
+ else
+ {
+ // save a memcpy
+ pOverlayBits = pBWBlurBits;
+ pBWBlurBits = 0;
+ }
+
+ //------------------------------------------
+ // 3 - Merge Grayscale image & overlay mask.
+ //------------------------------------------
+
+ // Merge overlay and gray scale image using 'Overlay' Gimp method for increase the highlight.
+ // The result is usually a brighter picture.
+ // Overlay mode composite value computation is D = A * (B + (2 * B) * (255 - A)).
+
+ outData.setSixteenBit(sixteenBit);
+ for (int x = 0; !m_cancel && x < Width; x++)
+ {
+ for (int y = 0; !m_cancel && y < Height; y++)
+ {
+ offset = x*bytesDepth + (y*Width*bytesDepth);
+
+ bwData.setColor (pBWBits + offset, sixteenBit);
+ overData.setColor(pOverlayBits + offset, sixteenBit);
+
+ if (sixteenBit)
+ {
+ outData.setRed ( intMult16 (bwData.red(), bwData.red() + intMult16(2 * overData.red(), 65535 - bwData.red()) ) );
+ outData.setGreen( intMult16 (bwData.green(), bwData.green() + intMult16(2 * overData.green(), 65535 - bwData.green()) ) );
+ outData.setBlue ( intMult16 (bwData.blue(), bwData.blue() + intMult16(2 * overData.blue(), 65535 - bwData.blue()) ) );
+ }
+ else
+ {
+ outData.setRed ( intMult8 (bwData.red(), bwData.red() + intMult8(2 * overData.red(), 255 - bwData.red()) ) );
+ outData.setGreen( intMult8 (bwData.green(), bwData.green() + intMult8(2 * overData.green(), 255 - bwData.green()) ) );
+ outData.setBlue ( intMult8 (bwData.blue(), bwData.blue() + intMult8(2 * overData.blue(), 255 - bwData.blue()) ) );
+ }
+ outData.setAlpha( bwData.alpha() );
+ outData.setPixel( pOutBits + offset );
+ }
+
+ // Update progress bar in dialog.
+ progress = (int) (80.0 + ((double)x * 20.0) / Width);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete [] pGrainBits;
+ delete [] pMaskBits;
+
+ if (Grain)
+ delete [] pOverlayBits;
+}
+
+} // NameSpace DigikamInfraredImagesPlugin
diff --git a/src/imageplugins/infrared/infrared.h b/src/imageplugins/infrared/infrared.h
new file mode 100644
index 00000000..fc2f89ee
--- /dev/null
+++ b/src/imageplugins/infrared/infrared.h
@@ -0,0 +1,60 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Infrared threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef INFRARED_H
+#define INFRARED_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamInfraredImagesPlugin
+{
+
+class Infrared : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ Infrared(Digikam::DImg *orgImage, TQObject *parent=0, int sensibility=1, bool grain=true);
+
+ ~Infrared(){};
+
+private: // Infrared filter data.
+
+ bool m_grain;
+
+ int m_sensibility;
+
+private: // Infrared filter methods.
+
+ virtual void filterImage(void);
+
+ void infraredImage(Digikam::DImg *orgImage, int Sensibility, bool Grain);
+
+};
+
+} // NameSpace DigikamInfraredImagesPlugin
+
+#endif /* INFRARED_H */
diff --git a/src/imageplugins/infrared/infraredtool.cpp b/src/imageplugins/infrared/infraredtool.cpp
new file mode 100644
index 00000000..f34d1c8a
--- /dev/null
+++ b/src/imageplugins/infrared/infraredtool.cpp
@@ -0,0 +1,225 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-22
+ * Description : a digiKam image editor plugin for simulate
+ * infrared film.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlcdnumber.h>
+#include <tqslider.h>
+#include <tqlayout.h>
+#include <tqdatetime.h>
+#include <tqcheckbox.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "infrared.h"
+#include "infraredtool.h"
+#include "infraredtool.moc"
+
+using namespace Digikam;
+
+namespace DigikamInfraredImagesPlugin
+{
+
+InfraredTool::InfraredTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("infrared");
+ setToolName(i18n("Infrared"));
+ setToolIcon(SmallIcon("infrared"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 3, 1);
+ TQLabel *label1 = new TQLabel(i18n("Sensitivity (ISO):"), m_gboxSettings->plainPage());
+
+ m_sensibilitySlider = new TQSlider(1, 25, 1, 1, TQt::Horizontal, m_gboxSettings->plainPage());
+ m_sensibilitySlider->setTracking(false);
+ m_sensibilitySlider->setTickInterval(1);
+ m_sensibilitySlider->setTickmarks(TQSlider::Below);
+
+ m_sensibilityLCDValue = new TQLCDNumber(4, m_gboxSettings->plainPage());
+ m_sensibilityLCDValue->setSegmentStyle(TQLCDNumber::Flat);
+ m_sensibilityLCDValue->display(TQString::number(200));
+ TQString whatsThis = i18n("<p>Set here the ISO-sensitivity of the simulated infrared film. "
+ "Increasing this value will increase the proportion of green color in the mix. "
+ "It will also increase the halo effect on the hightlights, and the film "
+ "graininess (if that box is checked).</p>"
+ "<p>Note: to simulate an <b>Ilford SFX200</b> infrared film, use a sensitivity excursion of 200 to 800. "
+ "A sensitivity over 800 simulates <b>Kodak HIE</b> high-speed infrared film. This last one creates a more "
+ "dramatic photographic style.</p>");
+
+ TQWhatsThis::add(m_sensibilityLCDValue, whatsThis);
+ TQWhatsThis::add(m_sensibilitySlider, whatsThis);
+
+ // -------------------------------------------------------------
+
+ m_addFilmGrain = new TQCheckBox(i18n("Add film grain"), m_gboxSettings->plainPage());
+ m_addFilmGrain->setChecked(true);
+ TQWhatsThis::add( m_addFilmGrain, i18n("<p>This option adds infrared film grain to "
+ "the image depending on ISO-sensitivity."));
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 1);
+ grid->addMultiCellWidget(m_sensibilitySlider, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_sensibilityLCDValue, 1, 1, 1, 1);
+ grid->addMultiCellWidget(m_addFilmGrain, 2, 2, 0, 1);
+ grid->setRowStretch(3, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "infrared Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect( m_sensibilitySlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()) );
+
+ // this connection is necessary to change the LCD display when
+ // the value is changed by single clicking on the slider
+ connect( m_sensibilitySlider, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotSliderMoved(int)) );
+
+ connect( m_sensibilitySlider, TQ_SIGNAL(sliderMoved(int)),
+ this, TQ_SLOT(slotSliderMoved(int)) );
+
+ connect( m_addFilmGrain, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()) );
+}
+
+InfraredTool::~InfraredTool()
+{
+}
+
+void InfraredTool::renderingFinished()
+{
+ m_sensibilitySlider->setEnabled(true);
+ m_addFilmGrain->setEnabled(true);
+}
+
+void InfraredTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("infrared Tool");
+ m_sensibilitySlider->blockSignals(true);
+ m_addFilmGrain->blockSignals(true);
+ m_sensibilitySlider->setValue(config->readNumEntry("SensitivityAjustment", 1));
+ m_addFilmGrain->setChecked(config->readBoolEntry("AddFilmGrain", false));
+ m_sensibilitySlider->blockSignals(false);
+ m_addFilmGrain->blockSignals(false);
+ slotSliderMoved(m_sensibilitySlider->value());
+}
+
+void InfraredTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("infrared Tool");
+ config->writeEntry("SensitivityAjustment", m_sensibilitySlider->value());
+ config->writeEntry("AddFilmGrain", m_addFilmGrain->isChecked());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void InfraredTool::slotResetSettings()
+{
+ m_sensibilitySlider->blockSignals(true);
+ m_addFilmGrain->blockSignals(true);
+ m_sensibilitySlider->setValue(1);
+ m_addFilmGrain->setChecked(false);
+ m_sensibilitySlider->blockSignals(false);
+ m_addFilmGrain->blockSignals(false);
+}
+
+void InfraredTool::slotSliderMoved(int v)
+{
+ m_sensibilityLCDValue->display( TQString::number(100 + 100 * v) );
+}
+
+void InfraredTool::prepareEffect()
+{
+ m_addFilmGrain->setEnabled(false);
+ m_sensibilitySlider->setEnabled(false);
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+ int s = 100 + 100 * m_sensibilitySlider->value();
+ bool g = m_addFilmGrain->isChecked();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Infrared(&image, this, s, g)));
+}
+
+void InfraredTool::prepareFinal()
+{
+ m_addFilmGrain->setEnabled(false);
+ m_sensibilitySlider->setEnabled(false);
+
+ int s = 100 + 100 * m_sensibilitySlider->value();
+ bool g = m_addFilmGrain->isChecked();
+
+ ImageIface iface(0, 0);
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Infrared(iface.getOriginalImg(), this, s, g)));
+}
+
+void InfraredTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void InfraredTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Infrared"), filter()->getTargetImage().bits());
+}
+
+} // NameSpace DigikamInfraredImagesPlugin
diff --git a/src/imageplugins/infrared/infraredtool.h b/src/imageplugins/infrared/infraredtool.h
new file mode 100644
index 00000000..ddb5144b
--- /dev/null
+++ b/src/imageplugins/infrared/infraredtool.h
@@ -0,0 +1,86 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-22
+ * Description : a digiKam image editor plugin for simulate
+ * infrared film.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef INFRAREDTOOL_H
+#define INFRAREDTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQSlider;
+class TQLCDNumber;
+class TQCheckBox;
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamInfraredImagesPlugin
+{
+
+class InfraredTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ InfraredTool(TQObject* parent);
+ ~InfraredTool();
+
+private slots:
+
+ void slotSliderMoved(int);
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQCheckBox *m_addFilmGrain;
+
+ TQSlider *m_sensibilitySlider;
+
+ TQLCDNumber *m_sensibilityLCDValue;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamInfraredImagesPlugin
+
+#endif /* INFRAREDTOOL_H */
diff --git a/src/imageplugins/inpainting/Makefile.am b/src/imageplugins/inpainting/Makefile.am
new file mode 100644
index 00000000..243253a8
--- /dev/null
+++ b/src/imageplugins/inpainting/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/libs/greycstoration \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_inpainting_la_SOURCES = imageplugin_inpainting.cpp \
+ inpaintingtool.cpp
+
+digikamimageplugin_inpainting_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_inpainting_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -no-undefined -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_inpainting.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_inpainting.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_inpainting_ui.rc
diff --git a/src/imageplugins/inpainting/digikamimageplugin_inpainting.desktop b/src/imageplugins/inpainting/digikamimageplugin_inpainting.desktop
new file mode 100644
index 00000000..09f891a7
--- /dev/null
+++ b/src/imageplugins/inpainting/digikamimageplugin_inpainting.desktop
@@ -0,0 +1,49 @@
+[Desktop Entry]
+Name=ImagePlugin_InPainting
+Name[bg]=Приставка за снимка - Дорисуване
+Name[da]=Plugin til indfyldning
+Name[el]=ΠρόσθετοΕικόνας_Αποζωγραφισμός
+Name[hr]=Bojanje
+Name[it]=PluginImmagini_Reintegrazione
+Name[nl]=Afbeeldingsplugin_Inkleuren
+Name[sr]=Пребојавање
+Name[sr@Latn]=Prebojavanje
+Name[sv]=Insticksprogram för ifyllnad
+Name[tr]=ResimEklentisi_InPainting
+Name[xx]=xxImagePlugin_InPaintingxx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=digiKam plugin to inpaint a photograph
+Comment[bg]=Приставка на digiKam за дорисуване на повредени или липсващи области от снимки
+Comment[ca]=Connector pel digiKam per repintar una fotografia
+Comment[da]=Digikam plugin til at indfylde i et fotografi
+Comment[de]=digiKam-Modul zur Korrektur von Bildfehlern durch Inpainting
+Comment[el]=Πρόσθετο αποζωγραφισμού μιας φωτογραφίας μέσα για το digiKam
+Comment[es]=Plugin para digiKam repintar una parte de una fotografía
+Comment[et]=DigiKami foto objektide kaotamise plugin
+Comment[fa]=وصلۀ digiKam برای کشیدن یک عکس
+Comment[gl]=Un plugin de digiKam para pintar por dentro unha fotografia
+Comment[hr]=digiKam dodatak za bojanje u fotografiji
+Comment[is]=Íforrit fyrir digiKam til að fjarlægja óæskilega hluti úr mynd
+Comment[it]=Plugin di digiKam per reintegrare una fotografia
+Comment[ja]=digiKam 写真修復プラグイン
+Comment[nds]=digiKam-Moduul för de Bildkorrektuur dör Övermalen
+Comment[nl]=Digikam-plugin voor het inkleuren van een foto
+Comment[pa]=ਇੱਕ ਫੋਟੋ-ਗਰਾਫ਼ ਇਨ-ਪੇਂਟ ਲਈ ਡਿਜ਼ੀਕੈਮ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam umożliwiająca zamalowanie fragmentów zdjęcia
+Comment[pt]=Um 'plugin' do digiKam para pintar por dentro uma fotografia
+Comment[pt_BR]=Um 'plugin' do digiKam para pintar por dentro uma fotografia
+Comment[ru]=Модуль подрисовки фотографий для digiKam
+Comment[sk]=digiKam plugin na odstránenie artefaktov
+Comment[sr]=digiKam-ов прикључак за пребојавање фотографије
+Comment[sr@Latn]=digiKam-ov priključak za prebojavanje fotografije
+Comment[sv]=Digikam insticksprogram för att fylla i ett fotografi
+Comment[tr]=TDE Fotoğraf Yöneticisi
+Comment[uk]=Втулок малювання на фотографіях для digiKam
+Comment[vi]=Phần bổ sung sơn vào ảnh chụp cho digiKam
+Comment[xx]=xxdigiKam plugin to inpaint a photographxx
+
+X-TDE-Library=digikamimageplugin_inpainting
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/inpainting/digikamimageplugin_inpainting_ui.rc b/src/imageplugins/inpainting/digikamimageplugin_inpainting_ui.rc
new file mode 100644
index 00000000..a4c13901
--- /dev/null
+++ b/src/imageplugins/inpainting/digikamimageplugin_inpainting_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_inpainting" >
+
+ <MenuBar>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ <Action name="imageplugin_inpainting" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action name="imageplugin_inpainting" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/inpainting/imageeffect_inpainting.cpp b/src/imageplugins/inpainting/imageeffect_inpainting.cpp
new file mode 100644
index 00000000..d7f2f5fe
--- /dev/null
+++ b/src/imageplugins/inpainting/imageeffect_inpainting.cpp
@@ -0,0 +1,466 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-30
+ * Description : a digiKam image editor plugin to inpaint
+ * a photograph
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ include.
+
+#include <cstdio>
+#include <cmath>
+#include <cstring>
+
+// TQt includes.
+
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqtabwidget.h>
+#include <tqtimer.h>
+#include <tqevent.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqbrush.h>
+#include <tqfile.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <kurllabel.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <tdefiledialog.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+#include <tdemessagebox.h>
+#include <knuminput.h>
+#include <tdeglobalsettings.h>
+#include <kpassivepopup.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "greycstorationsettings.h"
+#include "greycstorationwidget.h"
+#include "greycstorationiface.h"
+#include "imageeffect_inpainting.h"
+#include "imageeffect_inpainting.moc"
+
+namespace DigikamInPaintingImagesPlugin
+{
+
+class InPaintingPassivePopup : public KPassivePopup
+{
+public:
+
+ InPaintingPassivePopup(TQWidget* parent) : KPassivePopup(parent), m_parent(parent) {}
+
+protected:
+
+ virtual void positionSelf() { move(m_parent->x() + 30, m_parent->y() + 30); }
+
+private:
+
+ TQWidget* m_parent;
+};
+
+//------------------------------------------------------------------------------------------
+
+void ImageEffect_InPainting::inPainting(TQWidget* parent)
+{
+ // -- check if we actually have a selection --------------------
+
+ Digikam::ImageIface iface(0, 0);
+
+ int w = iface.selectedWidth();
+ int h = iface.selectedHeight();
+
+ if (!w || !h)
+ {
+ InPaintingPassivePopup* popup = new InPaintingPassivePopup(parent);
+ popup->setView(i18n("Inpainting Photograph Tool"),
+ i18n("You need to select a region to inpaint to use "
+ "this tool"));
+ popup->setAutoDelete(true);
+ popup->setTimeout(2500);
+ popup->show();
+ return;
+ }
+
+ // -- run the dlg ----------------------------------------------
+
+ ImageEffect_InPainting_Dialog dlg(parent);
+ dlg.exec();
+}
+
+//------------------------------------------------------------------------------------------
+
+ImageEffect_InPainting_Dialog::ImageEffect_InPainting_Dialog(TQWidget* parent)
+ : Digikam::ImageGuideDlg(parent, i18n("Photograph Inpainting"),
+ "inpainting", true, true, false,
+ Digikam::ImageGuideWidget::HVGuideMode,
+ 0, true, true, true)
+{
+ m_isComputed = false;
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Photograph Inpainting"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to inpaint a photograph."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("David Tschumperle", I18N_NOOP("CImg library"), 0,
+ "http://cimg.sourceforge.net");
+
+ about->addAuthor("Gerhard Kulzer", I18N_NOOP("Feedback and plugin polishing"),
+ "gerhard at kulzer.net");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout(gboxSettings, 2, 1, spacingHint());
+ m_mainTab = new TQTabWidget( gboxSettings );
+
+ TQWidget* firstPage = new TQWidget( m_mainTab );
+ TQGridLayout* grid = new TQGridLayout( firstPage, 2, 2, marginHint(), spacingHint());
+ m_mainTab->addTab( firstPage, i18n("Preset") );
+
+ KURLLabel *cimgLogoLabel = new KURLLabel(firstPage);
+ cimgLogoLabel->setText(TQString());
+ cimgLogoLabel->setURL("http://cimg.sourceforge.net");
+ TDEGlobal::dirs()->addResourceType("logo-cimg", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("logo-cimg", "logo-cimg.png");
+ cimgLogoLabel->setPixmap( TQPixmap( directory + "logo-cimg.png" ) );
+ TQToolTip::add(cimgLogoLabel, i18n("Visit CImg library website"));
+
+ TQLabel *typeLabel = new TQLabel(i18n("Filtering type:"), firstPage);
+ typeLabel->setAlignment ( TQt::AlignRight | TQt::AlignVCenter);
+ m_inpaintingTypeCB = new TQComboBox( false, firstPage );
+ m_inpaintingTypeCB->insertItem( i18n("None") );
+ m_inpaintingTypeCB->insertItem( i18n("Remove Small Artefact") );
+ m_inpaintingTypeCB->insertItem( i18n("Remove Medium Artefact") );
+ m_inpaintingTypeCB->insertItem( i18n("Remove Large Artefact") );
+ TQWhatsThis::add( m_inpaintingTypeCB, i18n("<p>Select the filter preset to use for photograph restoration:<p>"
+ "<b>None</b>: Most common values. Puts settings to default.<p>"
+ "<b>Remove Small Artefact</b>: inpaint small image artefact like image glitch.<p>"
+ "<b>Remove Medium Artefact</b>: inpaint medium image artefact.<p>"
+ "<b>Remove Large Artefact</b>: inpaint image artefact like unwanted object.<p>"));
+
+ grid->addMultiCellWidget(cimgLogoLabel, 0, 0, 1, 1);
+ grid->addMultiCellWidget(typeLabel, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_inpaintingTypeCB, 1, 1, 1, 1);
+ grid->setRowStretch(1, 10);
+
+ // -------------------------------------------------------------
+
+ m_settingsWidget = new Digikam::GreycstorationWidget(m_mainTab);
+
+ gridSettings->addMultiCellWidget(m_mainTab, 0, 0, 1, 1);
+ gridSettings->addMultiCellWidget(new TQLabel(gboxSettings), 1, 1, 1, 1);
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(cimgLogoLabel, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ this, TQ_SLOT(processCImgURL(const TQString&)));
+
+ connect(m_inpaintingTypeCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotResetValues(int)));
+}
+
+ImageEffect_InPainting_Dialog::~ImageEffect_InPainting_Dialog()
+{
+}
+
+void ImageEffect_InPainting_Dialog::renderingFinished()
+{
+ m_mainTab->setEnabled(true);
+}
+
+void ImageEffect_InPainting_Dialog::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("inpainting Tool Dialog");
+
+ Digikam::GreycstorationSettings settings;
+ settings.fastApprox = config->readBoolEntry("FastApprox", true);
+ settings.interp = config->readNumEntry("Interpolation",
+ Digikam::GreycstorationSettings::NearestNeighbor);
+ settings.amplitude = config->readDoubleNumEntry("Amplitude", 20.0);
+ settings.sharpness = config->readDoubleNumEntry("Sharpness", 0.3);
+ settings.anisotropy = config->readDoubleNumEntry("Anisotropy", 1.0);
+ settings.alpha = config->readDoubleNumEntry("Alpha", 0.8);
+ settings.sigma = config->readDoubleNumEntry("Sigma", 2.0);
+ settings.gaussPrec = config->readDoubleNumEntry("GaussPrec", 2.0);
+ settings.dl = config->readDoubleNumEntry("Dl", 0.8);
+ settings.da = config->readDoubleNumEntry("Da", 30.0);
+ settings.nbIter = config->readNumEntry("Iteration", 30);
+ settings.tile = config->readNumEntry("Tile", 512);
+ settings.btile = config->readNumEntry("BTile", 4);
+ m_settingsWidget->setSettings(settings);
+
+ int p = config->readNumEntry("Preset", NoPreset);
+ m_inpaintingTypeCB->setCurrentItem(p);
+ if (p == NoPreset)
+ m_settingsWidget->setEnabled(true);
+ else
+ m_settingsWidget->setEnabled(false);
+}
+
+void ImageEffect_InPainting_Dialog::writeUserSettings()
+{
+ Digikam::GreycstorationSettings settings = m_settingsWidget->getSettings();
+ TDEConfig* config = kapp->config();
+ config->setGroup("inpainting Tool Dialog");
+ config->writeEntry("Preset", m_inpaintingTypeCB->currentItem());
+ config->writeEntry("FastApprox", settings.fastApprox);
+ config->writeEntry("Interpolation", settings.interp);
+ config->writeEntry("Amplitude", settings.amplitude);
+ config->writeEntry("Sharpness", settings.sharpness);
+ config->writeEntry("Anisotropy", settings.anisotropy);
+ config->writeEntry("Alpha", settings.alpha);
+ config->writeEntry("Sigma", settings.sigma);
+ config->writeEntry("GaussPrec", settings.gaussPrec);
+ config->writeEntry("Dl", settings.dl);
+ config->writeEntry("Da", settings.da);
+ config->writeEntry("Iteration", settings.nbIter);
+ config->writeEntry("Tile", settings.tile);
+ config->writeEntry("BTile", settings.btile);
+ config->sync();
+}
+
+void ImageEffect_InPainting_Dialog::slotResetValues(int i)
+{
+ if (i == NoPreset)
+ m_settingsWidget->setEnabled(true);
+ else
+ m_settingsWidget->setEnabled(false);
+
+ resetValues();
+}
+
+void ImageEffect_InPainting_Dialog::resetValues()
+{
+ Digikam::GreycstorationSettings settings;
+ settings.setInpaintingDefaultSettings();
+
+ switch(m_inpaintingTypeCB->currentItem())
+ {
+ case RemoveSmallArtefact:
+ // We use default settings here.
+ break;
+
+ case RemoveMediumArtefact:
+ {
+ settings.amplitude = 50.0;
+ settings.nbIter = 50;
+ break;
+ }
+
+ case RemoveLargeArtefact:
+ {
+ settings.amplitude = 100.0;
+ settings.nbIter = 100;
+ break;
+ }
+ }
+
+ m_settingsWidget->setSettings(settings);
+}
+
+void ImageEffect_InPainting_Dialog::processCImgURL(const TQString& url)
+{
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+void ImageEffect_InPainting_Dialog::prepareEffect()
+{
+ m_mainTab->setEnabled(false);
+
+ Digikam::ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ m_originalImage = Digikam::DImg(iface.originalWidth(), iface.originalHeight(),
+ iface.originalSixteenBit(), iface.originalHasAlpha(), data);
+ delete [] data;
+
+ // Selected area from the image and mask creation:
+ //
+ // We optimize the computation time to use the current selected area in image editor
+ // and to create an inpainting mask with it. Because inpainting is done by interpolation
+ // neighboor pixels which can be located far from the selected area, we need to ajust the
+ // mask size in according with the parameter algorithms, especially 'amplitude'.
+ // Mask size is computed like this :
+ //
+ // (image_size_x + 2*amplitude , image_size_y + 2*amplitude)
+
+
+ TQRect selectionRect = TQRect(iface.selectedXOrg(), iface.selectedYOrg(),
+ iface.selectedWidth(), iface.selectedHeight());
+
+ TQPixmap inPaintingMask(iface.originalWidth(), iface.originalHeight());
+ inPaintingMask.fill(TQt::black);
+ TQPainter p(&inPaintingMask);
+ p.fillRect( selectionRect, TQBrush(TQt::white) );
+ p.end();
+
+ Digikam::GreycstorationSettings settings = m_settingsWidget->getSettings();
+
+ int x1 = (int)(selectionRect.left() - 2*settings.amplitude);
+ int y1 = (int)(selectionRect.top() - 2*settings.amplitude);
+ int x2 = (int)(selectionRect.right() + 2*settings.amplitude);
+ int y2 = (int)(selectionRect.bottom() + 2*settings.amplitude);
+ m_maskRect = TQRect(x1, y1, x2-x1, y2-y1);
+
+ // Mask area normalization.
+ // We need to check if mask area is out of image size else inpainting give strange results.
+
+ if (m_maskRect.left() < 0) m_maskRect.setLeft(0);
+ if (m_maskRect.top() < 0) m_maskRect.setTop(0);
+ if (m_maskRect.right() > iface.originalWidth()) m_maskRect.setRight(iface.originalWidth());
+ if (m_maskRect.bottom() > iface.originalHeight()) m_maskRect.setBottom(iface.originalHeight());
+
+ m_maskImage = inPaintingMask.convertToImage().copy(m_maskRect);
+ m_cropImage = m_originalImage.copy(m_maskRect);
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Digikam::GreycstorationIface(
+ &m_cropImage,
+ settings,
+ Digikam::GreycstorationIface::InPainting,
+ 0, 0,
+ m_maskImage, this));
+}
+
+void ImageEffect_InPainting_Dialog::prepareFinal()
+{
+ if (!m_isComputed)
+ {
+ setProgressVisible(true);
+ prepareEffect();
+ }
+ else
+ {
+ putFinalData();
+ kapp->restoreOverrideCursor();
+ accept();
+ }
+}
+
+void ImageEffect_InPainting_Dialog::putPreviewData()
+{
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+ Digikam::GreycstorationSettings settings = m_settingsWidget->getSettings();
+
+ m_cropImage = m_threadedFilter->getTargetImage();
+ TQRect cropSel((int)(2*settings.amplitude), (int)(2*settings.amplitude),
+ iface->selectedWidth(), iface->selectedHeight());
+ Digikam::DImg imDest = m_cropImage.copy(cropSel);
+
+ iface->putPreviewImage((imDest.smoothScale(iface->previewWidth(),
+ iface->previewHeight())).bits());
+ m_imagePreviewWidget->updatePreview();
+ m_isComputed = true;
+}
+
+void ImageEffect_InPainting_Dialog::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ if (!m_isComputed)
+ m_cropImage = m_threadedFilter->getTargetImage();
+
+ m_originalImage.bitBltImage(&m_cropImage, m_maskRect.left(), m_maskRect.top());
+
+ iface.putOriginalImage(i18n("InPainting"), m_originalImage.bits());
+}
+
+void ImageEffect_InPainting_Dialog::slotUser3()
+{
+ KURL loadInpaintingFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Inpainting Settings File to Load")) );
+ if( loadInpaintingFile.isEmpty() )
+ return;
+
+ TQFile file(loadInpaintingFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ if (!m_settingsWidget->loadSettings(file, TQString("# Photograph Inpainting Configuration File V2")))
+ {
+ KMessageBox::error(this,
+ i18n("\"%1\" is not a Photograph Inpainting settings text file.")
+ .arg(loadInpaintingFile.fileName()));
+ file.close();
+ return;
+ }
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot load settings from the Photograph Inpainting text file."));
+
+ file.close();
+ m_inpaintingTypeCB->blockSignals(true);
+ m_inpaintingTypeCB->setCurrentItem(NoPreset);
+ m_inpaintingTypeCB->blockSignals(false);
+ m_settingsWidget->setEnabled(true);
+}
+
+void ImageEffect_InPainting_Dialog::slotUser2()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Inpainting Settings File to Save")) );
+ if( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ m_settingsWidget->saveSettings(file, TQString("# Photograph Inpainting Configuration File V2"));
+ else
+ KMessageBox::error(this, i18n("Cannot save settings to the Photograph Inpainting text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamInPaintingImagesPlugin
+
diff --git a/src/imageplugins/inpainting/imageeffect_inpainting.h b/src/imageplugins/inpainting/imageeffect_inpainting.h
new file mode 100644
index 00000000..542e9504
--- /dev/null
+++ b/src/imageplugins/inpainting/imageeffect_inpainting.h
@@ -0,0 +1,116 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-30
+ * Description : a digiKam image editor plugin to inpaint
+ * a photograph
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+
+#ifndef IMAGEEFFECT_INPAINTING_H
+#define IMAGEEFFECT_INPAINTING_H
+
+// TQt include.
+
+#include <tqimage.h>
+#include <tqrect.h>
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "dimg.h"
+#include "imageguidedlg.h"
+
+class TQTabWidget;
+class TQComboBox;
+
+namespace Digikam
+{
+class GreycstorationWidget;
+}
+
+namespace DigikamInPaintingImagesPlugin
+{
+
+class ImageEffect_InPainting
+{
+public:
+
+ static void inPainting(TQWidget *parent);
+};
+
+//-----------------------------------------------------------
+
+class ImageEffect_InPainting_Dialog : public Digikam::ImageGuideDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_InPainting_Dialog(TQWidget* parent);
+ ~ImageEffect_InPainting_Dialog();
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+ void readUserSettings();
+ void processCImgURL(const TQString&);
+ void slotResetValues(int);
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ enum InPaintingFilteringPreset
+ {
+ NoPreset=0,
+ RemoveSmallArtefact,
+ RemoveMediumArtefact,
+ RemoveLargeArtefact
+ };
+
+ bool m_isComputed;
+
+ TQRect m_maskRect;
+
+ TQImage m_maskImage;
+
+ TQComboBox *m_inpaintingTypeCB;
+
+ TQTabWidget *m_mainTab;
+
+ Digikam::DImg m_originalImage;
+ Digikam::DImg m_cropImage;
+
+ Digikam::GreycstorationWidget *m_settingsWidget;
+};
+
+} // NameSpace DigikamInPaintingImagesPlugin
+
+#endif /* IMAGEEFFECT_INPAINTING_H */
diff --git a/src/imageplugins/inpainting/imageplugin_inpainting.cpp b/src/imageplugins/inpainting/imageplugin_inpainting.cpp
new file mode 100644
index 00000000..2c1e30f3
--- /dev/null
+++ b/src/imageplugins/inpainting/imageplugin_inpainting.cpp
@@ -0,0 +1,97 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-30
+ * Description : a digiKam image editor plugin to inpaint
+ * a photograph
+ *
+ * Copyright (C) 2005-2009 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "imageiface.h"
+#include "inpaintingtool.h"
+#include "imageplugin_inpainting.h"
+#include "imageplugin_inpainting.moc"
+
+using namespace DigikamInPaintingImagesPlugin;
+using namespace Digikam;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_inpainting,
+ KGenericFactory<ImagePlugin_InPainting>("digikamimageplugin_inpainting"));
+
+ImagePlugin_InPainting::ImagePlugin_InPainting(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_InPainting")
+{
+ m_inPaintingAction = new TDEAction(i18n("Inpainting..."), "inpainting",
+ CTRL+Key_E,
+ this, TQ_SLOT(slotInPainting()),
+ actionCollection(), "imageplugin_inpainting");
+
+ m_inPaintingAction->setWhatsThis( i18n( "This filter can be used to inpaint a part in a photo. "
+ "Select a region to inpaint to use this option.") );
+
+ setXMLFile( "digikamimageplugin_inpainting_ui.rc" );
+
+ DDebug() << "ImagePlugin_InPainting plugin loaded" << endl;
+}
+
+ImagePlugin_InPainting::~ImagePlugin_InPainting()
+{
+}
+
+void ImagePlugin_InPainting::setEnabledActions(bool enable)
+{
+ m_inPaintingAction->setEnabled(enable);
+}
+
+void ImagePlugin_InPainting::slotInPainting()
+{
+
+ ImageIface iface(0, 0);
+
+ int w = iface.selectedWidth();
+ int h = iface.selectedHeight();
+
+ if (!w || !h)
+ {
+ InPaintingPassivePopup* popup = new InPaintingPassivePopup(kapp->activeWindow());
+ popup->setView(i18n("Inpainting Photograph Tool"),
+ i18n("You need to select a region to inpaint to use "
+ "this tool"));
+ popup->setAutoDelete(true);
+ popup->setTimeout(2500);
+ popup->show();
+ return;
+ }
+
+ // -- run the dlg ----------------------------------------------
+
+ InPaintingTool *tool = new InPaintingTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/inpainting/imageplugin_inpainting.h b/src/imageplugins/inpainting/imageplugin_inpainting.h
new file mode 100644
index 00000000..fb2b1f5c
--- /dev/null
+++ b/src/imageplugins/inpainting/imageplugin_inpainting.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-30
+ * Description : a digiKam image editor plugin to inpaint
+ * a photograph
+ *
+ * Copyright (C) 2005-2009 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_INPAINTING_H
+#define IMAGEPLUGIN_INPAINTING_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_InPainting : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_InPainting(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_InPainting();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotInPainting();
+
+private:
+
+ TDEAction *m_inPaintingAction;
+};
+
+#endif /* IMAGEPLUGIN_INPAINTING_H */
diff --git a/src/imageplugins/inpainting/inpaintingtool.cpp b/src/imageplugins/inpainting/inpaintingtool.cpp
new file mode 100644
index 00000000..2ada52bf
--- /dev/null
+++ b/src/imageplugins/inpainting/inpaintingtool.cpp
@@ -0,0 +1,430 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-30
+ * Description : a digiKam image editor plugin to inpaint
+ * a photograph
+ *
+ * Copyright (C) 2005-2009 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+#include <cmath>
+#include <cstring>
+
+// TQt includes.
+
+#include <tqbrush.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqevent.h>
+#include <tqfile.h>
+#include <tqframe.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqpushbutton.h>
+#include <tqtabwidget.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kcursor.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdepopupmenu.h>
+#include <kprogress.h>
+#include <kstandarddirs.h>
+#include <kurllabel.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimgthreadedfilter.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "editortoolsettings.h"
+#include "greycstorationsettings.h"
+#include "greycstorationwidget.h"
+#include "greycstorationiface.h"
+#include "inpaintingtool.h"
+#include "inpaintingtool.moc"
+
+using namespace Digikam;
+
+namespace DigikamInPaintingImagesPlugin
+{
+
+InPaintingTool::InPaintingTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("inpainting");
+ setToolName(i18n("Inpainting"));
+ setToolIcon(SmallIcon("inpainting"));
+
+ m_isComputed = false;
+
+ m_previewWidget = new ImageWidget("inpainting Tool", 0,
+ i18n("<p>Here you can see the image selection preview with "
+ "inpainting applied."),
+ true, ImageGuideWidget::HVGuideMode, false, true);
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Try|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+ TQGridLayout* gridSettings = new TQGridLayout(m_gboxSettings->plainPage(), 2, 1);
+ m_mainTab = new TQTabWidget( m_gboxSettings->plainPage() );
+
+ TQWidget* firstPage = new TQWidget( m_mainTab );
+ TQGridLayout* grid = new TQGridLayout( firstPage, 2, 2);
+ m_mainTab->addTab( firstPage, i18n("Preset") );
+
+ KURLLabel *cimgLogoLabel = new KURLLabel(firstPage);
+ cimgLogoLabel->setText(TQString());
+ cimgLogoLabel->setURL("http://cimg.sourceforge.net");
+ TDEGlobal::dirs()->addResourceType("logo-cimg", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("logo-cimg", "logo-cimg.png");
+ cimgLogoLabel->setPixmap( TQPixmap( directory + "logo-cimg.png" ) );
+ TQToolTip::add(cimgLogoLabel, i18n("Visit CImg library website"));
+
+ TQLabel *typeLabel = new TQLabel(i18n("Filtering type:"), firstPage);
+ typeLabel->setAlignment ( TQt::AlignRight | TQt::AlignVCenter);
+ m_inpaintingTypeCB = new TQComboBox( false, firstPage );
+ m_inpaintingTypeCB->insertItem( i18n("None") );
+ m_inpaintingTypeCB->insertItem( i18n("Remove Small Artefact") );
+ m_inpaintingTypeCB->insertItem( i18n("Remove Medium Artefact") );
+ m_inpaintingTypeCB->insertItem( i18n("Remove Large Artefact") );
+ TQWhatsThis::add( m_inpaintingTypeCB, i18n("<p>Select the filter preset to use for photograph restoration:<p>"
+ "<b>None</b>: Most common values. Puts settings to default.<p>"
+ "<b>Remove Small Artefact</b>: inpaint small image artefact like image glitch.<p>"
+ "<b>Remove Medium Artefact</b>: inpaint medium image artefact.<p>"
+ "<b>Remove Large Artefact</b>: inpaint image artefact like unwanted object.<p>"));
+
+ grid->addMultiCellWidget(cimgLogoLabel, 0, 0, 1, 1);
+ grid->addMultiCellWidget(typeLabel, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_inpaintingTypeCB, 1, 1, 1, 1);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+ grid->setRowStretch(1, 10);
+
+ // -------------------------------------------------------------
+
+ m_settingsWidget = new GreycstorationWidget(m_mainTab);
+
+ gridSettings->addMultiCellWidget(m_mainTab, 0, 0, 1, 1);
+ gridSettings->addMultiCellWidget(new TQLabel(m_gboxSettings->plainPage()), 1, 1, 1, 1);
+ gridSettings->setMargin(m_gboxSettings->spacingHint());
+ gridSettings->setSpacing(m_gboxSettings->spacingHint());
+ gridSettings->setRowStretch(1, 10);
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(cimgLogoLabel, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ this, TQ_SLOT(processCImgURL(const TQString&)));
+
+ connect(m_inpaintingTypeCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotResetValues(int)));
+
+ // -------------------------------------------------------------
+
+ GreycstorationSettings defaults;
+ defaults.setInpaintingDefaultSettings();
+ m_settingsWidget->setDefaultSettings(defaults);
+}
+
+InPaintingTool::~InPaintingTool()
+{
+}
+
+void InPaintingTool::renderingFinished()
+{
+ m_mainTab->setEnabled(true);
+}
+
+void InPaintingTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("inpainting Tool");
+
+ GreycstorationSettings settings;
+ GreycstorationSettings defaults;
+ defaults.setInpaintingDefaultSettings();
+
+ settings.fastApprox = config->readBoolEntry("FastApprox", defaults.fastApprox);
+ settings.interp = config->readNumEntry("Interpolation", defaults.interp);
+ settings.amplitude = config->readDoubleNumEntry("Amplitude", defaults.amplitude);
+ settings.sharpness = config->readDoubleNumEntry("Sharpness", defaults.sharpness);
+ settings.anisotropy = config->readDoubleNumEntry("Anisotropy", defaults.anisotropy);
+ settings.alpha = config->readDoubleNumEntry("Alpha", defaults.alpha);
+ settings.sigma = config->readDoubleNumEntry("Sigma", defaults.sigma);
+ settings.gaussPrec = config->readDoubleNumEntry("GaussPrec", defaults.gaussPrec);
+ settings.dl = config->readDoubleNumEntry("Dl", defaults.dl);
+ settings.da = config->readDoubleNumEntry("Da", defaults.da);
+ settings.nbIter = config->readNumEntry("Iteration", defaults.nbIter);
+ settings.tile = config->readNumEntry("Tile", defaults.tile);
+ settings.btile = config->readNumEntry("BTile", defaults.btile);
+ m_settingsWidget->setSettings(settings);
+
+ int p = config->readNumEntry("Preset", NoPreset);
+ m_inpaintingTypeCB->setCurrentItem(p);
+ if (p == NoPreset)
+ m_settingsWidget->setEnabled(true);
+ else
+ m_settingsWidget->setEnabled(false);
+}
+
+void InPaintingTool::writeSettings()
+{
+ GreycstorationSettings settings = m_settingsWidget->getSettings();
+ TDEConfig* config = kapp->config();
+ config->setGroup("inpainting Tool");
+ config->writeEntry("Preset", m_inpaintingTypeCB->currentItem());
+ config->writeEntry("FastApprox", settings.fastApprox);
+ config->writeEntry("Interpolation", settings.interp);
+ config->writeEntry("Amplitude", settings.amplitude);
+ config->writeEntry("Sharpness", settings.sharpness);
+ config->writeEntry("Anisotropy", settings.anisotropy);
+ config->writeEntry("Alpha", settings.alpha);
+ config->writeEntry("Sigma", settings.sigma);
+ config->writeEntry("GaussPrec", settings.gaussPrec);
+ config->writeEntry("Dl", settings.dl);
+ config->writeEntry("Da", settings.da);
+ config->writeEntry("Iteration", settings.nbIter);
+ config->writeEntry("Tile", settings.tile);
+ config->writeEntry("BTile", settings.btile);
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void InPaintingTool::slotResetValues(int i)
+{
+ if (i == NoPreset)
+ m_settingsWidget->setEnabled(true);
+ else
+ m_settingsWidget->setEnabled(false);
+
+ slotResetSettings();
+}
+
+void InPaintingTool::slotResetSettings()
+{
+ GreycstorationSettings settings;
+ settings.setInpaintingDefaultSettings();
+
+ switch(m_inpaintingTypeCB->currentItem())
+ {
+ case RemoveSmallArtefact:
+ // We use default settings here.
+ break;
+
+ case RemoveMediumArtefact:
+ {
+ settings.amplitude = 50.0;
+ settings.nbIter = 50;
+ break;
+ }
+
+ case RemoveLargeArtefact:
+ {
+ settings.amplitude = 100.0;
+ settings.nbIter = 100;
+ break;
+ }
+ }
+
+ m_settingsWidget->setSettings(settings);
+}
+
+void InPaintingTool::processCImgURL(const TQString& url)
+{
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+void InPaintingTool::prepareEffect()
+{
+ m_mainTab->setEnabled(false);
+
+ ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ m_originalImage = DImg(iface.originalWidth(), iface.originalHeight(),
+ iface.originalSixteenBit(), iface.originalHasAlpha(), data);
+ delete [] data;
+
+ // Selected area from the image and mask creation:
+ //
+ // We optimize the computation time to use the current selected area in image editor
+ // and to create an inpainting mask with it. Because inpainting is done by interpolation
+ // neighboor pixels which can be located far from the selected area, we need to ajust the
+ // mask size in according with the parameter algorithms, especially 'amplitude'.
+ // Mask size is computed like this :
+ //
+ // (image_size_x + 2*amplitude , image_size_y + 2*amplitude)
+
+
+ TQRect selectionRect = TQRect(iface.selectedXOrg(), iface.selectedYOrg(),
+ iface.selectedWidth(), iface.selectedHeight());
+
+ TQPixmap inPaintingMask(iface.originalWidth(), iface.originalHeight());
+ inPaintingMask.fill(TQt::black);
+ TQPainter p(&inPaintingMask);
+ p.fillRect( selectionRect, TQBrush(TQt::white) );
+ p.end();
+
+ GreycstorationSettings settings = m_settingsWidget->getSettings();
+
+ int x1 = (int)(selectionRect.left() - 2*settings.amplitude);
+ int y1 = (int)(selectionRect.top() - 2*settings.amplitude);
+ int x2 = (int)(selectionRect.right() + 2*settings.amplitude);
+ int y2 = (int)(selectionRect.bottom() + 2*settings.amplitude);
+ m_maskRect = TQRect(x1, y1, x2-x1, y2-y1);
+
+ // Mask area normalization.
+ // We need to check if mask area is out of image size else inpainting give strange results.
+
+ if (m_maskRect.left() < 0) m_maskRect.setLeft(0);
+ if (m_maskRect.top() < 0) m_maskRect.setTop(0);
+ if (m_maskRect.right() > iface.originalWidth()) m_maskRect.setRight(iface.originalWidth());
+ if (m_maskRect.bottom() > iface.originalHeight()) m_maskRect.setBottom(iface.originalHeight());
+
+ m_maskImage = inPaintingMask.convertToImage().copy(m_maskRect);
+ m_cropImage = m_originalImage.copy(m_maskRect);
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(
+ new GreycstorationIface(
+ &m_cropImage,
+ settings,
+ GreycstorationIface::InPainting,
+ 0, 0,
+ m_maskImage, this)));
+}
+
+void InPaintingTool::prepareFinal()
+{
+ if (!m_isComputed)
+ {
+ prepareEffect();
+ }
+ else
+ {
+ Digikam::DImgThreadedFilter::EventData *eventData = new Digikam::DImgThreadedFilter::EventData();
+ eventData->progress = 100;
+ eventData->starting = false;
+ eventData->success = true;
+ TQApplication::postEvent(this, new TQCustomEvent(TQEvent::User, eventData));
+ }
+}
+
+void InPaintingTool::putPreviewData()
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+ GreycstorationSettings settings = m_settingsWidget->getSettings();
+
+ m_cropImage = filter()->getTargetImage();
+ TQRect cropSel((int)(2*settings.amplitude), (int)(2*settings.amplitude),
+ iface->selectedWidth(), iface->selectedHeight());
+ DImg imDest = m_cropImage.copy(cropSel);
+
+ iface->putPreviewImage((imDest.smoothScale(iface->previewWidth(),
+ iface->previewHeight())).bits());
+ m_previewWidget->updatePreview();
+ m_isComputed = true;
+}
+
+void InPaintingTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+
+ if (!m_isComputed)
+ m_cropImage = filter()->getTargetImage();
+
+ m_originalImage.bitBltImage(&m_cropImage, m_maskRect.left(), m_maskRect.top());
+
+ iface.putOriginalImage(i18n("InPainting"), m_originalImage.bits());
+}
+
+void InPaintingTool::slotLoadSettings()
+{
+ KURL loadInpaintingFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Inpainting Settings File to Load")) );
+ if( loadInpaintingFile.isEmpty() )
+ return;
+
+ TQFile file(loadInpaintingFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ if (!m_settingsWidget->loadSettings(file, TQString("# Photograph Inpainting Configuration File V2")))
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" is not a Photograph Inpainting settings text file.")
+ .arg(loadInpaintingFile.fileName()));
+ file.close();
+ return;
+ }
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot load settings from the Photograph Inpainting text file."));
+
+ file.close();
+ m_inpaintingTypeCB->blockSignals(true);
+ m_inpaintingTypeCB->setCurrentItem(NoPreset);
+ m_inpaintingTypeCB->blockSignals(false);
+ m_settingsWidget->setEnabled(true);
+}
+
+void InPaintingTool::slotSaveAsSettings()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Inpainting Settings File to Save")) );
+ if( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ m_settingsWidget->saveSettings(file, TQString("# Photograph Inpainting Configuration File V2"));
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot save settings to the Photograph Inpainting text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamInPaintingImagesPlugin
diff --git a/src/imageplugins/inpainting/inpaintingtool.h b/src/imageplugins/inpainting/inpaintingtool.h
new file mode 100644
index 00000000..44202c5d
--- /dev/null
+++ b/src/imageplugins/inpainting/inpaintingtool.h
@@ -0,0 +1,133 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-30
+ * Description : a digiKam image editor plugin to inpaint
+ * a photograph
+ *
+ * Copyright (C) 2005-2009 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef INPAINTINGTOOL_H
+#define INPAINTINGTOOL_H
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqrect.h>
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <kpassivepopup.h>
+
+// Digikam includes.
+
+#include "dimg.h"
+#include "editortool.h"
+
+class TQTabWidget;
+class TQComboBox;
+
+namespace Digikam
+{
+class GreycstorationWidget;
+class ImageWidget;
+class EditorToolSettings;
+}
+
+namespace DigikamInPaintingImagesPlugin
+{
+
+class InPaintingPassivePopup : public KPassivePopup
+{
+public:
+
+ InPaintingPassivePopup(TQWidget* parent) : KPassivePopup(parent), m_parent(parent) {}
+
+protected:
+
+ virtual void positionSelf() { move(m_parent->x() + 30, m_parent->y() + 30); }
+
+private:
+
+ TQWidget* m_parent;
+};
+
+//-----------------------------------------------------------
+
+class InPaintingTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ InPaintingTool(TQObject* parent);
+ ~InPaintingTool();
+
+private slots:
+
+ void processCImgURL(const TQString&);
+ void slotResetValues(int);
+ void slotResetSettings();
+ void slotSaveAsSettings();
+ void slotLoadSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ enum InPaintingFilteringPreset
+ {
+ NoPreset=0,
+ RemoveSmallArtefact,
+ RemoveMediumArtefact,
+ RemoveLargeArtefact
+ };
+
+ bool m_isComputed;
+
+ TQRect m_maskRect;
+
+ TQImage m_maskImage;
+
+ TQComboBox *m_inpaintingTypeCB;
+
+ TQTabWidget *m_mainTab;
+
+ Digikam::DImg m_originalImage;
+ Digikam::DImg m_cropImage;
+
+ Digikam::GreycstorationWidget *m_settingsWidget;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamInPaintingImagesPlugin
+
+#endif /* INPAINTINGTOOL_H */
diff --git a/src/imageplugins/inserttext/Makefile.am b/src/imageplugins/inserttext/Makefile.am
new file mode 100644
index 00000000..2753def7
--- /dev/null
+++ b/src/imageplugins/inserttext/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_inserttext_la_SOURCES = imageplugin_inserttext.cpp inserttextwidget.cpp \
+ inserttexttool.cpp fontchooserwidget.cpp
+
+digikamimageplugin_inserttext_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_inserttext_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_inserttext.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_inserttext.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_inserttext_ui.rc
+
diff --git a/src/imageplugins/inserttext/digikamimageplugin_inserttext.desktop b/src/imageplugins/inserttext/digikamimageplugin_inserttext.desktop
new file mode 100644
index 00000000..e9ca6cfd
--- /dev/null
+++ b/src/imageplugins/inserttext/digikamimageplugin_inserttext.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Name=ImagePlugin_InsertText
+Name[bg]=Приставка за снимки - Добавяне на текст
+Name[da]=Plugin til at indsætte tekst
+Name[el]=ΠρόσθετοΕικόνας_ΕισαγωγήΚειμένου
+Name[fi]=Tekstinlisäys
+Name[hr]=Tekst
+Name[it]=PluginImmagini_InserisciTesto
+Name[nl]=Afbeeldingsplugin_TekstInvoegen
+Name[sr]=Убаци текст
+Name[sr@Latn]=Ubaci tekst
+Name[sv]=Insticksprogram för infoga text
+Name[tr]=ResimEklentisi_MetinEkle
+Name[xx]=xxImagePlugin_InsertTextxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Insert text to image plugin for digiKam
+Comment[bg]=Приставка на digiKam за добавяне на текст към снимки
+Comment[ca]=Connector pel digiKam per inserir text en una imatge
+Comment[da]=Digikam plugin til at indsætte tekst i billeder
+Comment[de]=digiKam-Modul zum Einfügen von Text in ein Bild
+Comment[el]=Πρόσθετο εισαγωγής κειμένου σε εικόνα για το digiKam
+Comment[es]=Plugin de digiKampara insertar texto a una imagen
+Comment[et]=DigiKami pildile teksti lisamise plugin
+Comment[fa]=درج متن در وصلۀ تصویر برای digiKam
+Comment[fi]=Lisää tekstiä kuvaan
+Comment[gl]=Un plugin de digiKam para inserir texto na imaxe
+Comment[hr]=digiKam dodatak za umetanje teksta
+Comment[is]=Íforrit fyrir digiKam sem setur texta inn á mynd
+Comment[it]=Plugin per l'aggiunta di testo nell'immagire per digiKam
+Comment[ja]=digiKam テキスト挿入プラグイン
+Comment[nds]=digiKam-Moduul för't Infögen vun Text in en Bild
+Comment[nl]=Digikam-plugin voor het invoegen van tekst
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਚਿੱਤਰ ਉੱਤੇ ਪਾਠ ਲਿਖਣ ਲਈ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam dodająca tekst do zdjęcia
+Comment[pt]=Um 'plugin' do digiKam para inserir texto na imagem
+Comment[pt_BR]=Plugin de inserção de texto na imagem
+Comment[ru]=Модуль digiKam наложения текста на изображения
+Comment[sk]=digiKam plugin pre vkladanie textu do obrázku
+Comment[sr]=digiKam-ов прикључак за убацивање текста у слику
+Comment[sr@Latn]=digiKam-ov priključak za ubacivanje teksta u sliku
+Comment[sv]=Digikam insticksprogram för att infoga text i bilder
+Comment[tr]=digiKam için resme metin ekleme eklentisi
+Comment[uk]=Втулок для вставляння тексту в зображення для digiKam
+Comment[vi]=Phần bổ sung chèn chữ vào ảnh cho digiKam
+Comment[xx]=xxInsert text to image plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_inserttext
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/inserttext/digikamimageplugin_inserttext_ui.rc b/src/imageplugins/inserttext/digikamimageplugin_inserttext_ui.rc
new file mode 100644
index 00000000..4fa71fcc
--- /dev/null
+++ b/src/imageplugins/inserttext/digikamimageplugin_inserttext_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_inserttext" >
+
+ <MenuBar>
+
+ <Menu name="Decorate" ><text>&amp;Decorate</text>
+ <Action name="imageplugin_inserttext" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action name="imageplugin_inserttext" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/inserttext/fontchooserwidget.cpp b/src/imageplugins/inserttext/fontchooserwidget.cpp
new file mode 100644
index 00000000..aa76ea8e
--- /dev/null
+++ b/src/imageplugins/inserttext/fontchooserwidget.cpp
@@ -0,0 +1,738 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a simple widget to choose a font based on
+ * KDE FontChooserWidget implementation.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 1999 by Preston Brown <pbrown@kde.org>
+ * Copyright (C) 1997 by Bernd Johannes Wuebben <wuebben@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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqfile.h>
+#include <tqfont.h>
+#include <tqfontdatabase.h>
+#include <tqgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqscrollbar.h>
+#include <tqspinbox.h>
+#include <tqstringlist.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeapplication.h>
+#include <kcharsets.h>
+#include <tdeconfig.h>
+#include <kdialog.h>
+#include <tdeglobal.h>
+#include <tdeglobalsettings.h>
+#include <tdelistbox.h>
+#include <tdelocale.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+#include <tqlineedit.h>
+
+// Local includes.
+
+#include "fontchooserwidget.h"
+#include "fontchooserwidget.moc"
+
+namespace DigikamInsertTextImagesPlugin
+{
+
+class FontChooserWidget::FontChooserWidgetPrivate
+{
+public:
+
+ FontChooserWidgetPrivate()
+ {
+ m_palette.setColor(TQPalette::Active, TQColorGroup::Text, TQt::black);
+ m_palette.setColor(TQPalette::Active, TQColorGroup::Base, TQt::white);
+ }
+
+ TQPalette m_palette;
+};
+
+FontChooserWidget::FontChooserWidget(TQWidget *parent, const char *name,
+ bool onlyFixed, const TQStringList &fontList,
+ int visibleListSize, bool diff,
+ TQButton::ToggleState *sizeIsRelativeState )
+ : TQWidget(parent, name), usingFixed(onlyFixed)
+{
+ charsetsCombo = 0;
+
+ TQString mainWhatsThisText = i18n( "Here you can choose the font to be used." );
+ TQWhatsThis::add( this, mainWhatsThisText );
+
+ d = new FontChooserWidgetPrivate;
+ TQVBoxLayout *topLayout = new TQVBoxLayout( this, 0, KDialog::spacingHint() );
+ int checkBoxGap = KDialog::spacingHint() / 2;
+
+ int row = 0;
+ TQWidget *page = new TQWidget( this );
+ topLayout->addWidget(page);
+ TQGridLayout *gridLayout = new TQGridLayout( page, 4, 3, 0, KDialog::spacingHint() );
+
+ // First, create the labels across the top
+
+ TQHBoxLayout *familyLayout = new TQHBoxLayout();
+ familyLayout->addSpacing( checkBoxGap );
+
+ if (diff)
+ {
+ familyCheckbox = new TQCheckBox(i18n("Font"), page);
+
+ connect(familyCheckbox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(toggled_checkbox()));
+
+ familyLayout->addWidget(familyCheckbox, 0, TQt::AlignLeft);
+ TQString familyCBToolTipText =
+ i18n("Change font family?");
+ TQString familyCBWhatsThisText =
+ i18n("Enable this checkbox to change the font family settings.");
+ TQWhatsThis::add( familyCheckbox, familyCBWhatsThisText );
+ TQToolTip::add( familyCheckbox, familyCBToolTipText );
+ familyLabel = 0;
+ }
+ else
+ {
+ familyCheckbox = 0;
+ familyLabel = new TQLabel( i18n("Font:"), page, "familyLabel" );
+ familyLayout->addWidget(familyLabel, 1, TQt::AlignLeft);
+ }
+
+ gridLayout->addLayout(familyLayout, row, 0 );
+
+ TQHBoxLayout *styleLayout = new TQHBoxLayout();
+
+ if (diff)
+ {
+ styleCheckbox = new TQCheckBox(i18n("Style:"), page);
+
+ connect(styleCheckbox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(toggled_checkbox()));
+
+ styleLayout->addWidget(styleCheckbox, 0, TQt::AlignLeft);
+ TQString styleCBToolTipText =
+ i18n("Change font style?");
+ TQString styleCBWhatsThisText =
+ i18n("Enable this checkbox to change the font style settings.");
+ TQWhatsThis::add( styleCheckbox, styleCBWhatsThisText );
+ TQToolTip::add( styleCheckbox, styleCBToolTipText );
+ styleLabel = 0;
+ }
+ else
+ {
+ styleCheckbox = 0;
+ styleLabel = new TQLabel( i18n("Style:"), page, "styleLabel");
+ styleLayout->addWidget(styleLabel, 1, TQt::AlignLeft);
+ }
+
+ styleLayout->addSpacing( checkBoxGap );
+ gridLayout->addLayout(styleLayout, row, 1 );
+
+ TQHBoxLayout *sizeLayout = new TQHBoxLayout();
+
+ if (diff)
+ {
+ sizeCheckbox = new TQCheckBox(i18n("Size"),page);
+
+ connect(sizeCheckbox, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(toggled_checkbox()));
+
+ sizeLayout->addWidget(sizeCheckbox, 0, TQt::AlignLeft);
+ TQString sizeCBToolTipText =
+ i18n("Change font size?");
+ TQString sizeCBWhatsThisText =
+ i18n("Enable this checkbox to change the font size settings.");
+ TQWhatsThis::add( sizeCheckbox, sizeCBWhatsThisText );
+ TQToolTip::add( sizeCheckbox, sizeCBToolTipText );
+ sizeLabel = 0;
+ }
+ else
+ {
+ sizeCheckbox = 0;
+ sizeLabel = new TQLabel( i18n("Size:"), page, "sizeLabel");
+ sizeLayout->addWidget(sizeLabel, 1, TQt::AlignLeft);
+ }
+
+ sizeLayout->addSpacing( checkBoxGap );
+ sizeLayout->addSpacing( checkBoxGap ); // prevent label from eating border
+ gridLayout->addLayout(sizeLayout, row, 2 );
+
+ row ++;
+
+ // Now create the actual boxes that hold the info
+
+ familyListBox = new TDEListBox( page, "familyListBox");
+ familyListBox->setEnabled( !diff );
+ gridLayout->addWidget( familyListBox, row, 0 );
+ TQString fontFamilyWhatsThisText = i18n("Here you can choose the font family to be used." );
+ TQWhatsThis::add( familyListBox, fontFamilyWhatsThisText );
+ TQWhatsThis::add(diff?(TQWidget *) familyCheckbox:(TQWidget *) familyLabel, fontFamilyWhatsThisText );
+
+ connect(familyListBox, TQ_SIGNAL(highlighted(const TQString &)),
+ this, TQ_SLOT(family_chosen_slot(const TQString &)));
+
+ if(!fontList.isEmpty())
+ {
+ familyListBox->insertStringList(fontList);
+ }
+ else
+ {
+ fillFamilyListBox(onlyFixed);
+ }
+
+ familyListBox->setMinimumHeight( minimumListHeight( familyListBox, visibleListSize ) );
+
+ styleListBox = new TDEListBox( page, "styleListBox");
+ styleListBox->setEnabled( !diff );
+ gridLayout->addWidget(styleListBox, row, 1);
+ TQString fontStyleWhatsThisText = i18n("Here you can choose the font style to be used." );
+ TQWhatsThis::add( styleListBox, fontStyleWhatsThisText );
+ TQWhatsThis::add(diff?(TQWidget *)styleCheckbox:(TQWidget *)styleLabel, fontFamilyWhatsThisText );
+ styleListBox->insertItem(i18n("Regular"));
+ styleListBox->insertItem(i18n("Italic"));
+ styleListBox->insertItem(i18n("Bold"));
+ styleListBox->insertItem(i18n("Bold Italic"));
+ styleListBox->setMinimumWidth( minimumListWidth( styleListBox ) );
+ styleListBox->setMinimumHeight( minimumListHeight( styleListBox, visibleListSize ) );
+
+ connect(styleListBox, TQ_SIGNAL(highlighted(const TQString &)),
+ this, TQ_SLOT(style_chosen_slot(const TQString &)));
+
+ sizeListBox = new TDEListBox( page, "sizeListBox");
+ sizeOfFont = new KIntNumInput( page, "sizeOfFont");
+ sizeOfFont->setMinValue(4);
+
+ sizeListBox->setEnabled( !diff );
+ sizeOfFont->setEnabled( !diff );
+
+ if( sizeIsRelativeState )
+ {
+ TQString sizeIsRelativeCBText =
+ i18n("Relative");
+ TQString sizeIsRelativeCBToolTipText =
+ i18n("Font size<br><i>fixed</i> or <i>relative</i><br>to environment");
+ TQString sizeIsRelativeCBWhatsThisText =
+ i18n("Here you can switch between a fixed font size and a font size "
+ "to be calculated dynamically and adjusted to any changing "
+ "environment (e.g. widget dimensions, paper size)." );
+ sizeIsRelativeCheckBox = new TQCheckBox( sizeIsRelativeCBText,
+ page,
+ "sizeIsRelativeCheckBox" );
+ sizeIsRelativeCheckBox->setTristate( diff );
+ TQGridLayout *sizeLayout2 = new TQGridLayout( 3,2, KDialog::spacingHint()/2, "sizeLayout2" );
+ gridLayout->addLayout(sizeLayout2, row, 2);
+ sizeLayout2->setColStretch( 1, 1 ); // to prevent text from eating the right border
+ sizeLayout2->addMultiCellWidget( sizeOfFont, 0, 0, 0, 1);
+ sizeLayout2->addMultiCellWidget(sizeListBox, 1,1, 0,1);
+ sizeLayout2->addWidget(sizeIsRelativeCheckBox, 2, 0, TQt::AlignLeft);
+ TQWhatsThis::add( sizeIsRelativeCheckBox, sizeIsRelativeCBWhatsThisText );
+ TQToolTip::add( sizeIsRelativeCheckBox, sizeIsRelativeCBToolTipText );
+ }
+ else
+ {
+ sizeIsRelativeCheckBox = 0L;
+ TQGridLayout *sizeLayout2 = new TQGridLayout( 2,1, KDialog::spacingHint()/2, "sizeLayout2" );
+ gridLayout->addLayout(sizeLayout2, row, 2);
+ sizeLayout2->addWidget( sizeOfFont, 0, 0);
+ sizeLayout2->addMultiCellWidget(sizeListBox, 1,1, 0,0);
+ }
+
+ TQString fontSizeWhatsThisText = i18n("Here you can choose the font size to be used." );
+ TQWhatsThis::add( sizeListBox, fontSizeWhatsThisText );
+ TQWhatsThis::add( diff?(TQWidget *)sizeCheckbox:(TQWidget *)sizeLabel, fontSizeWhatsThisText );
+
+ fillSizeList();
+ sizeListBox->setMinimumWidth( minimumListWidth(sizeListBox) +
+ sizeListBox->fontMetrics().maxWidth() );
+ sizeListBox->setMinimumHeight( minimumListHeight( sizeListBox, visibleListSize ) );
+
+ connect( sizeOfFont, TQ_SIGNAL( valueChanged(int) ),
+ this, TQ_SLOT(size_value_slot(int)));
+
+ connect( sizeListBox, TQ_SIGNAL(highlighted(const TQString&)),
+ this, TQ_SLOT(size_chosen_slot(const TQString&)) );
+
+ sizeListBox->setSelected(sizeListBox->findItem(TQString::number(10)), true); // default to 10pt.
+
+ row ++;
+
+ row ++;
+
+ TQVBoxLayout *vbox;
+ page = new TQWidget( this );
+ topLayout->addWidget(page);
+ vbox = new TQVBoxLayout( page, 0, KDialog::spacingHint() );
+ TQLabel *label = new TQLabel( i18n("Actual Font"), page );
+ vbox->addWidget( label );
+
+ xlfdEdit = new TQLineEdit( page, "xlfdEdit" );
+ vbox->addWidget( xlfdEdit );
+
+ // lets initialize the display if possible
+ setFont( TDEGlobalSettings::generalFont(), usingFixed );
+
+ // check or uncheck or gray out the "relative" checkbox
+ if( sizeIsRelativeState && sizeIsRelativeCheckBox )
+ setSizeIsRelative( *sizeIsRelativeState );
+
+ TDEConfig *config = TDEGlobal::config();
+ TDEConfigGroupSaver saver(config, TQString::fromLatin1("General"));
+ showXLFDArea(config->readBoolEntry(TQString::fromLatin1("fontSelectorShowXLFD"), false));
+}
+
+FontChooserWidget::~FontChooserWidget()
+{
+ delete d;
+}
+
+int FontChooserWidget::minimumListWidth( const TQListBox *list )
+{
+ int w=0;
+
+ for( uint i=0; i<list->count(); i++ )
+ {
+ int itemWidth = list->item(i)->width(list);
+ w = TQMAX(w,itemWidth);
+ }
+
+ if( w == 0 )
+ {
+ w = 40;
+ }
+
+ w += list->frameWidth() * 2;
+ w += list->verticalScrollBar()->sizeHint().width();
+ return w;
+}
+
+int FontChooserWidget::minimumListHeight( const TQListBox *list, int numVisibleEntry )
+{
+ int w = list->count() > 0 ? list->item(0)->height(list) :
+ list->fontMetrics().lineSpacing();
+
+ if( w < 0 ) { w = 10; }
+ if( numVisibleEntry <= 0 ) { numVisibleEntry = 4; }
+ return ( w * numVisibleEntry + 2 * list->frameWidth() );
+}
+
+void FontChooserWidget::fillSizeList()
+{
+ if(! sizeListBox) return; //assertion.
+
+ static const int c[] =
+ {
+ 4, 5, 6, 7,
+ 8, 9, 10, 11,
+ 12, 13, 14, 15,
+ 16, 17, 18, 19,
+ 20, 22, 24, 26,
+ 28, 32, 48, 64,
+ 72, 80, 94, 102,
+ 116, 128, 132, 148,
+ 156, 164, 172, 188,
+ 192, 202, 212, 224,
+ 232, 240, 248, 256,
+ 0
+ };
+
+ for(int i = 0; c[i]; ++i)
+ {
+ sizeListBox->insertItem(TQString::number(c[i]));
+ }
+}
+
+void FontChooserWidget::setColor( const TQColor & col )
+{
+ d->m_palette.setColor( TQPalette::Active, TQColorGroup::Text, col );
+}
+
+TQColor FontChooserWidget::color() const
+{
+ return d->m_palette.color( TQPalette::Active, TQColorGroup::Text );
+}
+
+void FontChooserWidget::setBackgroundColor( const TQColor & col )
+{
+ d->m_palette.setColor( TQPalette::Active, TQColorGroup::Base, col );
+}
+
+TQColor FontChooserWidget::backgroundColor() const
+{
+ return d->m_palette.color( TQPalette::Active, TQColorGroup::Base );
+}
+
+void FontChooserWidget::setSizeIsRelative( TQButton::ToggleState relative )
+{
+ // check or uncheck or gray out the "relative" checkbox
+ if( sizeIsRelativeCheckBox )
+ {
+ if( TQButton::NoChange == relative )
+ sizeIsRelativeCheckBox->setNoChange();
+ else
+ sizeIsRelativeCheckBox->setChecked( TQButton::On == relative );
+ }
+}
+
+TQButton::ToggleState FontChooserWidget::sizeIsRelative() const
+{
+ return sizeIsRelativeCheckBox
+ ? sizeIsRelativeCheckBox->state()
+ : TQButton::NoChange;
+}
+
+TQSize FontChooserWidget::sizeHint( void ) const
+{
+ return minimumSizeHint();
+}
+
+void FontChooserWidget::enableColumn( int column, bool state )
+{
+ if( column & FamilyList )
+ {
+ familyListBox->setEnabled(state);
+ }
+ if( column & StyleList )
+ {
+ styleListBox->setEnabled(state);
+ }
+ if( column & SizeList )
+ {
+ sizeListBox->setEnabled(state);
+ }
+}
+
+void FontChooserWidget::setFont( const TQFont& aFont, bool onlyFixed )
+{
+ selFont = aFont;
+ selectedSize=aFont.pointSize();
+ if (selectedSize == -1)
+ selectedSize = TQFontInfo(aFont).pointSize();
+
+ if( onlyFixed != usingFixed)
+ {
+ usingFixed = onlyFixed;
+ fillFamilyListBox(usingFixed);
+ }
+ setupDisplay();
+ displaySample(selFont);
+}
+
+int FontChooserWidget::fontDiffFlags() {
+ int diffFlags = 0;
+ if (familyCheckbox && styleCheckbox && sizeCheckbox)
+ {
+ diffFlags = (int)(familyCheckbox->isChecked() ? FontDiffFamily : 0)
+ | (int)( styleCheckbox->isChecked() ? FontDiffStyle : 0)
+ | (int)( sizeCheckbox->isChecked() ? FontDiffSize : 0);
+ }
+ return diffFlags;
+}
+
+void FontChooserWidget::toggled_checkbox()
+{
+ familyListBox->setEnabled( familyCheckbox->isChecked() );
+ styleListBox->setEnabled( styleCheckbox->isChecked() );
+ sizeListBox->setEnabled( sizeCheckbox->isChecked() );
+ sizeOfFont->setEnabled( sizeCheckbox->isChecked() );
+}
+
+void FontChooserWidget::family_chosen_slot(const TQString& family)
+{
+ TQFontDatabase dbase;
+ TQStringList styles = TQStringList(dbase.styles(family));
+ styleListBox->clear();
+ currentStyles.clear();
+ TQStringList::Iterator end(styles.end());
+ for ( TQStringList::Iterator it = styles.begin(); it != end; ++it )
+ {
+ TQString style = *it;
+ int pos = style.find("Plain");
+ if(pos >=0) style = style.replace(pos,5,i18n("Regular"));
+ pos = style.find("Normal");
+ if(pos >=0) style = style.replace(pos,6,i18n("Regular"));
+ pos = style.find("Oblique");
+ if(pos >=0) style = style.replace(pos,7,i18n("Italic"));
+ if(!styleListBox->findItem(style))
+ {
+ styleListBox->insertItem(i18n(style.utf8()));
+ currentStyles.insert(i18n(style.utf8()), *it);
+ }
+ }
+ if(styleListBox->count()==0)
+ {
+ styleListBox->insertItem(i18n("Regular"));
+ currentStyles.insert(i18n("Regular"), "Normal");
+ }
+
+ styleListBox->blockSignals(true);
+ TQListBoxItem *item = styleListBox->findItem(selectedStyle);
+ if (item)
+ styleListBox->setSelected(styleListBox->findItem(selectedStyle), true);
+ else
+ styleListBox->setSelected(0, true);
+ styleListBox->blockSignals(false);
+
+ style_chosen_slot(TQString());
+}
+
+void FontChooserWidget::size_chosen_slot(const TQString& size)
+{
+ selectedSize=size.toInt();
+ sizeOfFont->setValue(selectedSize);
+ selFont.setPointSize(selectedSize);
+ emit fontSelected(selFont);
+}
+
+void FontChooserWidget::size_value_slot(int val)
+{
+ selFont.setPointSize(val);
+ emit fontSelected(selFont);
+}
+
+void FontChooserWidget::style_chosen_slot(const TQString& style)
+{
+ TQString currentStyle;
+ if (style.isEmpty())
+ currentStyle = styleListBox->currentText();
+ else
+ currentStyle = style;
+
+ int diff=0; // the difference between the font size requested and what we can show.
+
+ sizeListBox->clear();
+ TQFontDatabase dbase;
+ if(dbase.isSmoothlyScalable(familyListBox->currentText(), currentStyles[currentStyle]))
+ { // is vector font
+ //sampleEdit->setPaletteBackgroundPixmap( VectorPixmap ); // TODO
+ fillSizeList();
+ }
+ else
+ { // is bitmap font.
+ //sampleEdit->setPaletteBackgroundPixmap( BitmapPixmap ); // TODO
+ TQValueList<int> sizes = dbase.smoothSizes(familyListBox->currentText(), currentStyles[currentStyle]);
+ if(sizes.count() > 0)
+ {
+ TQValueList<int>::iterator it;
+ diff=1000;
+ TQValueList<int>::iterator end(sizes.end());
+ for ( it = sizes.begin(); it != end; ++it )
+ {
+ if(*it <= selectedSize || diff > *it - selectedSize) diff = selectedSize - *it;
+ sizeListBox->insertItem(TQString::number(*it));
+ }
+ }
+ else // there are times TQT does not provide the list..
+ fillSizeList();
+ }
+ sizeListBox->blockSignals(true);
+ sizeListBox->setSelected(sizeListBox->findItem(TQString::number(selectedSize)), true);
+ sizeListBox->blockSignals(false);
+ sizeListBox->ensureCurrentVisible();
+
+ selFont = dbase.font(familyListBox->currentText(), currentStyles[currentStyle], selectedSize-diff);
+ emit fontSelected(selFont);
+ if (!style.isEmpty())
+ selectedStyle = style;
+}
+
+void FontChooserWidget::displaySample(const TQFont& font)
+{
+ xlfdEdit->setText(font.rawName());
+ xlfdEdit->setCursorPosition(0);
+}
+
+void FontChooserWidget::setupDisplay()
+{
+ // Calling familyListBox->setCurrentItem() causes the value of selFont
+ // to change, so we save the family, style and size beforehand.
+ TQString family = selFont.family().lower();
+ int style = (selFont.bold() ? 2 : 0) + (selFont.italic() ? 1 : 0);
+ int size = selFont.pointSize();
+ if (size == -1)
+ size = TQFontInfo(selFont).pointSize();
+ TQString sizeStr = TQString::number(size);
+
+ int numEntries, i;
+
+ numEntries = familyListBox->count();
+ for (i = 0; i < numEntries; i++)
+ {
+ if (family == familyListBox->text(i).lower())
+ {
+ familyListBox->setCurrentItem(i);
+ break;
+ }
+ }
+
+ // 1st Fallback
+ if ( (i == numEntries) )
+ {
+ if (family.contains('['))
+ {
+ family = family.left(family.find('[')).stripWhiteSpace();
+ for (i = 0; i < numEntries; i++)
+ {
+ if (family == familyListBox->text(i).lower())
+ {
+ familyListBox->setCurrentItem(i);
+ break;
+ }
+ }
+ }
+ }
+
+ // 2nd Fallback
+ if ( (i == numEntries) )
+ {
+ TQString fallback = family+" [";
+ for (i = 0; i < numEntries; i++)
+ {
+ if (familyListBox->text(i).lower().startsWith(fallback))
+ {
+ familyListBox->setCurrentItem(i);
+ break;
+ }
+ }
+ }
+
+ // 3rd Fallback
+ if ( (i == numEntries) )
+ {
+ for (i = 0; i < numEntries; i++)
+ {
+ if (familyListBox->text(i).lower().startsWith(family))
+ {
+ familyListBox->setCurrentItem(i);
+ break;
+ }
+ }
+ }
+
+ // Fall back in case nothing matched. Otherwise, diff doesn't work
+ if ( i == numEntries )
+ familyListBox->setCurrentItem( 0 );
+
+ styleListBox->setCurrentItem(style);
+
+ numEntries = sizeListBox->count();
+ for (i = 0; i < numEntries; i++)
+ {
+ if (sizeStr == sizeListBox->text(i))
+ {
+ sizeListBox->setCurrentItem(i);
+ break;
+ }
+ }
+
+ sizeOfFont->setValue(size);
+}
+
+void FontChooserWidget::getFontList( TQStringList &list, uint fontListCriteria)
+{
+ TQFontDatabase dbase;
+ TQStringList lstSys(dbase.families());
+
+ // if we have criteria; then check fonts before adding
+ if (fontListCriteria)
+ {
+ TQStringList lstFonts;
+ TQStringList::Iterator end(lstSys.end());
+ for (TQStringList::Iterator it = lstSys.begin(); it != end; ++it)
+ {
+ if ((fontListCriteria & FixedWidthFonts) > 0 && !dbase.isFixedPitch(*it)) continue;
+ if (((fontListCriteria & (SmoothScalableFonts | ScalableFonts)) == ScalableFonts) &&
+ !dbase.isBitmapScalable(*it)) continue;
+ if ((fontListCriteria & SmoothScalableFonts) > 0 && !dbase.isSmoothlyScalable(*it)) continue;
+ lstFonts.append(*it);
+ }
+
+ if((fontListCriteria & FixedWidthFonts) > 0) {
+ // Fallback.. if there are no fixed fonts found, it is probably a
+ // bug in the font server or TQt. In this case, just use 'fixed'
+ if (lstFonts.count() == 0)
+ lstFonts.append("fixed");
+ }
+
+ lstSys = lstFonts;
+ }
+
+ lstSys.sort();
+
+ list = lstSys;
+}
+
+void FontChooserWidget::addFont( TQStringList &list, const char *xfont )
+{
+ const char *ptr = strchr( xfont, '-' );
+ if ( !ptr )
+ return;
+
+ ptr = strchr( ptr + 1, '-' );
+ if ( !ptr )
+ return;
+
+ TQString font = TQString::fromLatin1(ptr + 1);
+
+ int pos;
+ if ( ( pos = font.find( '-' ) ) > 0 ) {
+ font.truncate( pos );
+
+ if ( font.find( TQString::fromLatin1("open look"), 0, false ) >= 0 )
+ return;
+
+ TQStringList::Iterator it = list.begin();
+ TQStringList::Iterator end(list.end());
+ for ( ; it != end; ++it )
+ if ( *it == font )
+ return;
+ list.append( font );
+ }
+}
+
+void FontChooserWidget::fillFamilyListBox(bool onlyFixedFonts)
+{
+ TQStringList fontList;
+ getFontList(fontList, onlyFixedFonts?FixedWidthFonts:0);
+ familyListBox->clear();
+ familyListBox->insertStringList(fontList);
+}
+
+void FontChooserWidget::showXLFDArea(bool show)
+{
+ if( show )
+ {
+ xlfdEdit->parentWidget()->show();
+ }
+ else
+ {
+ xlfdEdit->parentWidget()->hide();
+ }
+}
+
+} // NameSpace DigikamInsertTextImagesPlugin
+
diff --git a/src/imageplugins/inserttext/fontchooserwidget.h b/src/imageplugins/inserttext/fontchooserwidget.h
new file mode 100644
index 00000000..4585c231
--- /dev/null
+++ b/src/imageplugins/inserttext/fontchooserwidget.h
@@ -0,0 +1,172 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a simple widget to choose a font based on
+ * KDE FontChooserWidget implementation.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 1999 by Preston Brown <pbrown@kde.org>
+ * Copyright (C) 1997 by Bernd Johannes Wuebben <wuebben@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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef FONT_CHOOSER_WIDGET_H
+#define FONT_CHOOSER_WIDGET_H
+
+#include <tqlineedit.h>
+#include <tqbutton.h>
+
+class TQComboBox;
+class TQCheckBox;
+class TQFont;
+class TQGroupBox;
+class TQLabel;
+class TQStringList;
+
+class TDEListBox;
+class KIntNumInput;
+
+namespace DigikamInsertTextImagesPlugin
+{
+
+class FontChooserWidget : public TQWidget
+{
+ TQ_OBJECT
+
+ TQ_PROPERTY( TQFont font READ font WRITE setFont )
+
+public:
+
+ enum FontColumn
+ {
+ FamilyList=0x01,
+ StyleList=0x02,
+ SizeList=0x04
+ };
+
+ enum FontDiff
+ {
+ FontDiffFamily=0x01,
+ FontDiffStyle=0x02,
+ FontDiffSize=0x04
+ };
+
+ enum FontListCriteria
+ {
+ FixedWidthFonts=0x01,
+ ScalableFonts=0x02,
+ SmoothScalableFonts=0x04
+ };
+
+public:
+
+ FontChooserWidget(TQWidget *parent = 0L, const char *name = 0L,
+ bool onlyFixed = false,
+ const TQStringList &fontList = TQStringList(),
+ int visibleListSize=8,
+ bool diff = false,
+ TQButton::ToggleState *sizeIsRelativeState = 0L );
+
+ ~FontChooserWidget();
+
+ void setFont( const TQFont &font, bool onlyFixed = false );
+ void setColor( const TQColor & col );
+ void setBackgroundColor( const TQColor & col );
+ void setSizeIsRelative( TQButton::ToggleState relative );
+
+ TQFont font() const { return selFont; };
+ TQColor color() const;
+ TQColor backgroundColor() const;
+ static void getFontList( TQStringList &list, uint fontListCriteria);
+ TQButton::ToggleState sizeIsRelative() const;
+ static TQString getXLFD( const TQFont &theFont ) { return theFont.rawName(); };
+
+ int fontDiffFlags();
+ void enableColumn( int column, bool state );
+ virtual TQSize sizeHint( void ) const;
+
+signals:
+
+ void fontSelected( const TQFont &font );
+
+private slots:
+
+ void toggled_checkbox();
+ void family_chosen_slot(const TQString&);
+ void size_chosen_slot(const TQString&);
+ void style_chosen_slot(const TQString&);
+ void displaySample(const TQFont &font);
+ void showXLFDArea(bool);
+ void size_value_slot(int);
+
+private:
+
+ void fillFamilyListBox(bool onlyFixedFonts = false);
+ void fillSizeList();
+
+ void addFont( TQStringList &list, const char *xfont );
+
+ void setupDisplay();
+
+ int minimumListWidth( const TQListBox *list );
+ int minimumListHeight( const TQListBox *list, int numVisibleEntry );
+
+private:
+
+ bool usingFixed;
+ int selectedSize;
+
+ TQMap<TQString, TQString> currentStyles;
+
+ // pointer to an optinally supplied list of fonts to
+ // inserted into the fontdialog font-family combo-box
+ TQStringList fontList;
+
+ TQLineEdit *xlfdEdit;
+
+ TQLabel *familyLabel;
+ TQLabel *styleLabel;
+
+ TQCheckBox *familyCheckbox;
+ TQCheckBox *styleCheckbox;
+ TQCheckBox *sizeCheckbox;
+ TQCheckBox *sizeIsRelativeCheckBox;
+
+ TQComboBox *charsetsCombo;
+
+ TQFont selFont;
+
+ TQString selectedStyle;
+
+ TQLabel *sizeLabel;
+
+ KIntNumInput *sizeOfFont;
+
+ TDEListBox *familyListBox;
+ TDEListBox *styleListBox;
+ TDEListBox *sizeListBox;
+
+private:
+
+ class FontChooserWidgetPrivate;
+ FontChooserWidgetPrivate *d;
+
+};
+
+} // NameSpace DigikamInsertTextImagesPlugin
+
+#endif // FONT_CHOOSER_WIDGET_H
diff --git a/src/imageplugins/inserttext/imageeffect_inserttext.cpp b/src/imageplugins/inserttext/imageeffect_inserttext.cpp
new file mode 100644
index 00000000..3f88644b
--- /dev/null
+++ b/src/imageplugins/inserttext/imageeffect_inserttext.cpp
@@ -0,0 +1,348 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a plugin to insert a text over an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqcombobox.h>
+#include <tqcheckbox.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqbrush.h>
+#include <tqpen.h>
+#include <tqfont.h>
+#include <tqtimer.h>
+#include <tqhbuttongroup.h>
+#include <tqtooltip.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kcursor.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <tdeconfig.h>
+#include <kcolorbutton.h>
+#include <ktextedit.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "inserttextwidget.h"
+#include "fontchooserwidget.h"
+#include "imageeffect_inserttext.h"
+#include "imageeffect_inserttext.moc"
+
+namespace DigikamInsertTextImagesPlugin
+{
+
+ImageEffect_InsertText::ImageEffect_InsertText(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Insert Text on Photograph"),
+ "inserttext", false, false)
+{
+ TQString whatsThis;
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Insert Text"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin for inserting text on a photograph."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2006, Gilles Caulier\n"
+ "(c) 2006-2007, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(plainPage());
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* l = new TQVBoxLayout(frame, 5, 0);
+ m_previewWidget = new InsertTextWidget(480, 320, frame);
+ l->addWidget(m_previewWidget);
+ TQWhatsThis::add( m_previewWidget, i18n("<p>This previews the text inserted in the image. "
+ "You can use the mouse to move the text to the right location."));
+ setPreviewAreaWidget(frame);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gbox2 = new TQWidget(plainPage());
+ TQGridLayout *gridBox2 = new TQGridLayout( gbox2, 9, 1, spacingHint());
+
+ m_textEdit = new KTextEdit(gbox2);
+ m_textEdit->setCheckSpellingEnabled(true);
+ m_textEdit->setWordWrap(TQTextEdit::NoWrap);
+ TQWhatsThis::add( m_textEdit, i18n("<p>Here, enter the text you want to insert in your image."));
+ gridBox2->addMultiCellWidget(m_textEdit, 0, 2, 0, 1);
+
+ // -------------------------------------------------------------
+
+ m_fontChooserWidget = new FontChooserWidget(gbox2);
+ TQWhatsThis::add( m_textEdit, i18n("<p>Here you can choose the font to be used."));
+ gridBox2->addMultiCellWidget(m_fontChooserWidget, 3, 3, 0, 1);
+
+ // -------------------------------------------------------------
+
+ TDEIconLoader icon;
+ m_alignButtonGroup = new TQHButtonGroup(gbox2);
+
+ TQPushButton *alignLeft = new TQPushButton( m_alignButtonGroup );
+ m_alignButtonGroup->insert(alignLeft, ALIGN_LEFT);
+ alignLeft->setPixmap( icon.loadIcon( "format-text-direction-ltr", (TDEIcon::Group)TDEIcon::Small ) );
+ alignLeft->setToggleButton(true);
+ TQToolTip::add( alignLeft, i18n( "Align text to the left" ) );
+
+ TQPushButton *alignRight = new TQPushButton( m_alignButtonGroup );
+ m_alignButtonGroup->insert(alignRight, ALIGN_RIGHT);
+ alignRight->setPixmap( icon.loadIcon( "format-text-direction-rtl", (TDEIcon::Group)TDEIcon::Small ) );
+ alignRight->setToggleButton(true);
+ TQToolTip::add( alignRight, i18n( "Align text to the right" ) );
+
+ TQPushButton *alignCenter = new TQPushButton( m_alignButtonGroup );
+ m_alignButtonGroup->insert(alignCenter, ALIGN_CENTER);
+ alignCenter->setPixmap( icon.loadIcon( "text_center", (TDEIcon::Group)TDEIcon::Small ) );
+ alignCenter->setToggleButton(true);
+ TQToolTip::add( alignCenter, i18n( "Align text to center" ) );
+
+ TQPushButton *alignBlock = new TQPushButton( m_alignButtonGroup );
+ m_alignButtonGroup->insert(alignBlock, ALIGN_BLOCK);
+ alignBlock->setPixmap( icon.loadIcon( "text_block", (TDEIcon::Group)TDEIcon::Small ) );
+ alignBlock->setToggleButton(true);
+ TQToolTip::add( alignBlock, i18n( "Align text to a block" ) );
+
+ m_alignButtonGroup->setExclusive(true);
+ m_alignButtonGroup->setFrameShape(TQFrame::NoFrame);
+ gridBox2->addMultiCellWidget(m_alignButtonGroup, 4, 4, 0, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label1 = new TQLabel(i18n("Rotation:"), gbox2);
+ m_textRotation = new TQComboBox( false, gbox2 );
+ m_textRotation->insertItem( i18n("None") );
+ m_textRotation->insertItem( i18n("90 Degrees") );
+ m_textRotation->insertItem( i18n("180 Degrees") );
+ m_textRotation->insertItem( i18n("270 Degrees") );
+ TQWhatsThis::add( m_textRotation, i18n("<p>Select the text rotation to use."));
+ gridBox2->addMultiCellWidget(label1, 5, 5, 0, 0);
+ gridBox2->addMultiCellWidget(m_textRotation, 5, 5, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Color:"), gbox2);
+ m_fontColorButton = new KColorButton( TQt::black, gbox2 );
+ TQWhatsThis::add( m_fontColorButton, i18n("<p>Select the font color to use."));
+ gridBox2->addMultiCellWidget(label2, 6, 6, 0, 0);
+ gridBox2->addMultiCellWidget(m_fontColorButton, 6, 6, 1, 1);
+
+ // -------------------------------------------------------------
+
+ m_borderText = new TQCheckBox( i18n( "Add border"), gbox2 );
+ TQToolTip::add( m_borderText, i18n( "Add a solid border around text using current text color" ) );
+
+ m_transparentText = new TQCheckBox( i18n( "Semi-transparent"), gbox2 );
+ TQToolTip::add( m_transparentText, i18n( "Use semi-transparent text background under image" ) );
+
+ gridBox2->addMultiCellWidget(m_borderText, 7, 7, 0, 1);
+ gridBox2->addMultiCellWidget(m_transparentText, 8, 8, 0, 1);
+ gridBox2->setRowStretch(9, 10);
+
+ setUserAreaWidget(gbox2);
+
+ // -------------------------------------------------------------
+
+ connect(m_fontChooserWidget, TQ_SIGNAL(fontSelected (const TQFont &)),
+ this, TQ_SLOT(slotFontPropertiesChanged(const TQFont &)));
+
+ connect(m_fontColorButton, TQ_SIGNAL(changed(const TQColor &)),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(m_textEdit, TQ_SIGNAL(textChanged()),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(m_alignButtonGroup, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotAlignModeChanged(int)));
+
+ connect(m_borderText, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(m_transparentText, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(m_textRotation, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(this, TQ_SIGNAL(signalUpdatePreview()), TQ_SLOT(slotUpdatePreview()));
+ // -------------------------------------------------------------
+
+ slotUpdatePreview();
+}
+
+ImageEffect_InsertText::~ImageEffect_InsertText()
+{
+}
+
+void ImageEffect_InsertText::readUserSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("inserttext Tool Dialog");
+ TQColor black(0, 0, 0);
+ TQFont defaultFont;
+
+ int orgW = m_previewWidget->imageIface()->originalWidth();
+ int orgH = m_previewWidget->imageIface()->originalHeight();
+
+ if ( orgW > orgH ) m_defaultSizeFont = (int)(orgH / 8.0);
+ else m_defaultSizeFont = (int)(orgW / 8.0);
+
+ defaultFont.setPointSize(m_defaultSizeFont);
+ m_textRotation->setCurrentItem( config->readNumEntry("Text Rotation", 0) );
+ m_fontColorButton->setColor(config->readColorEntry("Font Color", &black));
+ m_textEdit->setText(config->readEntry("Text String", i18n("Enter your text here!")));
+ m_textFont = config->readFontEntry("Font Properties", &defaultFont);
+ m_fontChooserWidget->setFont(m_textFont);
+ m_alignTextMode = config->readNumEntry("Text Alignment", ALIGN_LEFT);
+ m_borderText->setChecked( config->readBoolEntry("Border Text", false) );
+ m_transparentText->setChecked( config->readBoolEntry("Transparent Text", false) );
+ m_previewWidget->setPositionHint( config->readRectEntry("Position Hint") );
+
+ static_cast<TQPushButton*>(m_alignButtonGroup->find(m_alignTextMode))->setOn(true);
+ slotAlignModeChanged(m_alignTextMode);
+}
+
+void ImageEffect_InsertText::writeUserSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("inserttext Tool Dialog");
+
+ config->writeEntry( "Text Rotation", m_textRotation->currentItem() );
+ config->writeEntry( "Font Color", m_fontColorButton->color() );
+ config->writeEntry( "Text String", m_textEdit->text() );
+ config->writeEntry( "Font Properties", m_textFont );
+ config->writeEntry( "Text Alignment", m_alignTextMode );
+ config->writeEntry( "Border Text", m_borderText->isChecked() );
+ config->writeEntry( "Transparent Text", m_transparentText->isChecked() );
+ config->writeEntry( "Position Hint", m_previewWidget->getPositionHint() );
+
+ config->sync();
+}
+
+void ImageEffect_InsertText::resetValues()
+{
+ m_fontColorButton->blockSignals(true);
+ m_alignButtonGroup->blockSignals(true);
+ m_fontChooserWidget->blockSignals(true);
+
+ m_textRotation->setCurrentItem(0); // No rotation.
+ m_fontColorButton->setColor(TQt::black);
+ TQFont defaultFont;
+ m_textFont = defaultFont; // Reset to default TDE font.
+ m_textFont.setPointSize( m_defaultSizeFont );
+ m_fontChooserWidget->setFont(m_textFont);
+ m_borderText->setChecked( false );
+ m_transparentText->setChecked( false );
+ m_previewWidget->resetEdit();
+ static_cast<TQPushButton*>(m_alignButtonGroup->find(ALIGN_LEFT))->setOn(true);
+
+ m_fontChooserWidget->blockSignals(false);
+ m_fontColorButton->blockSignals(false);
+ m_alignButtonGroup->blockSignals(false);
+ slotAlignModeChanged(ALIGN_LEFT);
+}
+
+void ImageEffect_InsertText::slotAlignModeChanged(int mode)
+{
+ m_alignTextMode = mode;
+ m_textEdit->selectAll(true);
+
+ switch (m_alignTextMode)
+ {
+ case ALIGN_LEFT:
+ m_textEdit->setAlignment( TQt::AlignLeft );
+ break;
+
+ case ALIGN_RIGHT:
+ m_textEdit->setAlignment( TQt::AlignRight );
+ break;
+
+ case ALIGN_CENTER:
+ m_textEdit->setAlignment( TQt::AlignHCenter );
+ break;
+
+ case ALIGN_BLOCK:
+ m_textEdit->setAlignment( TQt::AlignJustify );
+ break;
+ }
+
+ m_textEdit->selectAll(false);
+ emit signalUpdatePreview();
+}
+
+void ImageEffect_InsertText::slotFontPropertiesChanged(const TQFont &font)
+{
+ m_textFont = font;
+ emit signalUpdatePreview();
+}
+
+void ImageEffect_InsertText::slotUpdatePreview()
+{
+ m_previewWidget->setText(m_textEdit->text(), m_textFont, m_fontColorButton->color(), m_alignTextMode,
+ m_borderText->isChecked(), m_transparentText->isChecked(),
+ m_textRotation->currentItem());
+}
+
+void ImageEffect_InsertText::finalRendering()
+{
+ accept();
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ Digikam::ImageIface iface(0, 0);
+ Digikam::DImg dest = m_previewWidget->makeInsertText();
+ iface.putOriginalImage(i18n("Insert Text"), dest.bits(), dest.width(), dest.height());
+
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamInsertTextImagesPlugin
+
diff --git a/src/imageplugins/inserttext/imageeffect_inserttext.h b/src/imageplugins/inserttext/imageeffect_inserttext.h
new file mode 100644
index 00000000..2b7c204c
--- /dev/null
+++ b/src/imageplugins/inserttext/imageeffect_inserttext.h
@@ -0,0 +1,103 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a plugin to insert a text over an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_INSERTEXT_H
+#define IMAGEEFFECT_INSERTEXT_H
+
+// TQt includes.
+
+#include <tqcolor.h>
+#include <tqimage.h>
+
+// Digikam includes.
+
+#include "imagedlgbase.h"
+
+class TQLabel;
+class TQFont;
+class TQHButtonGroup;
+class TQComboBox;
+class TQCheckBox;
+
+class KTextEdit;
+class KColorButton;
+
+namespace DigikamInsertTextImagesPlugin
+{
+
+class InsertTextWidget;
+class FontChooserWidget;
+
+class ImageEffect_InsertText : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_InsertText(TQWidget *parent);
+ ~ImageEffect_InsertText();
+
+signals:
+
+ void signalUpdatePreview();
+
+private slots:
+
+ void slotFontPropertiesChanged(const TQFont &font);
+ void slotUpdatePreview();
+ void slotAlignModeChanged(int mode);
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void finalRendering();
+
+private:
+
+ int m_alignTextMode;
+ int m_defaultSizeFont;
+
+ TQComboBox *m_textRotation;
+
+ TQCheckBox *m_borderText;
+ TQCheckBox *m_transparentText;
+
+ TQHButtonGroup *m_alignButtonGroup;
+
+ TQFont m_textFont;
+
+ KColorButton *m_fontColorButton;
+
+ FontChooserWidget *m_fontChooserWidget;
+
+ KTextEdit *m_textEdit;
+
+ InsertTextWidget *m_previewWidget;
+};
+
+} // NameSpace DigikamInsertTextImagesPlugin
+
+#endif /* IMAGEEFFECT_INSERTEXT_H */
diff --git a/src/imageplugins/inserttext/imageplugin_inserttext.cpp b/src/imageplugins/inserttext/imageplugin_inserttext.cpp
new file mode 100644
index 00000000..a7a5ab6b
--- /dev/null
+++ b/src/imageplugins/inserttext/imageplugin_inserttext.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a plugin to insert a text over an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "inserttexttool.h"
+#include "imageplugin_inserttext.h"
+#include "imageplugin_inserttext.moc"
+
+using namespace DigikamInsertTextImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_inserttext,
+ KGenericFactory<ImagePlugin_InsertText>("digikamimageplugin_inserttext"));
+
+ImagePlugin_InsertText::ImagePlugin_InsertText(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_InsertText")
+{
+ m_insertTextAction = new TDEAction(i18n("Insert Text..."), "inserttext",
+ SHIFT+CTRL+Key_T,
+ this, TQ_SLOT(slotInsertText()),
+ actionCollection(), "imageplugin_inserttext");
+
+ setXMLFile("digikamimageplugin_inserttext_ui.rc");
+
+ DDebug() << "ImagePlugin_InsertText plugin loaded" << endl;
+}
+
+ImagePlugin_InsertText::~ImagePlugin_InsertText()
+{
+}
+
+void ImagePlugin_InsertText::setEnabledActions(bool enable)
+{
+ m_insertTextAction->setEnabled(enable);
+}
+
+void ImagePlugin_InsertText::slotInsertText()
+{
+ InsertTextTool *tool = new InsertTextTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/inserttext/imageplugin_inserttext.h b/src/imageplugins/inserttext/imageplugin_inserttext.h
new file mode 100644
index 00000000..427b47c6
--- /dev/null
+++ b/src/imageplugins/inserttext/imageplugin_inserttext.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a plugin to insert a text over an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_INSERTTEXT_H
+#define IMAGEPLUGIN_INSERTTEXT_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_InsertText : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_InsertText(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_InsertText();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotInsertText();
+
+private:
+
+ TDEAction *m_insertTextAction;
+};
+
+#endif /* IMAGEPLUGIN_INSERTTEXT_H */
diff --git a/src/imageplugins/inserttext/inserttexttool.cpp b/src/imageplugins/inserttext/inserttexttool.cpp
new file mode 100644
index 00000000..3c854896
--- /dev/null
+++ b/src/imageplugins/inserttext/inserttexttool.cpp
@@ -0,0 +1,336 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a plugin to insert a text over an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqbrush.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqframe.h>
+#include <tqhbuttongroup.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqpixmap.h>
+#include <tqpushbutton.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kcolorbutton.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <ktextedit.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "editortoolsettings.h"
+#include "fontchooserwidget.h"
+#include "imageiface.h"
+#include "inserttextwidget.h"
+#include "inserttexttool.h"
+#include "inserttexttool.moc"
+
+using namespace Digikam;
+
+namespace DigikamInsertTextImagesPlugin
+{
+
+InsertTextTool::InsertTextTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("inserttext");
+ setToolName(i18n("Insert Text"));
+ setToolIcon(SmallIcon("inserttext"));
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(0);
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* l = new TQVBoxLayout(frame, 5, 0);
+ m_previewWidget = new InsertTextWidget(480, 320, frame);
+ l->addWidget(m_previewWidget);
+ TQWhatsThis::add(m_previewWidget, i18n("<p>This previews the text inserted in the image. "
+ "You can use the mouse to move the text to the right location."));
+ setToolView(frame);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+ TQGridLayout *grid = new TQGridLayout(m_gboxSettings->plainPage(), 9, 1);
+
+ m_textEdit = new KTextEdit(m_gboxSettings->plainPage());
+ m_textEdit->setCheckSpellingEnabled(true);
+ m_textEdit->setWordWrap(TQTextEdit::NoWrap);
+ TQWhatsThis::add(m_textEdit, i18n("<p>Here, enter the text you want to insert in your image."));
+
+ // -------------------------------------------------------------
+
+ m_fontChooserWidget = new FontChooserWidget(m_gboxSettings->plainPage());
+ TQWhatsThis::add( m_textEdit, i18n("<p>Here you can choose the font to be used."));
+
+ // -------------------------------------------------------------
+
+ TDEIconLoader icon;
+ m_alignButtonGroup = new TQHButtonGroup(m_gboxSettings->plainPage());
+
+ TQPushButton *alignLeft = new TQPushButton(m_alignButtonGroup);
+ m_alignButtonGroup->insert(alignLeft, ALIGN_LEFT);
+ alignLeft->setPixmap(icon.loadIcon("format-text-direction-ltr", (TDEIcon::Group) TDEIcon::Small));
+ alignLeft->setToggleButton(true);
+ TQToolTip::add(alignLeft, i18n("Align text to the left"));
+
+ TQPushButton *alignRight = new TQPushButton(m_alignButtonGroup);
+ m_alignButtonGroup->insert(alignRight, ALIGN_RIGHT);
+ alignRight->setPixmap(icon.loadIcon("format-text-direction-rtl", (TDEIcon::Group) TDEIcon::Small));
+ alignRight->setToggleButton(true);
+ TQToolTip::add(alignRight, i18n("Align text to the right"));
+
+ TQPushButton *alignCenter = new TQPushButton(m_alignButtonGroup);
+ m_alignButtonGroup->insert(alignCenter, ALIGN_CENTER);
+ alignCenter->setPixmap(icon.loadIcon("text_center", (TDEIcon::Group) TDEIcon::Small));
+ alignCenter->setToggleButton(true);
+ TQToolTip::add(alignCenter, i18n("Align text to center"));
+
+ TQPushButton *alignBlock = new TQPushButton(m_alignButtonGroup);
+ m_alignButtonGroup->insert(alignBlock, ALIGN_BLOCK);
+ alignBlock->setPixmap(icon.loadIcon("text_block", (TDEIcon::Group) TDEIcon::Small));
+ alignBlock->setToggleButton(true);
+ TQToolTip::add(alignBlock, i18n("Align text to a block"));
+
+ m_alignButtonGroup->setExclusive(true);
+ m_alignButtonGroup->setFrameShape(TQFrame::NoFrame);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label1 = new TQLabel(i18n("Rotation:"), m_gboxSettings->plainPage());
+ m_textRotation = new TQComboBox(false, m_gboxSettings->plainPage());
+ m_textRotation->insertItem(i18n("None"));
+ m_textRotation->insertItem(i18n("90 Degrees"));
+ m_textRotation->insertItem(i18n("180 Degrees"));
+ m_textRotation->insertItem(i18n("270 Degrees"));
+ TQWhatsThis::add( m_textRotation, i18n("<p>Select the text rotation to use."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Color:"), m_gboxSettings->plainPage());
+ m_fontColorButton = new KColorButton( TQt::black, m_gboxSettings->plainPage() );
+ TQWhatsThis::add( m_fontColorButton, i18n("<p>Select the font color to use."));
+
+ // -------------------------------------------------------------
+
+ m_borderText = new TQCheckBox(i18n("Add border"), m_gboxSettings->plainPage());
+ TQToolTip::add(m_borderText, i18n("Add a solid border around text using current text color"));
+
+ m_transparentText = new TQCheckBox(i18n("Semi-transparent"), m_gboxSettings->plainPage());
+ TQToolTip::add(m_transparentText, i18n("Use semi-transparent text background under image"));
+
+ grid->addMultiCellWidget(m_textEdit, 0, 2, 0, 1);
+ grid->addMultiCellWidget(m_fontChooserWidget, 3, 3, 0, 1);
+ grid->addMultiCellWidget(m_alignButtonGroup, 4, 4, 0, 1);
+ grid->addMultiCellWidget(label1, 5, 5, 0, 0);
+ grid->addMultiCellWidget(m_textRotation, 5, 5, 1, 1);
+ grid->addMultiCellWidget(label2, 6, 6, 0, 0);
+ grid->addMultiCellWidget(m_fontColorButton, 6, 6, 1, 1);
+ grid->addMultiCellWidget(m_borderText, 7, 7, 0, 1);
+ grid->addMultiCellWidget(m_transparentText, 8, 8, 0, 1);
+ grid->setMargin(0);
+ grid->setSpacing(m_gboxSettings->spacingHint());
+ grid->setRowStretch(9, 10);
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_fontChooserWidget, TQ_SIGNAL(fontSelected (const TQFont&)),
+ this, TQ_SLOT(slotFontPropertiesChanged(const TQFont&)));
+
+ connect(m_fontColorButton, TQ_SIGNAL(changed(const TQColor&)),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(m_textEdit, TQ_SIGNAL(textChanged()),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(m_alignButtonGroup, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotAlignModeChanged(int)));
+
+ connect(m_borderText, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(m_transparentText, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(m_textRotation, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ connect(this, TQ_SIGNAL(signalUpdatePreview()),
+ this, TQ_SLOT(slotUpdatePreview()));
+
+ // -------------------------------------------------------------
+
+ slotUpdatePreview();
+}
+
+InsertTextTool::~InsertTextTool()
+{
+}
+
+void InsertTextTool::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("inserttext Tool");
+ TQColor black(0, 0, 0);
+ TQFont defaultFont;
+
+ int orgW = m_previewWidget->imageIface()->originalWidth();
+ int orgH = m_previewWidget->imageIface()->originalHeight();
+
+ if (orgW > orgH) m_defaultSizeFont = (int)(orgH / 8.0);
+ else m_defaultSizeFont = (int)(orgW / 8.0);
+
+ defaultFont.setPointSize(m_defaultSizeFont);
+ m_textRotation->setCurrentItem(config->readNumEntry("Text Rotation", 0));
+ m_fontColorButton->setColor(config->readColorEntry("Font Color", &black));
+ m_textEdit->setText(config->readEntry("Text String", i18n("Enter your text here!")));
+ m_textFont = config->readFontEntry("Font Properties", &defaultFont);
+ m_fontChooserWidget->setFont(m_textFont);
+ m_alignTextMode = config->readNumEntry("Text Alignment", ALIGN_LEFT);
+ m_borderText->setChecked(config->readBoolEntry("Border Text", false));
+ m_transparentText->setChecked(config->readBoolEntry("Transparent Text", false));
+ m_previewWidget->setPositionHint(config->readRectEntry("Position Hint"));
+
+ static_cast<TQPushButton*>(m_alignButtonGroup->find(m_alignTextMode))->setOn(true);
+ slotAlignModeChanged(m_alignTextMode);
+}
+
+void InsertTextTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("inserttext Tool");
+
+ config->writeEntry("Text Rotation", m_textRotation->currentItem());
+ config->writeEntry("Font Color", m_fontColorButton->color());
+ config->writeEntry("Text String", m_textEdit->text());
+ config->writeEntry("Font Properties", m_textFont);
+ config->writeEntry("Text Alignment", m_alignTextMode);
+ config->writeEntry("Border Text", m_borderText->isChecked());
+ config->writeEntry("Transparent Text", m_transparentText->isChecked());
+ config->writeEntry("Position Hint", m_previewWidget->getPositionHint());
+
+ config->sync();
+}
+
+void InsertTextTool::slotResetSettings()
+{
+ m_fontColorButton->blockSignals(true);
+ m_alignButtonGroup->blockSignals(true);
+ m_fontChooserWidget->blockSignals(true);
+
+ m_textRotation->setCurrentItem(0); // No rotation.
+ m_fontColorButton->setColor(TQt::black);
+ TQFont defaultFont;
+ m_textFont = defaultFont; // Reset to default TDE font.
+ m_textFont.setPointSize(m_defaultSizeFont);
+ m_fontChooserWidget->setFont(m_textFont);
+ m_borderText->setChecked(false);
+ m_transparentText->setChecked(false);
+ m_previewWidget->resetEdit();
+ static_cast<TQPushButton*> (m_alignButtonGroup->find(ALIGN_LEFT))->setOn(true);
+
+ m_fontChooserWidget->blockSignals(false);
+ m_fontColorButton->blockSignals(false);
+ m_alignButtonGroup->blockSignals(false);
+ slotAlignModeChanged(ALIGN_LEFT);
+}
+
+void InsertTextTool::slotAlignModeChanged(int mode)
+{
+ m_alignTextMode = mode;
+ m_textEdit->selectAll(true);
+
+ switch (m_alignTextMode)
+ {
+ case ALIGN_LEFT:
+ m_textEdit->setAlignment( TQt::AlignLeft );
+ break;
+
+ case ALIGN_RIGHT:
+ m_textEdit->setAlignment( TQt::AlignRight );
+ break;
+
+ case ALIGN_CENTER:
+ m_textEdit->setAlignment( TQt::AlignHCenter );
+ break;
+
+ case ALIGN_BLOCK:
+ m_textEdit->setAlignment( TQt::AlignJustify );
+ break;
+ }
+
+ m_textEdit->selectAll(false);
+ emit signalUpdatePreview();
+}
+
+void InsertTextTool::slotFontPropertiesChanged(const TQFont& font)
+{
+ m_textFont = font;
+ emit signalUpdatePreview();
+}
+
+void InsertTextTool::slotUpdatePreview()
+{
+ m_previewWidget->setText(m_textEdit->text(), m_textFont, m_fontColorButton->color(), m_alignTextMode,
+ m_borderText->isChecked(), m_transparentText->isChecked(),
+ m_textRotation->currentItem());
+}
+
+void InsertTextTool::finalRendering()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+
+ ImageIface iface(0, 0);
+ DImg dest = m_previewWidget->makeInsertText();
+ iface.putOriginalImage(i18n("Insert Text"), dest.bits(), dest.width(), dest.height());
+
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamInsertTextImagesPlugin
diff --git a/src/imageplugins/inserttext/inserttexttool.h b/src/imageplugins/inserttext/inserttexttool.h
new file mode 100644
index 00000000..c148aa60
--- /dev/null
+++ b/src/imageplugins/inserttext/inserttexttool.h
@@ -0,0 +1,111 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a plugin to insert a text over an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef INSERTEXTTOOL_H
+#define INSERTEXTTOOL_H
+
+// TQt includes.
+
+#include <tqfont.h>
+#include <tqcolor.h>
+#include <tqimage.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQLabel;
+class TQFont;
+class TQHButtonGroup;
+class TQComboBox;
+class TQCheckBox;
+
+class KTextEdit;
+class KColorButton;
+
+namespace Digikam
+{
+class EditorToolSettings;
+}
+
+namespace DigikamInsertTextImagesPlugin
+{
+
+class InsertTextWidget;
+class FontChooserWidget;
+
+class InsertTextTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ InsertTextTool(TQObject *parent);
+ ~InsertTextTool();
+
+signals:
+
+ void signalUpdatePreview();
+
+private slots:
+
+ void slotFontPropertiesChanged(const TQFont& font);
+ void slotUpdatePreview();
+ void slotAlignModeChanged(int mode);
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+
+private:
+
+ int m_alignTextMode;
+ int m_defaultSizeFont;
+
+ TQComboBox *m_textRotation;
+
+ TQCheckBox *m_borderText;
+ TQCheckBox *m_transparentText;
+
+ TQHButtonGroup *m_alignButtonGroup;
+
+ TQFont m_textFont;
+
+ KColorButton *m_fontColorButton;
+
+ KTextEdit *m_textEdit;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+
+ FontChooserWidget *m_fontChooserWidget;
+
+ InsertTextWidget *m_previewWidget;
+};
+
+} // NameSpace DigikamInsertTextImagesPlugin
+
+#endif /* INSERTEXTTOOL_H */
diff --git a/src/imageplugins/inserttext/inserttextwidget.cpp b/src/imageplugins/inserttext/inserttextwidget.cpp
new file mode 100644
index 00000000..dc5b65f4
--- /dev/null
+++ b/src/imageplugins/inserttext/inserttextwidget.cpp
@@ -0,0 +1,622 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a widget to insert a text over an image.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+#include <cmath>
+
+// TQt includes.
+
+#include <tqpainter.h>
+#include <tqfont.h>
+#include <tqfontmetrics.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdeglobal.h>
+
+// Digikam includes.
+
+#include "imageiface.h"
+
+// Local includes.
+
+#include "inserttextwidget.h"
+#include "inserttextwidget.moc"
+
+namespace DigikamInsertTextImagesPlugin
+{
+
+InsertTextWidget::InsertTextWidget(int w, int h, TQWidget *parent)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ m_currentMoving = false;
+
+ m_iface = new Digikam::ImageIface(w, h);
+ m_data = m_iface->getPreviewImage();
+ m_w = m_iface->previewWidth();
+ m_h = m_iface->previewHeight();
+ m_pixmap = new TQPixmap(w, h);
+ m_pixmap->fill(colorGroup().background());
+
+ setBackgroundMode(TQt::NoBackground);
+ setMinimumSize(w, h);
+ setMouseTracking(true);
+
+ m_rect = TQRect(width()/2-m_w/2, height()/2-m_h/2, m_w, m_h);
+ m_textRect = TQRect();
+
+ m_backgroundColor = TQColor(0xCC, 0xCC, 0xCC);
+ m_transparency = 210;
+}
+
+InsertTextWidget::~InsertTextWidget()
+{
+ delete [] m_data;
+ delete m_iface;
+ delete m_pixmap;
+}
+
+Digikam::ImageIface* InsertTextWidget::imageIface()
+{
+ return m_iface;
+}
+
+void InsertTextWidget::resetEdit()
+{
+ // signal this needs to be filled by makePixmap
+ m_textRect = TQRect();
+ makePixmap();
+ repaint(false);
+}
+
+void InsertTextWidget::setText(TQString text, TQFont font, TQColor color, int alignMode,
+ bool border, bool transparent, int rotation)
+{
+ m_textString = text;
+ m_textColor = color;
+ m_textBorder = border;
+ m_textTransparent = transparent;
+ m_textRotation = rotation;
+
+ switch (alignMode)
+ {
+ case ALIGN_LEFT:
+ m_alignMode = TQt::AlignLeft;
+ break;
+
+ case ALIGN_RIGHT:
+ m_alignMode = TQt::AlignRight;
+ break;
+
+ case ALIGN_CENTER:
+ m_alignMode = TQt::AlignHCenter;
+ break;
+
+ case ALIGN_BLOCK:
+ m_alignMode = TQt::AlignJustify;
+ break;
+ }
+
+ // Center text if top left corner text area is not visible.
+
+ /*
+ if ( m_textFont.pointSize() != font.pointSize() &&
+ !rect().contains( m_textRect.x(), m_textRect.y() ) )
+ {
+ m_textFont = font;
+ resetEdit();
+ return;
+ }
+ */
+
+ m_textFont = font;
+
+ makePixmap();
+ repaint(false);
+}
+
+void InsertTextWidget::setPositionHint(TQRect hint)
+{
+ // interpreted by composeImage
+ m_positionHint = hint;
+ if (m_textRect.isValid())
+ {
+ // invalidate current position so that hint is certainly interpreted
+ m_textRect = TQRect();
+ makePixmap();
+ repaint();
+ }
+}
+
+TQRect InsertTextWidget::getPositionHint()
+{
+ TQRect hint;
+ if (m_textRect.isValid())
+ {
+ // We normalize on the size of the image, but we store as int. Precision loss is no problem.
+ hint.setX( (int) ((float)(m_textRect.x() - m_rect.x()) / (float)m_rect.width() * 10000.0) );
+ hint.setY( (int) ((float)(m_textRect.y() - m_rect.y()) / (float)m_rect.height() * 10000.0) );
+ hint.setWidth( (int) ((float)m_textRect.width() / (float)m_rect.width() * 10000.0) );
+ hint.setHeight( (int) ((float)m_textRect.height() / (float)m_rect.height() * 10000.0) );
+ }
+ return hint;
+}
+
+Digikam::DImg InsertTextWidget::makeInsertText(void)
+{
+ int orgW = m_iface->originalWidth();
+ int orgH = m_iface->originalHeight();
+ float ratioW = (float)orgW/(float)m_w;
+ float ratioH = (float)orgH/(float)m_h;
+
+ int x, y;
+ if (m_textRect.isValid())
+ {
+ // convert from widget to image coordinates, then to original size
+ x = lroundf( (m_textRect.x() - m_rect.x()) * ratioW);
+ y = lroundf( (m_textRect.y() - m_rect.y()) * ratioH);
+ }
+ else
+ {
+ x = -1;
+ y = -1;
+ }
+
+ // Get original image
+ Digikam::DImg image = m_iface->getOriginalImg()->copy();
+
+ int borderWidth = TQMAX(1, lroundf(ratioW));
+ // compose and draw result on image
+ composeImage(&image, 0, x, y,
+ m_textFont, m_textFont.pointSizeFloat(),
+ m_textRotation, m_textColor, m_alignMode, m_textString,
+ m_textTransparent, m_backgroundColor,
+ m_textBorder ? BORDER_NORMAL : BORDER_NONE, borderWidth, borderWidth);
+
+ return image;
+}
+
+void InsertTextWidget::makePixmap(void)
+{
+ int orgW = m_iface->originalWidth();
+ int orgH = m_iface->originalHeight();
+ float ratioW = (float)m_w / (float)orgW;
+ float ratioH = (float)m_h / (float)orgH;
+
+ int x, y;
+ if (m_textRect.isValid())
+ {
+ // convert from widget to image coordinates
+ x = m_textRect.x() - m_rect.x();
+ y = m_textRect.y() - m_rect.y();
+ }
+ else
+ {
+ x = -1;
+ y = -1;
+ }
+
+ // get preview image data
+ uchar *data = m_iface->getPreviewImage();
+ Digikam::DImg image(m_iface->previewWidth(), m_iface->previewHeight(), m_iface->previewSixteenBit(),
+ m_iface->previewHasAlpha(), data);
+ delete [] data;
+
+ // paint pixmap for drawing this widget
+ // First, fill with background color
+ m_pixmap->fill(colorGroup().background());
+ TQPainter p(m_pixmap);
+ // Convert image to pixmap and draw it
+ TQPixmap imagePixmap = image.convertToPixmap();
+ p.drawPixmap(m_rect.x(), m_rect.y(),
+ imagePixmap, 0, 0, imagePixmap.width(), imagePixmap.height());
+
+ // prepare painter for use by compose image
+ p.setClipRect(m_rect);
+ p.translate(m_rect.x(), m_rect.y());
+
+ // compose image and draw result directly on pixmap, with correct offset
+ TQRect textRect = composeImage(&image, &p, x, y,
+ m_textFont, m_textFont.pointSizeFloat() * ((ratioW > ratioH) ? ratioW : ratioH),
+ m_textRotation, m_textColor, m_alignMode, m_textString,
+ m_textTransparent, m_backgroundColor,
+ m_textBorder ? BORDER_NORMAL : BORDER_SUPPORT, 1, 1);
+
+ p.end();
+
+ // store new text rectangle
+ // convert from image to widget coordinates
+ m_textRect.setX(textRect.x() + m_rect.x());
+ m_textRect.setY(textRect.y() + m_rect.y());
+ m_textRect.setSize(textRect.size());
+}
+
+/*
+ Take data from image, draw text at x|y with specified parameters.
+ If destPainter is null, draw to image,
+ if destPainter is not null, draw directly using the painter.
+ Returns modified area of image.
+*/
+TQRect InsertTextWidget::composeImage(Digikam::DImg *image, TQPainter *destPainter,
+ int x, int y,
+ TQFont font, float pointSize, int textRotation, TQColor textColor,
+ int alignMode, const TQString &textString,
+ bool transparentBackground, TQColor backgroundColor,
+ BorderMode borderMode, int borderWidth, int spacing)
+{
+ /*
+ The problem we have to solve is that we have no pixel access to font rendering,
+ we have to let TQt do the drawing. On the other hand we need to support 16 bit, which
+ cannot be done with TQPixmap.
+ The current solution cuts out the text area, lets TQt do its drawing, converts back and blits to original.
+ */
+ Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(Digikam::DColorComposer::PorterDuffNone);
+
+ int maxWidth, maxHeight;
+ if (x == -1 && y == -1)
+ {
+ maxWidth = image->width();
+ maxHeight = image->height();
+ }
+ else
+ {
+ maxWidth = image->width() - x;
+ maxHeight = image->height() - y;
+ }
+
+ // find out size of the area that we are drawing to
+ font.setPointSizeFloat(pointSize);
+ TQFontMetrics fontMt( font );
+ TQRect fontRect = fontMt.boundingRect(0, 0, maxWidth, maxHeight, 0, textString);
+
+ int fontWidth, fontHeight;
+
+ switch(textRotation)
+ {
+ case ROTATION_NONE:
+ case ROTATION_180:
+ default:
+ fontWidth = fontRect.width();
+ fontHeight = fontRect.height();
+ break;
+
+ case ROTATION_90:
+ case ROTATION_270:
+ fontWidth = fontRect.height();
+ fontHeight = fontRect.width();
+ break;
+ }
+
+ // x, y == -1 means that we have to find a good initial position for the text here
+ if (x == -1 && y == -1)
+ {
+ // was a valid position hint stored from last use?
+ if (m_positionHint.isValid())
+ {
+ // We assume that people tend to orient text along the edges,
+ // so we do some guessing so that positions such as "in the lower right corner"
+ // will be remembered across different image sizes.
+
+ // get relative positions
+ float fromTop = (float)m_positionHint.top() / 10000.0;
+ float fromBottom = 1.0 - (float)m_positionHint.bottom() / 10000.0;
+ float fromLeft = (float)m_positionHint.left() / 10000.0;
+ float fromRight = 1.0 - (float)m_positionHint.right() / 10000.0;
+
+ // calculate horizontal position
+ if (fromLeft < fromRight)
+ {
+ x = (int)(fromLeft * maxWidth);
+
+ // we are placing from the smaller distance,
+ // so if now the larger distance is actually too small,
+ // fall back to standard placement, nothing to lose.
+ if (x + fontWidth > maxWidth)
+ x = TQMAX( (maxWidth - fontWidth) / 2, 0);
+ }
+ else
+ {
+ x = maxWidth - (int)(fromRight * maxWidth) - fontWidth;
+ if ( x < 0 )
+ x = TQMAX( (maxWidth - fontWidth) / 2, 0);
+ }
+
+ // calculate vertical position
+ if (fromTop < fromBottom)
+ {
+ y = (int)(fromTop * maxHeight);
+ if (y + fontHeight > maxHeight)
+ y = TQMAX( (maxHeight - fontHeight) / 2, 0);
+ }
+ else
+ {
+ y = maxHeight - (int)(fromBottom * maxHeight) - fontHeight;
+ if ( y < 0 )
+ y = TQMAX( (maxHeight - fontHeight) / 2, 0);
+ }
+
+ if (! TQRect(x, y, fontWidth, fontHeight).
+ intersects(TQRect(0, 0, maxWidth, maxHeight)) )
+ {
+ // emergency fallback - nothing is visible
+ x = TQMAX( (maxWidth - fontWidth) / 2, 0);
+ y = TQMAX( (maxHeight - fontHeight) / 2, 0);
+ }
+
+ // invalidate position hint, use only once
+ m_positionHint = TQRect();
+ }
+ else
+ {
+ // use standard position
+ x = TQMAX( (maxWidth - fontWidth) / 2, 0);
+ y = TQMAX( (maxHeight - fontHeight) / 2, 0);
+ }
+ }
+
+ // create a rectangle relative to image
+ TQRect drawRect( x, y, fontWidth + 2 * borderWidth + 2 * spacing, fontHeight + 2 * borderWidth + 2 * spacing);
+
+ // create a rectangle relative to textArea, excluding the border
+ TQRect textAreaBackgroundRect( borderWidth, borderWidth, fontWidth + 2 * spacing, fontHeight + 2 * spacing);
+
+ // create a rectangle relative to textArea, excluding the border and spacing
+ TQRect textAreaTextRect( borderWidth + spacing, borderWidth + spacing, fontWidth, fontHeight );
+
+ // create a rectangle relative to textArea, including the border,
+ // for drawing the rectangle, taking into account that the width of the TQPen goes in and out in equal parts
+ TQRect textAreaDrawRect( borderWidth / 2, borderWidth / 2, fontWidth + borderWidth + 2 * spacing,
+ fontHeight + borderWidth + 2 * spacing );
+
+ // cut out the text area
+ Digikam::DImg textArea = image->copy(drawRect);
+
+ if (textArea.isNull())
+ return TQRect();
+
+ // compose semi-transparent background over textArea
+ if (transparentBackground)
+ {
+ Digikam::DImg transparentLayer(textAreaBackgroundRect.width(), textAreaBackgroundRect.height(), textArea.sixteenBit(), true);
+ Digikam::DColor transparent(backgroundColor);
+ transparent.setAlpha(m_transparency);
+ if (image->sixteenBit())
+ transparent.convertToSixteenBit();
+ transparentLayer.fill(transparent);
+ textArea.bitBlendImage(composer, &transparentLayer, 0, 0, transparentLayer.width(), transparentLayer.height(),
+ textAreaBackgroundRect.x(), textAreaBackgroundRect.y());
+ }
+
+ Digikam::DImg textNotDrawn;
+ if (textArea.sixteenBit())
+ {
+ textNotDrawn = textArea.copy();
+ textNotDrawn.convertToEightBit();
+ }
+ else
+ textNotDrawn = textArea;
+
+ // We have no direct pixel access to font rendering, so now we need to use TQt/X11 for the drawing
+
+ // convert text area to pixmap
+ TQPixmap pixmap = textNotDrawn.convertToPixmap();
+ // paint on pixmap
+ TQPainter p(&pixmap);
+ p.setPen( TQPen(textColor, 1) ) ;
+ p.setFont( font );
+ p.save();
+
+ // translate to origin of text, leaving space for the border
+ p.translate(textAreaTextRect.x(), textAreaTextRect.y());
+
+ switch(textRotation)
+ {
+ case ROTATION_NONE:
+ p.drawText( 0, 0, textAreaTextRect.width(),
+ textAreaTextRect.height(), alignMode, textString );
+ break;
+ case ROTATION_90:
+ p.translate(textAreaTextRect.width(), 0);
+ p.rotate(90.0);
+ p.drawText( 0, 0, textAreaTextRect.height(), textAreaTextRect.width(),
+ alignMode, textString );
+ break;
+ case ROTATION_180:
+ p.translate(textAreaTextRect.width(), textAreaTextRect.height());
+ p.rotate(180.0);
+ p.drawText( 0, 0, textAreaTextRect.width(), textAreaTextRect.height(),
+ alignMode, textString );
+ break;
+ case ROTATION_270:
+ p.translate(0, textAreaTextRect.height());
+ p.rotate(270.0);
+ p.drawText( 0, 0, textAreaTextRect.height(), textAreaTextRect.width(),
+ alignMode, textString );
+ break;
+ }
+
+ p.restore();
+
+ // Drawing rectangle around text.
+
+ if (borderMode == BORDER_NORMAL) // Decorative border using text color.
+ {
+ p.setPen( TQPen(textColor, borderWidth, TQt::SolidLine,
+ TQt::SquareCap, TQt::RoundJoin) ) ;
+ p.drawRect(textAreaDrawRect);
+ }
+ else if (borderMode == BORDER_SUPPORT) // Make simple dot line border to help user.
+ {
+ p.setPen(TQPen(TQt::white, 1, TQt::SolidLine));
+ p.drawRect(textAreaDrawRect);
+ p.setPen(TQPen(TQt::red, 1, TQt::DotLine));
+ p.drawRect(textAreaDrawRect);
+ }
+ p.end();
+
+ if (!destPainter)
+ {
+ // convert to TQImage, then to DImg
+ TQImage pixmapImage = pixmap.convertToImage();
+ Digikam::DImg textDrawn(pixmapImage.width(), pixmapImage.height(), false, true, pixmapImage.bits());
+
+ // This does not work: during the conversion, colors are altered significantly (diffs of 1 to 10 in each component),
+ // so we cannot find out which pixels have actually been touched.
+ /*
+ // Compare the result of drawing with the previous version.
+ // Set all unchanged pixels to transparent
+ Digikam::DColor color, ncolor;
+ uchar *ptr, *nptr;
+ ptr = textDrawn.bits();
+ nptr = textNotDrawn.bits();
+ int bytesDepth = textDrawn.bytesDepth();
+ int numPixels = textDrawn.width() * textDrawn.height();
+ for (int i = 0; i < numPixels; i++, ptr+= bytesDepth, nptr += bytesDepth)
+ {
+ color.setColor(ptr, false);
+ ncolor.setColor(nptr, false);
+ if ( color.red() == ncolor.red() &&
+ color.green() == ncolor.green() &&
+ color.blue() == ncolor.blue())
+ {
+ color.setAlpha(0);
+ color.setPixel(ptr);
+ }
+ }
+ // convert to 16 bit if needed
+ */
+ textDrawn.convertToDepthOfImage(&textArea);
+
+ // now compose to original: only pixels affected by drawing text and border are changed, not whole area
+ textArea.bitBlendImage(composer, &textDrawn, 0, 0, textDrawn.width(), textDrawn.height(), 0, 0);
+
+ // copy result to original image
+ image->bitBltImage(&textArea, drawRect.x(), drawRect.y());
+ }
+ else
+ {
+ destPainter->drawPixmap(drawRect.x(), drawRect.y(), pixmap, 0, 0, pixmap.width(), pixmap.height());
+ }
+
+ delete composer;
+
+ return drawRect;
+}
+
+void InsertTextWidget::paintEvent( TQPaintEvent * )
+{
+ bitBlt(this, 0, 0, m_pixmap);
+}
+
+void InsertTextWidget::resizeEvent(TQResizeEvent * e)
+{
+ blockSignals(true);
+ delete m_pixmap;
+
+ int w = e->size().width();
+ int h = e->size().height();
+
+ int textX = m_textRect.x() - m_rect.x();
+ int textY = m_textRect.y() - m_rect.y();
+ int old_w = m_w;
+ int old_h = m_h;
+ m_data = m_iface->setPreviewImageSize(w, h);
+ m_w = m_iface->previewWidth();
+ m_h = m_iface->previewHeight();
+
+ m_pixmap = new TQPixmap(w, h);
+ m_rect = TQRect(w/2-m_w/2, h/2-m_h/2, m_w, m_h);
+
+ if (m_textRect.isValid())
+ {
+ int textWidth = m_textRect.width();
+ int textHeight = m_textRect.height();
+
+ textX = lroundf( textX * (float)m_w / (float)old_w );
+ textY = lroundf( textY * (float)m_h / (float)old_h );
+ textWidth = lroundf(textWidth * (float)m_w / (float)old_w );
+ textHeight = lroundf(textHeight * (float)m_h / (float)old_h );
+
+ m_textRect.setX(textX + m_rect.x());
+ m_textRect.setY(textY + m_rect.y());
+ m_textRect.setWidth(textWidth);
+ m_textRect.setHeight(textHeight);
+ makePixmap();
+ }
+
+ blockSignals(false);
+}
+
+void InsertTextWidget::mousePressEvent ( TQMouseEvent * e )
+{
+ if ( e->button() == TQt::LeftButton &&
+ m_textRect.contains( e->x(), e->y() ) )
+ {
+ m_xpos = e->x();
+ m_ypos = e->y();
+ setCursor ( KCursor::sizeAllCursor() );
+ m_currentMoving = true;
+ }
+}
+
+void InsertTextWidget::mouseReleaseEvent ( TQMouseEvent * )
+{
+ setCursor ( KCursor::arrowCursor() );
+ m_currentMoving = false;
+}
+
+void InsertTextWidget::mouseMoveEvent ( TQMouseEvent * e )
+{
+ if ( rect().contains( e->x(), e->y() ) )
+ {
+ if ( e->state() == TQt::LeftButton && m_currentMoving )
+ {
+ uint newxpos = e->x();
+ uint newypos = e->y();
+
+ m_textRect.moveBy(newxpos - m_xpos, newypos - m_ypos);
+
+ makePixmap();
+ repaint(false);
+
+ m_xpos = newxpos;
+ m_ypos = newypos;
+ setCursor( KCursor::handCursor() );
+ }
+ else if ( m_textRect.contains( e->x(), e->y() ) )
+ {
+ setCursor ( KCursor::sizeAllCursor() );
+ }
+ else
+ {
+ setCursor ( KCursor::arrowCursor() );
+ }
+ }
+}
+
+} // NameSpace DigikamInsertTextImagesPlugin
diff --git a/src/imageplugins/inserttext/inserttextwidget.h b/src/imageplugins/inserttext/inserttextwidget.h
new file mode 100644
index 00000000..bbce9189
--- /dev/null
+++ b/src/imageplugins/inserttext/inserttextwidget.h
@@ -0,0 +1,156 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-14
+ * Description : a widget to insert a text over an image.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef INSERTTEXTWIDGET_H
+#define INSERTTEXTWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqimage.h>
+#include <tqrect.h>
+#include <tqsize.h>
+#include <tqpixmap.h>
+#include <tqstring.h>
+#include <tqfont.h>
+#include <tqcolor.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Digikam includes.
+
+#include "dimg.h"
+
+class TQPixmap;
+
+namespace Digikam
+{
+class ImageIface;
+}
+
+namespace DigikamInsertTextImagesPlugin
+{
+
+enum Action
+{
+ ALIGN_LEFT=0,
+ ALIGN_RIGHT,
+ ALIGN_CENTER,
+ ALIGN_BLOCK,
+ BORDER_TEXT,
+ TRANSPARENT_TEXT
+};
+
+enum TextRotation
+{
+ ROTATION_NONE=0,
+ ROTATION_90,
+ ROTATION_180,
+ ROTATION_270
+};
+
+enum BorderMode
+{
+ BORDER_NONE,
+ BORDER_SUPPORT,
+ BORDER_NORMAL
+};
+
+class InsertTextWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ InsertTextWidget(int w, int h, TQWidget *parent=0);
+ ~InsertTextWidget();
+
+ Digikam::ImageIface* imageIface();
+ Digikam::DImg makeInsertText(void);
+
+ void setText(TQString text, TQFont font, TQColor color, int alignMode,
+ bool border, bool transparent, int rotation);
+ void resetEdit(void);
+
+ void setPositionHint(TQRect hint);
+ TQRect getPositionHint();
+
+protected:
+
+ void paintEvent(TQPaintEvent *e);
+ void resizeEvent(TQResizeEvent * e);
+ void mousePressEvent(TQMouseEvent * e);
+ void mouseReleaseEvent(TQMouseEvent * e);
+ void mouseMoveEvent(TQMouseEvent * e);
+
+ void makePixmap(void);
+ TQRect composeImage(Digikam::DImg *image, TQPainter *destPainter,
+ int x, int y,
+ TQFont font, float pointSize, int textRotation, TQColor textColor,
+ int alignMode, const TQString &textString,
+ bool transparentBackground, TQColor backgroundColor,
+ BorderMode borderMode, int borderWidth, int spacing);
+
+private:
+
+ bool m_currentMoving;
+ bool m_textBorder;
+ bool m_textTransparent;
+
+ int m_alignMode;
+ int m_textRotation;
+
+ uchar *m_data;
+ int m_w;
+ int m_h;
+
+ int m_xpos;
+ int m_ypos;
+
+ int m_transparency;
+
+ TQPixmap *m_pixmap;
+
+ TQRect m_rect;
+ TQRect m_textRect;
+
+ TQString m_textString;
+
+ TQFont m_textFont;
+
+ TQColor m_textColor;
+
+ TQColor m_backgroundColor;
+
+ TQRect m_positionHint;
+
+ Digikam::ImageIface *m_iface;
+};
+
+} // NameSpace DigikamInsertTextImagesPlugin
+
+#endif /* INSERTTEXTWIDGET_H */
diff --git a/src/imageplugins/lensdistortion/Makefile.am b/src/imageplugins/lensdistortion/Makefile.am
new file mode 100644
index 00000000..cd157aa1
--- /dev/null
+++ b/src/imageplugins/lensdistortion/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_lensdistortion_la_SOURCES = imageplugin_lensdistortion.cpp \
+ lensdistortiontool.cpp \
+ lensdistortion.cpp pixelaccess.cpp
+
+digikamimageplugin_lensdistortion_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_lensdistortion_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_lensdistortion.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_lensdistortion.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_lensdistortion_ui.rc
diff --git a/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion.desktop b/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion.desktop
new file mode 100644
index 00000000..da529559
--- /dev/null
+++ b/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion.desktop
@@ -0,0 +1,50 @@
+[Desktop Entry]
+Name=ImagePlugin_LensDistortion
+Name[bg]=Приставка за снимки - Аберации от обективи
+Name[da]=Billedplugin_Linseforvrængning
+Name[el]=ΠρόσθετοΕικόνας_ΠαραμόρφωσηΦακών
+Name[fi]=Linssivääristymä
+Name[hr]=Izobličena leća
+Name[it]=PluginImmagini_DistorsioneLenticolare
+Name[nl]=Afbeeldingsplugin_Lensafwijking
+Name[sr]=Изобличење сочива
+Name[sr@Latn]=Izobličenje sočiva
+Name[sv]=Insticksprogram för linsförvrängning
+Name[tr]=ResimEklentisi_MercekÇarpıtması
+Name[xx]=xxImagePlugin_LensDistortionxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Spherical aberration image correction plugin for digiKam
+Comment[bg]=Приставка на digiKam за корекция на аберации от обективи в снимките
+Comment[ca]=Connector pel digiKam per corregir l'aberració esfèrica d'una imatge
+Comment[da]=Plugin til korrigering af sfærisk afvigelse for Digikam
+Comment[de]=digiKam-Modul zur Reduzierung kugelförmiger Verzerrung durch Linsen
+Comment[el]=Πρόσθετο διόρθωσης εικόνας σφαιρικής παρέκκλισης για το digiKam
+Comment[es]=Plugin para digiKam para corrección de aberraciones de imagen esféricas
+Comment[et]=DigiKami sfäärilise aberratsiooni korrigeerimise plugin
+Comment[fa]=وصلۀ اصلاح تصویر انحراف کروی برای digiKam
+Comment[fi]=Palloaberraatio (kalansilmävääristymä)
+Comment[gl]=Un plugin de digiKam para corrixir a aberrazón esférica da imaxe
+Comment[hr]=digiKam dodatak za ispravljanje kružne aberacije
+Comment[is]=Íforrit fyrir digiKam sem minnkar hringskekkingu linsu
+Comment[it]=Plugin di correzione dell'aberrazione sferica delle immagini per digiKam
+Comment[ja]=digiKam 球面収差補正プラグイン
+Comment[nds]=digiKam-Moduul för't Richten vun Kugel-Vertarren
+Comment[nl]=Digikam-plugin voor het corrigeren van bolvormige afwijkingen
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਗੋਲਾ ਐਬੱਰੇਸ਼ਨ ਚਿੱਤਰ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam korygująca aberrację sferyczną
+Comment[pt]=Um 'plugin' do digiKam para corrigir a aberração esférica da imagem
+Comment[pt_BR]=Um 'plugin' do digiKam para corrigir a aberração esférica da imagem
+Comment[ru]=Модуль digiKam коррекции сферических искажений
+Comment[sk]=digiKam plugin na korekciu sférickej aberácie šošovky
+Comment[sr]=digiKam-ов прикључак за исправљање сферног искривљења слике
+Comment[sr@Latn]=digiKam-ov priključak za ispravljanje sfernog iskrivljenja slike
+Comment[sv]=Digikam insticksprogram för korrigering av sfärisk avvikelse i bild
+Comment[tr]=digiKam için resim küresel sapma düzeltme eklentisi
+Comment[uk]=Втулок коректування сферичних спотворень для digiKam
+Comment[vi]=Phần bổ sung sửa quang sai hình cầu ảnh cho digiKam
+Comment[xx]=xxSpherical aberration image correction plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_lensdistortion
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion_ui.rc b/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion_ui.rc
new file mode 100644
index 00000000..4705467e
--- /dev/null
+++ b/src/imageplugins/lensdistortion/digikamimageplugin_lensdistortion_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_lensdistortion" >
+
+ <MenuBar>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ <Action name="imageplugin_lensdistortion" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action name="imageplugin_lensdistortion" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/lensdistortion/imageeffect_lensdistortion.cpp b/src/imageplugins/lensdistortion/imageeffect_lensdistortion.cpp
new file mode 100644
index 00000000..89420a9c
--- /dev/null
+++ b/src/imageplugins/lensdistortion/imageeffect_lensdistortion.cpp
@@ -0,0 +1,317 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-27
+ * Description : a plugin to reduce lens distorsions to an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ include.
+
+#include <cstring>
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqbrush.h>
+#include <tqpen.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeconfig.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "lensdistortion.h"
+#include "imageeffect_lensdistortion.h"
+#include "imageeffect_lensdistortion.moc"
+
+namespace DigikamLensDistortionImagesPlugin
+{
+
+ImageEffect_LensDistortion::ImageEffect_LensDistortion(TQWidget* parent)
+ : Digikam::ImageGuideDlg(parent, i18n("Lens Distortion Correction"),
+ "lensdistortion", false, true, true,
+ Digikam::ImageGuideWidget::HVGuideMode)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Lens Distortion Correction"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to reduce spherical aberration caused "
+ "by a lens to an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2006, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ about->addAuthor("David Hodson", I18N_NOOP("Lens distortion correction algorithm."),
+ "hodsond at acm dot org");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 8, 1, spacingHint());
+
+ m_maskPreviewLabel = new TQLabel( gboxSettings );
+ m_maskPreviewLabel->setAlignment ( TQt::AlignHCenter | TQt::AlignVCenter );
+ TQWhatsThis::add( m_maskPreviewLabel, i18n("<p>You can see here a thumbnail preview of the distortion correction "
+ "applied to a cross pattern.") );
+ gridSettings->addMultiCellWidget(m_maskPreviewLabel, 0, 0, 0, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label1 = new TQLabel(i18n("Main:"), gboxSettings);
+
+ m_mainInput = new KDoubleNumInput(gboxSettings);
+ m_mainInput->setPrecision(1);
+ m_mainInput->setRange(-100.0, 100.0, 0.1, true);
+ TQWhatsThis::add( m_mainInput, i18n("<p>This value controls the amount of distortion. Negative values correct lens barrel "
+ "distortion, while positive values correct lens pincushion distortion."));
+
+ gridSettings->addMultiCellWidget(label1, 1, 1, 0, 1);
+ gridSettings->addMultiCellWidget(m_mainInput, 2, 2, 0, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Edge:"), gboxSettings);
+
+ m_edgeInput = new KDoubleNumInput(gboxSettings);
+ m_edgeInput->setPrecision(1);
+ m_edgeInput->setRange(-100.0, 100.0, 0.1, true);
+ TQWhatsThis::add( m_edgeInput, i18n("<p>This value controls in the same manner as the Main control, but has more effect "
+ "at the edges of the image than at the center."));
+
+ gridSettings->addMultiCellWidget(label2, 3, 3, 0, 1);
+ gridSettings->addMultiCellWidget(m_edgeInput, 4, 4, 0, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Zoom:"), gboxSettings);
+
+ m_rescaleInput = new KDoubleNumInput(gboxSettings);
+ m_rescaleInput->setPrecision(1);
+ m_rescaleInput->setRange(-100.0, 100.0, 0.1, true);
+ TQWhatsThis::add( m_rescaleInput, i18n("<p>This value rescales the overall image size."));
+
+ gridSettings->addMultiCellWidget(label3, 5, 5, 0, 1);
+ gridSettings->addMultiCellWidget(m_rescaleInput, 6, 6, 0, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label4 = new TQLabel(i18n("Brighten:"), gboxSettings);
+
+ m_brightenInput = new KDoubleNumInput(gboxSettings);
+ m_brightenInput->setPrecision(1);
+ m_brightenInput->setRange(-100.0, 100.0, 0.1, true);
+ TQWhatsThis::add( m_brightenInput, i18n("<p>This value adjusts the brightness in image corners."));
+
+ gridSettings->addMultiCellWidget(label4, 7, 7, 0, 1);
+ gridSettings->addMultiCellWidget(m_brightenInput, 8, 8, 0, 1);
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_mainInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_edgeInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_rescaleInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_brightenInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ // -------------------------------------------------------------
+
+ /* Calc transform preview.
+ We would like a checkered area to demonstrate the effect.
+ We do not have any drawing support in DImg, so we let TQt draw.
+ First we create a white TQImage. We convert this to a TQPixmap,
+ on which we can draw. Then we convert back to TQImage,
+ convert the TQImage to a DImg which we only need to create once, here.
+ Later, we apply the effect on a copy and convert the DImg to TQPixmap.
+ Longing for TQt4 where we can paint directly on the TQImage...
+ */
+
+ TQImage preview(120, 120, 32);
+ memset(preview.bits(), 255, preview.numBytes());
+ TQPixmap pix (preview);
+ TQPainter pt(&pix);
+ pt.setPen( TQPen(TQt::black, 1) );
+ pt.fillRect( 0, 0, pix.width(), pix.height(), TQBrush(TQt::black, TQt::CrossPattern) );
+ pt.drawRect( 0, 0, pix.width(), pix.height() );
+ pt.end();
+ TQImage preview2(pix.convertToImage());
+ m_previewRasterImage = Digikam::DImg(preview2.width(), preview2.height(), false, false, preview2.bits());
+}
+
+ImageEffect_LensDistortion::~ImageEffect_LensDistortion()
+{
+}
+
+void ImageEffect_LensDistortion::readUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("lensdistortion Tool Dialog");
+
+ m_mainInput->blockSignals(true);
+ m_edgeInput->blockSignals(true);
+ m_rescaleInput->blockSignals(true);
+ m_brightenInput->blockSignals(true);
+
+ m_mainInput->setValue(config->readDoubleNumEntry("2nd Order Distortion", 0.0));
+ m_edgeInput->setValue(config->readDoubleNumEntry("4th Order Distortion",0.0));
+ m_rescaleInput->setValue(config->readDoubleNumEntry("Zoom Factor", 0.0));
+ m_brightenInput->setValue(config->readDoubleNumEntry("Brighten", 0.0));
+
+ m_mainInput->blockSignals(false);
+ m_edgeInput->blockSignals(false);
+ m_rescaleInput->blockSignals(false);
+ m_brightenInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ImageEffect_LensDistortion::writeUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("lensdistortion Tool Dialog");
+ config->writeEntry("2nd Order Distortion", m_mainInput->value());
+ config->writeEntry("4th Order Distortion", m_edgeInput->value());
+ config->writeEntry("Zoom Factor", m_rescaleInput->value());
+ config->writeEntry("Brighten", m_brightenInput->value());
+ config->sync();
+}
+
+void ImageEffect_LensDistortion::resetValues()
+{
+ m_mainInput->blockSignals(true);
+ m_edgeInput->blockSignals(true);
+ m_rescaleInput->blockSignals(true);
+ m_brightenInput->blockSignals(true);
+
+ m_mainInput->setValue(0.0);
+ m_edgeInput->setValue(0.0);
+ m_rescaleInput->setValue(0.0);
+ m_brightenInput->setValue(0.0);
+
+ m_mainInput->blockSignals(false);
+ m_edgeInput->blockSignals(false);
+ m_rescaleInput->blockSignals(false);
+ m_brightenInput->blockSignals(false);
+}
+
+void ImageEffect_LensDistortion::prepareEffect()
+{
+ m_mainInput->setEnabled(false);
+ m_edgeInput->setEnabled(false);
+ m_rescaleInput->setEnabled(false);
+ m_brightenInput->setEnabled(false);
+
+ double m = m_mainInput->value();
+ double e = m_edgeInput->value();
+ double r = m_rescaleInput->value();
+ double b = m_brightenInput->value();
+
+ LensDistortion transformPreview(&m_previewRasterImage, 0L, m, e, r, b, 0, 0);
+ m_maskPreviewLabel->setPixmap(TQPixmap::TQPixmap(transformPreview.getTargetImage().convertToPixmap()));
+
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new LensDistortion(iface->getOriginalImg(), this, m, e, r, b, 0, 0));
+}
+
+void ImageEffect_LensDistortion::prepareFinal()
+{
+ m_mainInput->setEnabled(false);
+ m_edgeInput->setEnabled(false);
+ m_rescaleInput->setEnabled(false);
+ m_brightenInput->setEnabled(false);
+
+ double m = m_mainInput->value();
+ double e = m_edgeInput->value();
+ double r = m_rescaleInput->value();
+ double b = m_brightenInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new LensDistortion(iface.getOriginalImg(), this, m, e, r, b, 0, 0));
+}
+
+void ImageEffect_LensDistortion::putPreviewData(void)
+{
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage()
+ .smoothScale(iface->previewWidth(), iface->previewHeight());
+ iface->putPreviewImage(imDest.bits());
+
+ m_imagePreviewWidget->updatePreview();
+}
+
+void ImageEffect_LensDistortion::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Lens Distortion"),
+ m_threadedFilter->getTargetImage().bits());
+}
+
+void ImageEffect_LensDistortion::renderingFinished()
+{
+ m_mainInput->setEnabled(true);
+ m_edgeInput->setEnabled(true);
+ m_rescaleInput->setEnabled(true);
+ m_brightenInput->setEnabled(true);
+}
+
+} // NameSpace DigikamLensDistortionImagesPlugin
+
diff --git a/src/imageplugins/lensdistortion/imageeffect_lensdistortion.h b/src/imageplugins/lensdistortion/imageeffect_lensdistortion.h
new file mode 100644
index 00000000..2688a5df
--- /dev/null
+++ b/src/imageplugins/lensdistortion/imageeffect_lensdistortion.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-27
+ * Description : a plugin to reduce lens distorsions to an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_LENSDISTORTION_H
+#define IMAGEEFFECT_LENSDISTORTION_H
+
+// TQt includes.
+
+#include <tqimage.h>
+
+// Digikam includes.
+
+#include "dimg.h"
+#include "imageguidedlg.h"
+
+class TQLabel;
+
+class KDoubleNumInput;
+
+namespace DigikamLensDistortionImagesPlugin
+{
+
+class ImageEffect_LensDistortion : public Digikam::ImageGuideDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_LensDistortion(TQWidget *parent);
+ ~ImageEffect_LensDistortion();
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQLabel *m_maskPreviewLabel;
+
+ KDoubleNumInput *m_mainInput;
+ KDoubleNumInput *m_edgeInput;
+ KDoubleNumInput *m_rescaleInput;
+ KDoubleNumInput *m_brightenInput;
+
+ Digikam::DImg m_previewRasterImage;
+};
+
+} // NameSpace DigikamLensDistortionImagesPlugin
+
+#endif /* IMAGEEFFECT_LENSDISTORTION_H */
diff --git a/src/imageplugins/lensdistortion/imageplugin_lensdistortion.cpp b/src/imageplugins/lensdistortion/imageplugin_lensdistortion.cpp
new file mode 100644
index 00000000..73403fa7
--- /dev/null
+++ b/src/imageplugins/lensdistortion/imageplugin_lensdistortion.cpp
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-27
+ * Description : a plugin to reduce lens distorsions to an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "lensdistortiontool.h"
+#include "imageplugin_lensdistortion.h"
+#include "imageplugin_lensdistortion.moc"
+
+using namespace DigikamLensDistortionImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_lensdistortion,
+ KGenericFactory<ImagePlugin_LensDistortion>("digikamimageplugin_lensdistortion"));
+
+ImagePlugin_LensDistortion::ImagePlugin_LensDistortion(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_LensDistortion")
+{
+ m_lensdistortionAction = new TDEAction(i18n("Lens Distortion..."), "lensdistortion", 0,
+ this, TQ_SLOT(slotLensDistortion()),
+ actionCollection(), "imageplugin_lensdistortion");
+
+ setXMLFile("digikamimageplugin_lensdistortion_ui.rc");
+
+ DDebug() << "ImagePlugin_LensDistortion plugin loaded" << endl;
+}
+
+ImagePlugin_LensDistortion::~ImagePlugin_LensDistortion()
+{
+}
+
+void ImagePlugin_LensDistortion::setEnabledActions(bool enable)
+{
+ m_lensdistortionAction->setEnabled(enable);
+}
+
+void ImagePlugin_LensDistortion::slotLensDistortion()
+{
+ LensDistortionTool *tool = new LensDistortionTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/lensdistortion/imageplugin_lensdistortion.h b/src/imageplugins/lensdistortion/imageplugin_lensdistortion.h
new file mode 100644
index 00000000..ceb24756
--- /dev/null
+++ b/src/imageplugins/lensdistortion/imageplugin_lensdistortion.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-27
+ * Description : a plugin to reduce lens distorsions to an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_LENSDISTORTION_H
+#define IMAGEPLUGIN_LENSDISTORTION_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_LensDistortion : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_LensDistortion(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_LensDistortion();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotLensDistortion();
+
+private:
+
+ TDEAction *m_lensdistortionAction;
+};
+
+#endif /* IMAGEPLUGIN_LENSDISTORTION_H */
diff --git a/src/imageplugins/lensdistortion/lensdistortion.cpp b/src/imageplugins/lensdistortion/lensdistortion.cpp
new file mode 100644
index 00000000..7b18cc93
--- /dev/null
+++ b/src/imageplugins/lensdistortion/lensdistortion.cpp
@@ -0,0 +1,135 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : lens distortion algorithm.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2001-2003 by David Hodson <hodsond@acm.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Local includes.
+
+#include "dimg.h"
+#include "ddebug.h"
+#include "pixelaccess.h"
+#include "lensdistortion.h"
+
+namespace DigikamLensDistortionImagesPlugin
+{
+
+LensDistortion::LensDistortion(Digikam::DImg *orgImage, TQObject *parent, double main,
+ double edge, double rescale, double brighten,
+ int center_x, int center_y)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "LensDistortion")
+{
+ m_main = main;
+ m_edge = edge;
+ m_rescale = rescale;
+ m_brighten = brighten;
+ m_centre_x = center_x;
+ m_centre_y = center_y;
+
+ initFilter();
+}
+
+void LensDistortion::filterImage(void)
+{
+ int Width = m_orgImage.width();
+ int Height = m_orgImage.height();
+ int bytesDepth = m_orgImage.bytesDepth();
+
+ uchar *data = m_destImage.bits();
+
+ // initial copy
+
+ m_destImage.bitBltImage(&m_orgImage, 0, 0);
+
+ // initialize coefficients
+
+ double normallise_radius_sq = 4.0 / (Width * Width + Height * Height);
+ double center_x = Width * (100.0 + m_centre_x) / 200.0;
+ double center_y = Height * (100.0 + m_centre_y) / 200.0;
+ double mult_sq = m_main / 200.0;
+ double mult_qd = m_edge / 200.0;
+ double rescale = pow(2.0, - m_rescale / 100.0);
+ double brighten = - m_brighten / 10.0;
+
+ PixelAccess *pa = new PixelAccess(&m_orgImage);
+
+ /*
+ * start at image (i, j), increment by (step, step)
+ * output goes to dst, which is w x h x d in size
+ * NB: d <= image.bpp
+ */
+
+ // We are working on the full image.
+ int dstWidth = Width;
+ int dstHeight = Height;
+ uchar* dst = (uchar*)data;
+ int step = 1, progress;
+
+ int iLimit, jLimit;
+ double srcX, srcY, mag;
+
+ iLimit = dstWidth * step;
+ jLimit = dstHeight * step;
+
+ for (int dstJ = 0 ; !m_cancel && (dstJ < jLimit) ; dstJ += step)
+ {
+ for (int dstI = 0 ; !m_cancel && (dstI < iLimit) ; dstI += step)
+ {
+ // Get source Coordinates.
+ double radius_sq;
+ double off_x;
+ double off_y;
+ double radius_mult;
+
+ off_x = dstI - center_x;
+ off_y = dstJ - center_y;
+ radius_sq = (off_x * off_x) + (off_y * off_y);
+
+ radius_sq *= normallise_radius_sq;
+
+ radius_mult = radius_sq * mult_sq + radius_sq * radius_sq * mult_qd;
+ mag = radius_mult;
+ radius_mult = rescale * (1.0 + radius_mult);
+
+ srcX = center_x + radius_mult * off_x;
+ srcY = center_y + radius_mult * off_y;
+
+ brighten = 1.0 + mag * brighten;
+ pa->pixelAccessGetCubic(srcX, srcY, brighten, dst);
+ dst += bytesDepth;
+ }
+
+ // Update progress bar in dialog.
+
+ progress = (int) (((double)dstJ * 100.0) / jLimit);
+ if (m_parent && progress%5 == 0)
+ postProgress(progress);
+ }
+
+ delete pa;
+}
+
+} // NameSpace DigikamLensDistortionImagesPlugin
diff --git a/src/imageplugins/lensdistortion/lensdistortion.h b/src/imageplugins/lensdistortion/lensdistortion.h
new file mode 100644
index 00000000..cbc46105
--- /dev/null
+++ b/src/imageplugins/lensdistortion/lensdistortion.h
@@ -0,0 +1,63 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : lens distortion algorithm.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2001-2003 by David Hodson <hodsond@acm.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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef LENS_DISTORTION_H
+#define LENS_DISTORTION_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamLensDistortionImagesPlugin
+{
+
+class LensDistortion : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ LensDistortion(Digikam::DImg *orgImage, TQObject *parent=0, double main=0.0,
+ double edge=0.0, double rescale=0.0, double brighten=0.0,
+ int center_x=0, int center_y=0);
+
+ ~LensDistortion(){};
+
+private:
+
+ virtual void filterImage(void);
+
+private:
+
+ int m_centre_x;
+ int m_centre_y;
+
+ double m_main;
+ double m_edge;
+ double m_rescale;
+ double m_brighten;
+};
+
+} // NameSpace DigikamLensDistortionImagesPlugin
+
+#endif /* LENS_DISTORTION_H */
diff --git a/src/imageplugins/lensdistortion/lensdistortiontool.cpp b/src/imageplugins/lensdistortion/lensdistortiontool.cpp
new file mode 100644
index 00000000..8d33e1df
--- /dev/null
+++ b/src/imageplugins/lensdistortion/lensdistortiontool.cpp
@@ -0,0 +1,326 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-27
+ * Description : a plugin to reduce lens distorsions to an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstring>
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqbrush.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqpixmap.h>
+#include <tqwhatsthis.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "editortoolsettings.h"
+#include "lensdistortion.h"
+#include "lensdistortiontool.h"
+#include "lensdistortiontool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamLensDistortionImagesPlugin
+{
+
+LensDistortionTool::LensDistortionTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("lensdistortion");
+ setToolName(i18n("Lens Distortion"));
+ setToolIcon(SmallIcon("lensdistortion"));
+
+ m_previewWidget = new ImageWidget("lensdistortion Tool", 0, TQString(),
+ false, ImageGuideWidget::HVGuideMode);
+
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel,
+ EditorToolSettings::ColorGuide);
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 9, 1);
+
+ m_maskPreviewLabel = new TQLabel( m_gboxSettings->plainPage() );
+ m_maskPreviewLabel->setAlignment ( TQt::AlignHCenter | TQt::AlignVCenter );
+ TQWhatsThis::add( m_maskPreviewLabel, i18n("<p>You can see here a thumbnail preview of the distortion correction "
+ "applied to a cross pattern.") );
+
+ // -------------------------------------------------------------
+
+ TQLabel *label1 = new TQLabel(i18n("Main:"), m_gboxSettings->plainPage());
+
+ m_mainInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_mainInput->setPrecision(1);
+ m_mainInput->setRange(-100.0, 100.0, 0.1);
+ m_mainInput->setDefaultValue(0.0);
+ TQWhatsThis::add(m_mainInput, i18n("<p>This value controls the amount of distortion. Negative values correct lens barrel "
+ "distortion, while positive values correct lens pincushion distortion."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Edge:"), m_gboxSettings->plainPage());
+
+ m_edgeInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_edgeInput->setPrecision(1);
+ m_edgeInput->setRange(-100.0, 100.0, 0.1);
+ m_edgeInput->setDefaultValue(0.0);
+ TQWhatsThis::add(m_edgeInput, i18n("<p>This value controls in the same manner as the Main control, but has more effect "
+ "at the edges of the image than at the center."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Zoom:"), m_gboxSettings->plainPage());
+
+ m_rescaleInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_rescaleInput->setPrecision(1);
+ m_rescaleInput->setRange(-100.0, 100.0, 0.1);
+ m_rescaleInput->setDefaultValue(0.0);
+ TQWhatsThis::add(m_rescaleInput, i18n("<p>This value rescales the overall image size."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label4 = new TQLabel(i18n("Brighten:"), m_gboxSettings->plainPage());
+
+ m_brightenInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_brightenInput->setPrecision(1);
+ m_brightenInput->setRange(-100.0, 100.0, 0.1);
+ m_brightenInput->setDefaultValue(0.0);
+ TQWhatsThis::add(m_brightenInput, i18n("<p>This value adjusts the brightness in image corners."));
+
+ grid->addMultiCellWidget(m_maskPreviewLabel, 0, 0, 0, 1);
+ grid->addMultiCellWidget(label1, 1, 1, 0, 1);
+ grid->addMultiCellWidget(m_mainInput, 2, 2, 0, 1);
+ grid->addMultiCellWidget(label2, 3, 3, 0, 1);
+ grid->addMultiCellWidget(m_edgeInput, 4, 4, 0, 1);
+ grid->addMultiCellWidget(label3, 5, 5, 0, 1);
+ grid->addMultiCellWidget(m_rescaleInput, 6, 6, 0, 1);
+ grid->addMultiCellWidget(label4, 7, 7, 0, 1);
+ grid->addMultiCellWidget(m_brightenInput, 8, 8, 0, 1);
+ grid->setRowStretch(9, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_mainInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_edgeInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_rescaleInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_brightenInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gboxSettings, TQ_SIGNAL(signalColorGuideChanged()),
+ this, TQ_SLOT(slotColorGuideChanged()));
+
+ // -------------------------------------------------------------
+
+ /* Calc transform preview.
+ We would like a checkered area to demonstrate the effect.
+ We do not have any drawing support in DImg, so we let TQt draw.
+ First we create a white TQImage. We convert this to a TQPixmap,
+ on which we can draw. Then we convert back to TQImage,
+ convert the TQImage to a DImg which we only need to create once, here.
+ Later, we apply the effect on a copy and convert the DImg to TQPixmap.
+ Longing for TQt4 where we can paint directly on the TQImage...
+ */
+
+ TQImage preview(120, 120, 32);
+ memset(preview.bits(), 255, preview.numBytes());
+ TQPixmap pix (preview);
+ TQPainter pt(&pix);
+ pt.setPen( TQPen(TQt::black, 1) );
+ pt.fillRect( 0, 0, pix.width(), pix.height(), TQBrush(TQt::black, TQt::CrossPattern) );
+ pt.drawRect( 0, 0, pix.width(), pix.height() );
+ pt.end();
+ TQImage preview2(pix.convertToImage());
+ m_previewRasterImage = DImg(preview2.width(), preview2.height(), false, false, preview2.bits());
+}
+
+LensDistortionTool::~LensDistortionTool()
+{
+}
+
+void LensDistortionTool::slotColorGuideChanged()
+{
+ m_previewWidget->slotChangeGuideColor(m_gboxSettings->guideColor());
+ m_previewWidget->slotChangeGuideSize(m_gboxSettings->guideSize());
+}
+
+void LensDistortionTool::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("lensdistortion Tool");
+
+ m_mainInput->blockSignals(true);
+ m_edgeInput->blockSignals(true);
+ m_rescaleInput->blockSignals(true);
+ m_brightenInput->blockSignals(true);
+
+ m_mainInput->setValue(config->readDoubleNumEntry("2nd Order Distortion", m_mainInput->defaultValue()));
+ m_edgeInput->setValue(config->readDoubleNumEntry("4th Order Distortion",m_edgeInput->defaultValue()));
+ m_rescaleInput->setValue(config->readDoubleNumEntry("Zoom Factor", m_rescaleInput->defaultValue()));
+ m_brightenInput->setValue(config->readDoubleNumEntry("Brighten", m_brightenInput->defaultValue()));
+ m_gboxSettings->setGuideColor(config->readColorEntry("Guide Color", &TQt::red));
+ m_gboxSettings->setGuideSize(config->readNumEntry("Guide Width", 1));
+
+ m_mainInput->blockSignals(false);
+ m_edgeInput->blockSignals(false);
+ m_rescaleInput->blockSignals(false);
+ m_brightenInput->blockSignals(false);
+
+ slotColorGuideChanged();
+ slotEffect();
+}
+
+void LensDistortionTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("lensdistortion Tool");
+ config->writeEntry("2nd Order Distortion", m_mainInput->value());
+ config->writeEntry("4th Order Distortion", m_edgeInput->value());
+ config->writeEntry("Zoom Factor", m_rescaleInput->value());
+ config->writeEntry("Brighten", m_brightenInput->value());
+ config->writeEntry("Guide Color", m_gboxSettings->guideColor());
+ config->writeEntry("Guide Width", m_gboxSettings->guideSize());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void LensDistortionTool::slotResetSettings()
+{
+ m_mainInput->blockSignals(true);
+ m_edgeInput->blockSignals(true);
+ m_rescaleInput->blockSignals(true);
+ m_brightenInput->blockSignals(true);
+
+ m_mainInput->slotReset();
+ m_edgeInput->slotReset();
+ m_rescaleInput->slotReset();
+ m_brightenInput->slotReset();
+
+ m_mainInput->blockSignals(false);
+ m_edgeInput->blockSignals(false);
+ m_rescaleInput->blockSignals(false);
+ m_brightenInput->blockSignals(false);
+}
+
+void LensDistortionTool::prepareEffect()
+{
+ m_mainInput->setEnabled(false);
+ m_edgeInput->setEnabled(false);
+ m_rescaleInput->setEnabled(false);
+ m_brightenInput->setEnabled(false);
+
+ double m = m_mainInput->value();
+ double e = m_edgeInput->value();
+ double r = m_rescaleInput->value();
+ double b = m_brightenInput->value();
+
+ LensDistortion transformPreview(&m_previewRasterImage, 0L, m, e, r, b, 0, 0);
+ m_maskPreviewLabel->setPixmap(TQPixmap(transformPreview.getTargetImage().convertToPixmap()));
+
+ ImageIface* iface = m_previewWidget->imageIface();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new LensDistortion(iface->getOriginalImg(), this, m, e, r, b, 0, 0)));
+}
+
+void LensDistortionTool::prepareFinal()
+{
+ m_mainInput->setEnabled(false);
+ m_edgeInput->setEnabled(false);
+ m_rescaleInput->setEnabled(false);
+ m_brightenInput->setEnabled(false);
+
+ double m = m_mainInput->value();
+ double e = m_edgeInput->value();
+ double r = m_rescaleInput->value();
+ double b = m_brightenInput->value();
+
+ ImageIface iface(0, 0);
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new LensDistortion(iface.getOriginalImg(), this, m, e, r, b, 0, 0)));
+}
+
+void LensDistortionTool::putPreviewData()
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+
+ DImg imDest = filter()->getTargetImage().smoothScale(iface->previewWidth(), iface->previewHeight());
+ iface->putPreviewImage(imDest.bits());
+
+ m_previewWidget->updatePreview();
+}
+
+void LensDistortionTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Lens Distortion"), filter()->getTargetImage().bits());
+}
+
+void LensDistortionTool::renderingFinished()
+{
+ m_mainInput->setEnabled(true);
+ m_edgeInput->setEnabled(true);
+ m_rescaleInput->setEnabled(true);
+ m_brightenInput->setEnabled(true);
+}
+
+} // NameSpace DigikamLensDistortionImagesPlugin
diff --git a/src/imageplugins/lensdistortion/lensdistortiontool.h b/src/imageplugins/lensdistortion/lensdistortiontool.h
new file mode 100644
index 00000000..f3c7b67f
--- /dev/null
+++ b/src/imageplugins/lensdistortion/lensdistortiontool.h
@@ -0,0 +1,92 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-27
+ * Description : a plugin to reduce lens distorsions to an image.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef LENSDISTORTIONTOOL_H
+#define LENSDISTORTIONTOOL_H
+
+// Digikam includes.
+
+#include "dimg.h"
+#include "editortool.h"
+
+class TQLabel;
+
+namespace KDcrawIface
+{
+class RDoubleNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImageWidget;
+}
+
+namespace DigikamLensDistortionImagesPlugin
+{
+
+class LensDistortionTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ LensDistortionTool(TQObject *parent);
+ ~LensDistortionTool();
+
+private slots:
+
+ void slotResetSettings();
+ void slotColorGuideChanged();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQLabel *m_maskPreviewLabel;
+
+ KDcrawIface::RDoubleNumInput *m_mainInput;
+ KDcrawIface::RDoubleNumInput *m_edgeInput;
+ KDcrawIface::RDoubleNumInput *m_rescaleInput;
+ KDcrawIface::RDoubleNumInput *m_brightenInput;
+
+ Digikam::DImg m_previewRasterImage;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamLensDistortionImagesPlugin
+
+#endif /* LENSDISTORTIONTOOL_H */
diff --git a/src/imageplugins/lensdistortion/pixelaccess.cpp b/src/imageplugins/lensdistortion/pixelaccess.cpp
new file mode 100644
index 00000000..a6041f94
--- /dev/null
+++ b/src/imageplugins/lensdistortion/pixelaccess.cpp
@@ -0,0 +1,314 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-27
+ * Description : acess pixels method for lens distortion algorithm.
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstring>
+#include <cmath>
+#include <cstdlib>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "pixelaccess.h"
+
+namespace DigikamLensDistortionImagesPlugin
+{
+
+PixelAccess::PixelAccess(Digikam::DImg *srcImage)
+{
+ m_image = srcImage;
+
+ m_width = PixelAccessWidth;
+ m_height = PixelAccessHeight;
+
+ m_depth = m_image->bytesDepth();
+ m_imageWidth = m_image->width();
+ m_imageHeight = m_image->height();
+ m_sixteenBit = m_image->sixteenBit();
+
+ for ( int i = 0 ; i < PixelAccessRegions ; i++ )
+ {
+ m_buffer[i] = new Digikam::DImg(m_image->copy(0, 0, m_width, m_height));
+
+ m_tileMinX[i] = 1;
+ m_tileMaxX[i] = m_width - 2;
+ m_tileMinY[i] = 1;
+ m_tileMaxY[i] = m_height - 2;
+ }
+}
+
+PixelAccess::~PixelAccess()
+{
+ for( int i = 0 ; i < PixelAccessRegions ; i++ )
+ delete m_buffer[i];
+}
+
+uchar* PixelAccess::pixelAccessAddress(int i, int j)
+{
+ return m_buffer[0]->bits() + m_depth * (m_width * (j + 1 - m_tileMinY[0]) + (i + 1 - m_tileMinX[0]));
+}
+
+// Swap region[n] with region[0].
+void PixelAccess::pixelAccessSelectRegion(int n)
+{
+ Digikam::DImg *temp;
+ int a, b, c, d;
+ int i;
+
+ temp = m_buffer[n];
+ a = m_tileMinX[n];
+ b = m_tileMaxX[n];
+ c = m_tileMinY[n];
+ d = m_tileMaxY[n];
+
+ for( i = n ; i > 0 ; i--)
+ {
+ m_buffer[i] = m_buffer[i-1];
+ m_tileMinX[i] = m_tileMinX[i-1];
+ m_tileMaxX[i] = m_tileMaxX[i-1];
+ m_tileMinY[i] = m_tileMinY[i-1];
+ m_tileMaxY[i] = m_tileMaxY[i-1];
+ }
+
+ m_buffer[0] = temp;
+ m_tileMinX[0] = a;
+ m_tileMaxX[0] = b;
+ m_tileMinY[0] = c;
+ m_tileMaxY[0] = d;
+}
+
+// Buffer[0] is cleared, should start at [i, j], fill rows that overlap image.
+void PixelAccess::pixelAccessDoEdge(int i, int j)
+{
+ int lineStart, lineEnd;
+ int rowStart, rowEnd;
+ int lineWidth;
+ uchar* line;
+
+ lineStart = i;
+ if (lineStart < 0) lineStart = 0;
+ lineEnd = i + m_width;
+ if (lineEnd > m_imageWidth) lineEnd = m_imageWidth;
+ lineWidth = lineEnd - lineStart;
+
+ if( lineStart >= lineEnd )
+ return;
+
+ rowStart = j;
+ if (rowStart < 0) rowStart = 0;
+ rowEnd = j + m_height;
+ if (rowEnd > m_imageHeight) rowEnd = m_imageHeight;
+
+ for( int y = rowStart ; y < rowEnd ; y++ )
+ {
+ line = pixelAccessAddress(lineStart, y);
+ memcpy(line, m_image->scanLine(y) + lineStart * m_depth, lineWidth * m_depth);
+ }
+}
+
+// Moves buffer[0] so that [x, y] is inside it.
+void PixelAccess::pixelAccessReposition(int xInt, int yInt)
+{
+ int newStartX = xInt - PixelAccessXOffset;
+ int newStartY = yInt - PixelAccessYOffset;
+
+ m_tileMinX[0] = newStartX + 1;
+ m_tileMaxX[0] = newStartX + m_width - 2;
+ m_tileMinY[0] = newStartY + 1;
+ m_tileMaxY[0] = newStartY + m_height - 2;
+
+
+ if ( (newStartX < 0) || ((newStartX + m_width) >= m_imageWidth) ||
+ (newStartY < 0) || ((newStartY + m_height) >= m_imageHeight) )
+ {
+ // some data is off edge of image
+
+ m_buffer[0]->fill(Digikam::DColor(0,0,0,0, m_sixteenBit));
+
+ // This could probably be done by bitBltImage but I did not figure out how,
+ // so leave the working code here. And no, it is not this:
+ //m_buffer[0]->bitBltImage(m_image, newStartX, newStartY, m_width, m_height, 0, 0);
+
+ if ( ((newStartX + m_width) < 0) || (newStartX >= m_imageWidth) ||
+ ((newStartY + m_height) < 0) || (newStartY >= m_imageHeight) )
+ {
+ // totally outside, just leave it.
+ }
+ else
+ {
+ pixelAccessDoEdge(newStartX, newStartY);
+ }
+ }
+ else
+ {
+ m_buffer[0]->bitBltImage(m_image, newStartX, newStartY, m_width, m_height, 0, 0);
+ }
+}
+
+void PixelAccess::pixelAccessGetCubic(double srcX, double srcY, double brighten, uchar* dst)
+{
+ int xInt, yInt;
+ double dx, dy;
+ uchar *corner;
+
+ xInt = (int)floor(srcX);
+ dx = srcX - xInt;
+ yInt = (int)floor(srcY);
+ dy = srcY - yInt;
+
+ // We need 4x4 pixels, xInt-1 to xInt+2 horz, yInt-1 to yInt+2 vert
+ // they're probably in the last place we looked...
+
+ if ((xInt >= m_tileMinX[0]) && (xInt < m_tileMaxX[0]) &&
+ (yInt >= m_tileMinY[0]) && (yInt < m_tileMaxY[0]) )
+ {
+ corner = pixelAccessAddress(xInt - 1, yInt - 1);
+ cubicInterpolate(corner, m_depth * m_width, dst, m_sixteenBit, dx, dy, brighten);
+ return;
+ }
+
+ // Or maybe it was a while back...
+
+ for ( int i = 1 ; i < PixelAccessRegions ; i++)
+ {
+ if ((xInt >= m_tileMinX[i]) && (xInt < m_tileMaxX[i]) &&
+ (yInt >= m_tileMinY[i]) && (yInt < m_tileMaxY[i]) )
+ {
+ // Check here first next time
+
+ pixelAccessSelectRegion(i);
+ corner = pixelAccessAddress(xInt - 1, yInt - 1);
+ cubicInterpolate(corner, m_depth * m_width, dst, m_sixteenBit, dx, dy, brighten);
+ return;
+ }
+ }
+
+ // Nope, recycle an old region.
+
+ pixelAccessSelectRegion(PixelAccessRegions - 1);
+ pixelAccessReposition(xInt, yInt);
+
+ corner = pixelAccessAddress(xInt - 1, yInt - 1);
+ cubicInterpolate(corner, m_depth * m_width, dst, m_sixteenBit, dx, dy, brighten);
+}
+
+/*
+ * Catmull-Rom cubic interpolation
+ *
+ * equally spaced points p0, p1, p2, p3
+ * interpolate 0 <= u < 1 between p1 and p2
+ *
+ * (1 u u^2 u^3) ( 0.0 1.0 0.0 0.0 ) (p0)
+ * ( -0.5 0.0 0.5 0.0 ) (p1)
+ * ( 1.0 -2.5 2.0 -0.5 ) (p2)
+ * ( -0.5 1.5 -1.5 0.5 ) (p3)
+ *
+ */
+void PixelAccess::cubicInterpolate(uchar* src, int rowStride, uchar* dst,
+ bool sixteenBit, double dx, double dy, double brighten)
+{
+ float um1, u, up1, up2;
+ float vm1, v, vp1, vp2;
+ int c;
+ const int numberOfComponents = 4;
+ float verts[4 * numberOfComponents];
+
+ um1 = ((-0.5 * dx + 1.0) * dx - 0.5) * dx;
+ u = (1.5 * dx - 2.5) * dx * dx + 1.0;
+ up1 = ((-1.5 * dx + 2.0) * dx + 0.5) * dx;
+ up2 = (0.5 * dx - 0.5) * dx * dx;
+
+ vm1 = ((-0.5 * dy + 1.0) * dy - 0.5) * dy;
+ v = (1.5 * dy - 2.5) * dy * dy + 1.0;
+ vp1 = ((-1.5 * dy + 2.0) * dy + 0.5) * dy;
+ vp2 = (0.5 * dy - 0.5) * dy * dy;
+
+ if (sixteenBit)
+ {
+ unsigned short *src16 = (unsigned short *)src;
+ unsigned short *dst16 = (unsigned short *)dst;
+
+ // for each component, read the values of 4 pixels into array
+
+ for (c = 0 ; c < 4 * numberOfComponents ; c++)
+ {
+ verts[c] = vm1 * src16[c] + v * src16[c+rowStride] + vp1 * src16[c+rowStride*2] + vp2 * src16[c+rowStride*3];
+ }
+
+ // for each component, compute resulting value from array
+
+ for (c = 0 ; c < numberOfComponents ; c++)
+ {
+ float result;
+ result = um1 * verts[c] + u * verts[c+numberOfComponents]
+ + up1 * verts[c+numberOfComponents*2] + up2 * verts[c+numberOfComponents*3];
+ result *= brighten;
+
+ if (result < 0.0)
+ {
+ dst16[c] = 0;
+ }
+ else if (result > 65535.0)
+ {
+ dst16[c] = 65535;
+ }
+ else
+ {
+ dst16[c] = (uint)result;
+ }
+ }
+ }
+ else
+ {
+ for (c = 0 ; c < 4 * numberOfComponents ; c++)
+ {
+ verts[c] = vm1 * src[c] + v * src[c+rowStride] + vp1 * src[c+rowStride*2] + vp2 * src[c+rowStride*3];
+ }
+
+ for (c = 0 ; c < numberOfComponents ; c++)
+ {
+ float result;
+ result = um1 * verts[c] + u * verts[c+numberOfComponents]
+ + up1 * verts[c+numberOfComponents*2] + up2 * verts[c+numberOfComponents*3];
+ result *= brighten;
+
+ if (result < 0.0)
+ {
+ dst[c] = 0;
+ }
+ else if (result > 255.0)
+ {
+ dst[c] = 255;
+ }
+ else
+ {
+ dst[c] = (uint)result;
+ }
+ }
+ }
+}
+
+} // NameSpace DigikamLensDistortionImagesPlugin
+
diff --git a/src/imageplugins/lensdistortion/pixelaccess.h b/src/imageplugins/lensdistortion/pixelaccess.h
new file mode 100644
index 00000000..734d0779
--- /dev/null
+++ b/src/imageplugins/lensdistortion/pixelaccess.h
@@ -0,0 +1,93 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-27
+ * Description : acess pixels method for lens distortion algorithm.
+ *
+ * Copyright (C) 2004-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef PIXEL_ACCESS_H
+#define PIXEL_ACCESS_H
+
+#define PixelAccessRegions 20
+#define PixelAccessWidth 40
+#define PixelAccessHeight 20
+#define PixelAccessXOffset 3
+#define PixelAccessYOffset 3
+
+// Digikam includes.
+
+#include "dimg.h"
+
+namespace DigikamLensDistortionImagesPlugin
+{
+
+ /* PixelAcess class: solving the eternal problem: random, cubic-interpolated,
+ * sub-pixel coordinate access to an image.
+ * Assuming that accesses are at least slightly coherent,
+ * PixelAccess keeps PixelAccessRegions buffers, each containing a
+ * PixelAccessWidth x PixelAccessHeight region of pixels.
+ * Buffer[0] is always checked first, so move the last accessed
+ * region into that position.
+ * When a request arrives which is outside all the regions,
+ * get a new region.
+ * The new region is placed so that the requested pixel is positioned
+ * at [PixelAccessXOffset, PixelAccessYOffset] in the region.
+ */
+
+class PixelAccess
+{
+public:
+
+ PixelAccess(Digikam::DImg *srcImage);
+ ~PixelAccess();
+
+ void pixelAccessGetCubic(double srcX, double srcY, double brighten, uchar* dst);
+
+private:
+
+ Digikam::DImg *m_image;
+
+ //uchar* m_buffer[PixelAccessRegions];
+ Digikam::DImg *m_buffer[PixelAccessRegions];
+
+ int m_width;
+ int m_height;
+ int m_depth;
+ int m_imageWidth;
+ int m_imageHeight;
+ bool m_sixteenBit;
+ int m_tileMinX[PixelAccessRegions];
+ int m_tileMaxX[PixelAccessRegions];
+ int m_tileMinY[PixelAccessRegions];
+ int m_tileMaxY[PixelAccessRegions];
+
+protected:
+
+ inline uchar* pixelAccessAddress(int i, int j);
+ void pixelAccessSelectRegion(int n);
+ void pixelAccessDoEdge(int i, int j);
+ void pixelAccessReposition(int xInt, int yInt);
+ void cubicInterpolate(uchar* src, int rowStride, uchar* dst,
+ bool sixteenBit, double dx, double dy, double brighten);
+};
+
+} // NameSpace DigikamLensDistortionImagesPlugin
+
+#endif /* PIXEL_ACCESS_H */
diff --git a/src/imageplugins/noisereduction/Makefile.am b/src/imageplugins/noisereduction/Makefile.am
new file mode 100644
index 00000000..c1b6ac08
--- /dev/null
+++ b/src/imageplugins/noisereduction/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_noisereduction_la_SOURCES = imageplugin_noisereduction.cpp \
+ noisereductiontool.cpp noisereduction.cpp
+
+digikamimageplugin_noisereduction_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_noisereduction_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_noisereduction.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_noisereduction.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_noisereduction_ui.rc
+
diff --git a/src/imageplugins/noisereduction/digikamimageplugin_noisereduction.desktop b/src/imageplugins/noisereduction/digikamimageplugin_noisereduction.desktop
new file mode 100644
index 00000000..9cf408e3
--- /dev/null
+++ b/src/imageplugins/noisereduction/digikamimageplugin_noisereduction.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Name=ImagePlugin_NoiseReduction
+Name[da]=Plugin for støjreducering
+Name[el]=ΠρόσθετοΕικόνας_ΜείωσηΘορύβου
+Name[fi]=Kohinanpoisto
+Name[hr]=Uklanjanje šuma
+Name[it]=PluginImmagini_RiduzioneDisturbi
+Name[nl]=Afbeeldingsplugin_Ruisreductie
+Name[pt]=ImagePlugin_Restoration
+Name[sr]=Смањење шума
+Name[sr@Latn]=Smanjenje šuma
+Name[sv]=Insticksprogram för brusreducering
+Name[tr]=ResimEklentisi_Onarım
+Name[vi]=ImagePlugin_Restoration
+Name[xx]=xxImagePlugin_NoiseReductionxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Noise Reduction plugin for digiKam
+Comment[bg]=Приставка на digiKam за намаляване шума в снимки
+Comment[ca]=Connector pel digiKam de reducció de soroll
+Comment[da]=Plugin til støjreduktion for DigiKam
+Comment[de]=digiKam-Modul zum Entfernen von Rauschen
+Comment[el]=Πρόσθετο μείωσης θορύβου για το digiKam
+Comment[es]=Plugin para digiKam de reducción de ruido
+Comment[et]=DigiKami müra vähendamise plugin
+Comment[fa]=وصلۀ کاهش نوفه برای digiKam
+Comment[fi]=Vähentää kuvan kohinaa
+Comment[fr]=Module externe pour réduire le bruit numérique dans digiKam
+Comment[gl]=Un plugin de digiKam para a reduzón de ruído
+Comment[hr]=digiKam dodatak za uklanjanje šuma
+Comment[is]=Íforrit fyrir digiKam sem minnkar truflanir (noise) í mynd
+Comment[it]=Plugin di riduzione dei disturbi per digiKam
+Comment[ja]=digiKam ノイズ低減プラグイン
+Comment[ms]=Plugin Pengurangan Bising untuk digiKam
+Comment[nds]=digiKam-Moduul för Ruusminnern
+Comment[nl]=Digikam-plugin voor ruisreductie
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਗੜਬੜ ਘਟਾਉਣ ਲਈ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam zmniejszająca szum
+Comment[pt]=Um 'plugin' do digiKam para a redução de ruído
+Comment[pt_BR]=Plugin de redução de ruidos
+Comment[ru]=Модуль уменьшения шума для digiKam
+Comment[sk]=digiKam plugin na potlačenie šumu
+Comment[sr]=digiKam-ов прикључак за смањење шума
+Comment[sr@Latn]=digiKam-ov priključak za smanjenje šuma
+Comment[sv]=Digikam insticksprogram för brusreducering
+Comment[tr]=digiKam için Parazit Azaltma eklentisi
+Comment[uk]=Втулок зменшення шуму для digiKam
+Comment[vi]=Phần bổ sung giảm nhiễu cho digiKam
+Comment[xx]=xxNoise Reduction plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_noisereduction
+author=Caulier Gilles, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/noisereduction/digikamimageplugin_noisereduction_ui.rc b/src/imageplugins/noisereduction/digikamimageplugin_noisereduction_ui.rc
new file mode 100644
index 00000000..b6a663e3
--- /dev/null
+++ b/src/imageplugins/noisereduction/digikamimageplugin_noisereduction_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_noisereduction" >
+
+ <MenuBar>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ <Action name="imageplugin_noisereduction" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_noisereduction" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/noisereduction/imageeffect_noisereduction.cpp b/src/imageplugins/noisereduction/imageeffect_noisereduction.cpp
new file mode 100644
index 00000000..707b05db
--- /dev/null
+++ b/src/imageplugins/noisereduction/imageeffect_noisereduction.cpp
@@ -0,0 +1,553 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqcheckbox.h>
+#include <tqstring.h>
+#include <tqtabwidget.h>
+#include <tqimage.h>
+#include <tqlayout.h>
+#include <tqfile.h>
+#include <tqtextstream.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <tdemessagebox.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "noisereduction.h"
+#include "imageeffect_noisereduction.h"
+#include "imageeffect_noisereduction.moc"
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+ImageEffect_NoiseReduction::ImageEffect_NoiseReduction(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Noise Reduction"),
+ "noisereduction", true, true, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Noise Reduction"),
+ digikam_version,
+ I18N_NOOP("A noise reduction image filter plugin for digiKam."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Peter Heckert", I18N_NOOP("Noise Reduction algorithm. Developer"),
+ "peter dot heckert at arcor dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQTabWidget *mainTab = new TQTabWidget(m_imagePreviewWidget);
+
+ TQWidget* firstPage = new TQWidget( mainTab );
+ TQGridLayout* gridSettings = new TQGridLayout( firstPage, 6, 1, spacingHint());
+ mainTab->addTab( firstPage, i18n("Details") );
+
+ TQLabel *label1 = new TQLabel(i18n("Radius:"), firstPage);
+
+ m_radiusInput = new KDoubleNumInput(firstPage);
+ m_radiusInput->setPrecision(1);
+ m_radiusInput->setRange(0.0, 10.0, 0.1, true);
+ TQWhatsThis::add( m_radiusInput, i18n("<p><b>Radius</b>: this control selects the "
+ "gliding window size used for the filter. Larger values do not increase "
+ "the amount of time needed to filter each pixel in the image but "
+ "can cause blurring. This window moves across the image, and the "
+ "color in it is smoothed to remove imperfections. "
+ "In any case it must be about the same size as the noise granularity "
+ "or somewhat more. If it is set higher than necessary, then it "
+ "can cause unwanted blur."));
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridSettings->addMultiCellWidget(m_radiusInput, 0, 0, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Threshold:"), firstPage);
+
+ m_thresholdInput = new KDoubleNumInput(firstPage);
+ m_thresholdInput->setPrecision(2);
+ m_thresholdInput->setRange(0.0, 1.0, 0.01, true);
+ TQWhatsThis::add( m_thresholdInput, i18n("<p><b>Threshold</b>: use the slider for coarse adjustment, "
+ "and the spin control for fine adjustment to control edge detection sensitivity. "
+ "This value should be set so that edges and details are clearly visible "
+ "and noise is smoothed out. "
+ "Adjustment must be made carefully, because the gap between \"noisy\", "
+ "\"smooth\", and \"blur\" is very small. Adjust it as carefully as you would adjust "
+ "the focus of a camera."));
+
+ gridSettings->addMultiCellWidget(label3, 1, 1, 0, 0);
+ gridSettings->addMultiCellWidget(m_thresholdInput, 1, 1, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label4 = new TQLabel(i18n("Texture:"), firstPage);
+
+ m_textureInput = new KDoubleNumInput(firstPage);
+ m_textureInput->setPrecision(2);
+ m_textureInput->setRange(-0.99, 0.99, 0.01, true);
+ TQWhatsThis::add( m_textureInput, i18n("<p><b>Texture</b>: this control sets the texture accuracy. "
+ "This value can be used, to get more or less texture accuracy. When decreased, "
+ "then noise and texture are blurred out, when increased then texture is "
+ "amplified, but also noise will increase. It has almost no effect on image edges."));
+
+ gridSettings->addMultiCellWidget(label4, 2, 2, 0, 0);
+ gridSettings->addMultiCellWidget(m_textureInput, 2, 2, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label7 = new TQLabel(i18n("Sharpness:"), firstPage); // Filter setting "Lookahead".
+
+ m_sharpnessInput = new KDoubleNumInput(firstPage);
+ m_sharpnessInput->setPrecision(2);
+ m_sharpnessInput->setRange(0.0, 1.0, 0.1, true);
+ TQWhatsThis::add( m_sharpnessInput, i18n("<p><b>Sharpness</b>: "
+ "This value improves the frequency response for the filter. "
+ "When it is too strong then not all noise can be removed, or spike noise may appear. "
+ "Set it near to maximum, if you want to remove very weak noise or JPEG-artifacts, "
+ "without losing detail."));
+
+ gridSettings->addMultiCellWidget(label7, 3, 3, 0, 0);
+ gridSettings->addMultiCellWidget(m_sharpnessInput, 3, 3, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label5 = new TQLabel(i18n("Edge Lookahead:"), firstPage); // Filter setting "Sharp".
+
+ m_lookaheadInput = new KDoubleNumInput(firstPage);
+ m_lookaheadInput->setPrecision(2);
+ m_lookaheadInput->setRange(0.01, 20.0, 0.01, true);
+ TQWhatsThis::add( m_lookaheadInput, i18n("<p><b>Edge</b>: "
+ "This value defines the pixel distance to which the filter looks ahead for edges. "
+ "When this value is increased, then spike noise is erased. "
+ "You can eventually re-adjust the <b>Edge</b> filter, when you have changed this setting. "
+ "When this value is too high, the adaptive filter can no longer accurately track "
+ "image details, and noise or blurring can occur."));
+
+ gridSettings->addMultiCellWidget(label5, 4, 4, 0, 0);
+ gridSettings->addMultiCellWidget(m_lookaheadInput, 4, 4, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label10 = new TQLabel(i18n("Erosion:"), firstPage);
+
+ m_phaseInput = new KDoubleNumInput(firstPage);
+ m_phaseInput->setPrecision(1);
+ m_phaseInput->setRange(0.5, 20.0, 0.5, true);
+ TQWhatsThis::add( m_phaseInput, i18n("<p><b>Erosion</b>: "
+ "Use this to increase edge noise erosion and spike noise erosion "
+ "(noise is removed by erosion)."));
+
+ gridSettings->addMultiCellWidget(label10, 5, 5, 0, 0);
+ gridSettings->addMultiCellWidget(m_phaseInput, 5, 5, 1, 1);
+ gridSettings->setColStretch(1, 10);
+ gridSettings->setRowStretch(6, 10);
+
+ // -------------------------------------------------------------
+
+ TQWidget* secondPage = new TQWidget( mainTab );
+ TQGridLayout* gridSettings2 = new TQGridLayout( secondPage, 4, 1, spacingHint());
+ mainTab->addTab( secondPage, i18n("Advanced") );
+
+ TQLabel *label2 = new TQLabel(i18n("Luminance:"), secondPage);
+
+ m_lumToleranceInput = new KDoubleNumInput(secondPage);
+ m_lumToleranceInput->setPrecision(1);
+ m_lumToleranceInput->setRange(0.0, 1.0, 0.1, true);
+ TQWhatsThis::add( m_lumToleranceInput, i18n("<p><b>Luminance</b>: this control sets the luminance tolerance of the image."
+ "We recommend using either the <b>Color</b> or the <b>Luminance</b> tolerance settings "
+ "to make an image correction, not both at the same time. These settings "
+ "do not influence the main smoothing process controlled by the <b>Details</b> "
+ "settings."));
+
+ gridSettings2->addMultiCellWidget(label2, 0, 0, 0, 0);
+ gridSettings2->addMultiCellWidget(m_lumToleranceInput, 0, 0, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label6 = new TQLabel(i18n("Color:"), secondPage);
+
+ m_csmoothInput = new KDoubleNumInput(secondPage);
+ m_csmoothInput->setPrecision(1);
+ m_csmoothInput->setRange(0.0, 1.0, 0.1, true);
+ TQWhatsThis::add( m_csmoothInput, i18n("<p><b>Color</b>: this control sets the color tolerance of the image. It is "
+ "recommended using either the <b>Color</b> or the <b>Luminance</b> tolerance "
+ "to make image correction, not both at the same time. These settings "
+ "do not influence the main smoothing process controlled by the <b>Details</b> "
+ "settings."));
+
+ gridSettings2->addMultiCellWidget(label6, 1, 1, 0, 0);
+ gridSettings2->addMultiCellWidget(m_csmoothInput, 1, 1, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label8 = new TQLabel(i18n("Gamma:"), secondPage);
+
+ m_gammaInput = new KDoubleNumInput(secondPage);
+ m_gammaInput->setPrecision(1);
+ m_gammaInput->setRange(0.3, 3.0, 0.1, true);
+ TQWhatsThis::add( m_gammaInput, i18n("<p><b>Gamma</b>: this control sets the gamma tolerance of the image. This value "
+ "can be used to increase the tolerance values for darker areas (which commonly "
+ "are noisier). This results in more blur for shadow areas."));
+
+ gridSettings2->addMultiCellWidget(label8, 2, 2, 0, 0);
+ gridSettings2->addMultiCellWidget(m_gammaInput, 2, 2, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label9 = new TQLabel(i18n("Damping:"), secondPage);
+
+ m_dampingInput = new KDoubleNumInput(secondPage);
+ m_dampingInput->setPrecision(1);
+ m_dampingInput->setRange(0.5, 20.0, 0.5, true);
+ TQWhatsThis::add( m_dampingInput, i18n("<p><b>Damping</b>: this control sets the phase-jitter damping adjustment. "
+ "This value defines how fast the adaptive filter-radius reacts to luminance "
+ "variations. If increased, then edges appear smoother; if too high, then blur "
+ "may occur. If at minimum, then noise and phase jitter at the edges can occur. It "
+ "can suppress spike noise when increased, and this is the preferred method to "
+ "remove it."));
+
+ gridSettings2->addMultiCellWidget(label9, 3, 3, 0, 0);
+ gridSettings2->addMultiCellWidget(m_dampingInput, 3, 3, 1, 1);
+ gridSettings2->setColStretch(1, 10);
+ gridSettings2->setRowStretch(4, 10);
+
+ m_imagePreviewWidget->setUserAreaWidget(mainTab);
+
+ // -------------------------------------------------------------
+
+// connect(m_radiusInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_lumToleranceInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_thresholdInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_textureInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_sharpnessInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_csmoothInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_lookaheadInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_gammaInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_dampingInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+//
+// connect(m_phaseInput, TQ_SIGNAL(valueChanged(double)),
+// this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_NoiseReduction::~ImageEffect_NoiseReduction()
+{
+}
+
+void ImageEffect_NoiseReduction::renderingFinished()
+{
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+}
+
+void ImageEffect_NoiseReduction::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("noisereduction Tool Dialog");
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+
+ m_radiusInput->setValue(config->readDoubleNumEntry("RadiusAjustment", 1.0));
+ m_lumToleranceInput->setValue(config->readDoubleNumEntry("LumToleranceAjustment", 1.0));
+ m_thresholdInput->setValue(config->readDoubleNumEntry("ThresholdAjustment", 0.08));
+ m_textureInput->setValue(config->readDoubleNumEntry("TextureAjustment", 0.0));
+ m_sharpnessInput->setValue(config->readDoubleNumEntry("SharpnessAjustment", 0.25));
+ m_csmoothInput->setValue(config->readDoubleNumEntry("CsmoothAjustment", 1.0));
+ m_lookaheadInput->setValue(config->readDoubleNumEntry("LookAheadAjustment", 2.0));
+ m_gammaInput->setValue(config->readDoubleNumEntry("GammaAjustment", 1.4));
+ m_dampingInput->setValue(config->readDoubleNumEntry("DampingAjustment", 5.0));
+ m_phaseInput->setValue(config->readDoubleNumEntry("PhaseAjustment", 1.0));
+
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+}
+
+void ImageEffect_NoiseReduction::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("noisereduction Tool Dialog");
+ config->writeEntry("RadiusAjustment", m_radiusInput->value());
+ config->writeEntry("LumToleranceAjustment", m_lumToleranceInput->value());
+ config->writeEntry("ThresholdAjustment", m_thresholdInput->value());
+ config->writeEntry("TextureAjustment", m_textureInput->value());
+ config->writeEntry("SharpnessAjustment", m_sharpnessInput->value());
+ config->writeEntry("CsmoothAjustment", m_csmoothInput->value());
+ config->writeEntry("LookAheadAjustment", m_lookaheadInput->value());
+ config->writeEntry("GammaAjustment", m_gammaInput->value());
+ config->writeEntry("DampingAjustment", m_dampingInput->value());
+ config->writeEntry("PhaseAjustment", m_phaseInput->value());
+ config->sync();
+}
+
+void ImageEffect_NoiseReduction::resetValues()
+{
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+
+ m_radiusInput->setValue(1.0);
+ m_lumToleranceInput->setValue(1.0);
+ m_thresholdInput->setValue(0.08);
+ m_textureInput->setValue(0.0);
+ m_sharpnessInput->setValue(0.25);
+ m_csmoothInput->setValue(1.0);
+ m_lookaheadInput->setValue(2.0);
+ m_gammaInput->setValue(1.4);
+ m_dampingInput->setValue(5.0);
+ m_phaseInput->setValue(1.0);
+
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+}
+
+void ImageEffect_NoiseReduction::prepareEffect()
+{
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ double r = m_radiusInput->value();
+ double l = m_lumToleranceInput->value();
+ double th = m_thresholdInput->value();
+ double tx = m_textureInput->value();
+ double s = m_sharpnessInput->value();
+ double c = m_csmoothInput->value();
+ double a = m_lookaheadInput->value();
+ double g = m_gammaInput->value();
+ double d = m_dampingInput->value();
+ double p = m_phaseInput->value();
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new NoiseReduction(&image,
+ this, r, l, th, tx, s, c, a, g, d, p));
+}
+
+void ImageEffect_NoiseReduction::prepareFinal()
+{
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ double r = m_radiusInput->value();
+ double l = m_lumToleranceInput->value();
+ double th = m_thresholdInput->value();
+ double tx = m_textureInput->value();
+ double s = m_sharpnessInput->value();
+ double c = m_csmoothInput->value();
+ double a = m_lookaheadInput->value();
+ double g = m_gammaInput->value();
+ double d = m_dampingInput->value();
+ double p = m_phaseInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new NoiseReduction(iface.getOriginalImg(),
+ this, r, l, th, tx, s, c, a, g, d, p));
+}
+
+void ImageEffect_NoiseReduction::putPreviewData(void)
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_NoiseReduction::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Noise Reduction"), m_threadedFilter->getTargetImage().bits());
+}
+
+void ImageEffect_NoiseReduction::slotUser3()
+{
+ KURL loadRestorationFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Noise Reduction Settings File to Load")) );
+ if ( loadRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(loadRestorationFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+ if ( stream.readLine() != "# Photograph Noise Reduction Configuration File" )
+ {
+ KMessageBox::error(this,
+ i18n("\"%1\" is not a Photograph Noise Reduction settings text file.")
+ .arg(loadRestorationFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+ m_radiusInput->setValue( stream.readLine().toDouble() );
+ m_lumToleranceInput->setValue( stream.readLine().toDouble() );
+ m_thresholdInput->setValue( stream.readLine().toDouble() );
+ m_textureInput->setValue( stream.readLine().toDouble() );
+ m_sharpnessInput->setValue( stream.readLine().toDouble() );
+ m_csmoothInput->setValue( stream.readLine().toDouble() );
+ m_lookaheadInput->setValue( stream.readLine().toDouble() );
+ m_gammaInput->setValue( stream.readLine().toDouble() );
+ m_dampingInput->setValue( stream.readLine().toDouble() );
+ m_phaseInput->setValue( stream.readLine().toDouble() );
+ blockSignals(false);
+// slotEffect();
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot load settings from the Photograph Noise Reduction text file."));
+
+ file.close();
+}
+
+void ImageEffect_NoiseReduction::slotUser2()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Noise Reduction Settings File to Save")) );
+ if ( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# Photograph Noise Reduction Configuration File\n";
+ stream << m_radiusInput->value() << "\n";
+ stream << m_lumToleranceInput->value() << "\n";
+ stream << m_thresholdInput->value() << "\n";
+ stream << m_textureInput->value() << "\n";
+ stream << m_sharpnessInput->value() << "\n";
+ stream << m_csmoothInput->value() << "\n";
+ stream << m_lookaheadInput->value() << "\n";
+ stream << m_gammaInput->value() << "\n";
+ stream << m_dampingInput->value() << "\n";
+ stream << m_phaseInput->value() << "\n";
+
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot save settings to the Photograph Noise Reduction text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
+
diff --git a/src/imageplugins/noisereduction/imageeffect_noisereduction.h b/src/imageplugins/noisereduction/imageeffect_noisereduction.h
new file mode 100644
index 00000000..b7ee1bb6
--- /dev/null
+++ b/src/imageplugins/noisereduction/imageeffect_noisereduction.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_NOISEREDUCTION_H
+#define IMAGEEFFECT_NOISEREDUCTION_H
+
+// Local includes.
+
+#include "ctrlpaneldlg.h"
+
+class KDoubleNumInput;
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+class ImageEffect_NoiseReduction : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_NoiseReduction(TQWidget* parent);
+ ~ImageEffect_NoiseReduction();
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+
+private:
+
+ KDoubleNumInput *m_radiusInput;
+ KDoubleNumInput *m_lumToleranceInput;
+ KDoubleNumInput *m_thresholdInput;
+ KDoubleNumInput *m_textureInput;
+ KDoubleNumInput *m_sharpnessInput;
+
+ KDoubleNumInput *m_csmoothInput;
+ KDoubleNumInput *m_lookaheadInput;
+ KDoubleNumInput *m_gammaInput;
+ KDoubleNumInput *m_dampingInput;
+ KDoubleNumInput *m_phaseInput;
+};
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
+
+#endif /* IMAGEEFFECT_NOISEREDUCTION_H */
diff --git a/src/imageplugins/noisereduction/imageplugin_noisereduction.cpp b/src/imageplugins/noisereduction/imageplugin_noisereduction.cpp
new file mode 100644
index 00000000..8392933d
--- /dev/null
+++ b/src/imageplugins/noisereduction/imageplugin_noisereduction.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "noisereductiontool.h"
+#include "imageplugin_noisereduction.h"
+#include "imageplugin_noisereduction.moc"
+
+using namespace DigikamNoiseReductionImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_noisereduction,
+ KGenericFactory<ImagePlugin_NoiseReduction>("digikamimageplugin_noisereduction"));
+
+ImagePlugin_NoiseReduction::ImagePlugin_NoiseReduction(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_NoiseReduction")
+{
+ m_noiseReductionAction = new TDEAction(i18n("Noise Reduction..."), "noisereduction", 0,
+ this, TQ_SLOT(slotNoiseReduction()),
+ actionCollection(), "imageplugin_noisereduction");
+
+ setXMLFile("digikamimageplugin_noisereduction_ui.rc");
+
+ DDebug() << "ImagePlugin_NoiseReduction plugin loaded" << endl;
+}
+
+ImagePlugin_NoiseReduction::~ImagePlugin_NoiseReduction()
+{
+}
+
+void ImagePlugin_NoiseReduction::setEnabledActions(bool enable)
+{
+ m_noiseReductionAction->setEnabled(enable);
+}
+
+void ImagePlugin_NoiseReduction::slotNoiseReduction()
+{
+ NoiseReductionTool *tool = new NoiseReductionTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/noisereduction/imageplugin_noisereduction.h b/src/imageplugins/noisereduction/imageplugin_noisereduction.h
new file mode 100644
index 00000000..3cbcb312
--- /dev/null
+++ b/src/imageplugins/noisereduction/imageplugin_noisereduction.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_NOISEREDUCTION_H
+#define IMAGEPLUGIN_NOISEREDUCTION_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_NoiseReduction : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_NoiseReduction(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_NoiseReduction();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotNoiseReduction();
+
+private:
+
+ TDEAction *m_noiseReductionAction;
+};
+
+#endif /* IMAGEPLUGIN_NOISEREDUCTION_H */
diff --git a/src/imageplugins/noisereduction/noisereduction.cpp b/src/imageplugins/noisereduction/noisereduction.cpp
new file mode 100644
index 00000000..b9be4729
--- /dev/null
+++ b/src/imageplugins/noisereduction/noisereduction.cpp
@@ -0,0 +1,809 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Noise Reduction threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original Noise Filter algorithm copyright (C) 2005
+ * Peter Heckert <peter dot heckert at arcor dot de>
+ * from dcamnoise2 gimp plugin available at this url :
+ * http://home.arcor.de/peter.heckert/dcamnoise2-0.63.c
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#define IIR1(dest,src) (dest) = (d3 = ((((src) * b + d3) * b3 + d2) * b2 + d1) * b1)
+#define IIR2(dest,src) (dest) = (d2 = ((((src) * b + d2) * b3 + d1) * b2 + d3) * b1)
+#define IIR3(dest,src) (dest) = (d1 = ((((src) * b + d1) * b3 + d3) * b2 + d2) * b1)
+
+#define IIR1A(dest,src) (dest) = fabs(d3 = ((((src) * b + d3) * b3 + d2) * b2 + d1) * b1)
+#define IIR2A(dest,src) (dest) = fabs(d2 = ((((src) * b + d2) * b3 + d1) * b2 + d3) * b1)
+#define IIR3A(dest,src) (dest) = fabs(d1 = ((((src) * b + d1) * b3 + d3) * b2 + d2) * b1)
+
+#define FR 0.212671
+#define FG 0.715160
+#define FB 0.072169
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "noisereduction.h"
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+NoiseReduction::NoiseReduction(Digikam::DImg *orgImage, TQObject *parent,
+ double radius, double lsmooth, double effect, double texture, double sharp,
+ double csmooth, double lookahead, double gamma, double damping, double phase)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "NoiseReduction")
+{
+ m_radius = radius; /* default radius default = 1.0 */
+ m_sharp = sharp; /* Sharpness factor default = 0.25 */
+ m_lsmooth = lsmooth; /* Luminance Tolerance default = 1.0 */
+ m_effect = effect; /* Adaptive filter-effect threshold default = 0.08 */
+ m_texture = texture; /* Texture Detail default = 0.0 */
+
+ m_csmooth = csmooth; /* RGB Tolerance default = 1.0 */
+ m_lookahead = lookahead; /* Lookahead default = 2.0 */
+ m_gamma = gamma; /* Filter gamma default = 1.0 */
+ m_damping = damping; /* Phase jitter Damping default = 5.0 */
+ m_phase = phase; /* Area Noise Clip default = 1.0 */
+
+ m_iir.B = 0.0;
+ m_iir.b1 = 0.0;
+ m_iir.b2 = 0.0;
+ m_iir.b3 = 0.0;
+ m_iir.b0 = 0.0;
+ m_iir.r = 0.0;
+ m_iir.q = 0.0;
+ m_iir.p = 0;
+
+ m_clampMax = m_orgImage.sixteenBit() ? 65535 : 255;
+
+ initFilter();
+}
+
+// Remove noise on the region, given a source region, dest.
+// region, width and height of the regions, and corner coordinates of
+// a subregion to act upon. Everything outside the subregion is unaffected.
+
+void NoiseReduction::filterImage(void)
+{
+ int bytes = m_orgImage.bytesDepth(); // Bytes per pixel sample
+ uchar *srcPR = m_orgImage.bits();
+ uchar *destPR = m_destImage.bits();
+ int width = m_orgImage.width();
+ int height = m_orgImage.height();
+
+ int row, col, i, progress;
+ float prob = 0.0;
+
+ int w = (int)((m_radius + m_lookahead + m_damping + m_phase) * 4.0 + 40.0);
+
+ // NOTE: commented from original implementation
+ // if (radius < m_lookahead) w = m_lookahead * 4.0 + 40.0;
+
+ float csmooth = m_csmooth;
+
+ // Raw Filter preview
+
+ if (csmooth >= 0.99) csmooth = 1.0;
+
+ // Allocate and init buffers
+
+ uchar *src = new uchar[ TQMAX (width, height) * bytes ];
+ uchar *dest = new uchar[ TQMAX (width, height) * bytes ];
+ float *data = new float[ TQMAX (width, height) + 2*w ];
+ float *data2 = new float[ TQMAX (width, height) + 2*w ];
+ float *buffer = new float[ TQMAX (width, height) + 2*w ];
+ float *rbuf = new float[ TQMAX (width, height) + 2*w ];
+ float *tbuf = new float[ TQMAX (width, height) + 2*w ];
+
+ memset (src, 0, TQMAX (width, height) * bytes);
+ memset (dest, 0, TQMAX (width, height) * bytes);
+
+ for (i=0 ; i < TQMAX(width,height)+2*w-1 ; i++)
+ data[i] = data2[i] = buffer[i] = rbuf[i] = tbuf[i] = 0.0;
+
+ // Initialize the damping filter coefficients
+
+ iir_init(m_radius);
+
+ // blur the rows
+
+ for (row = 0 ; !m_cancel && (row < height) ; row++)
+ {
+ memcpy(src, srcPR + row*width*bytes, width*bytes);
+ memcpy(dest, src, width*bytes);
+
+ blur_line (data+w, data2+w, buffer+w, rbuf+w, tbuf+w, src, dest, width);
+
+ memcpy(destPR + row*width*bytes, dest, width*bytes);
+
+ progress = (int)(((double)row * 20.0) / height);
+ if ( progress%2 == 0 )
+ postProgress( progress );
+ }
+
+ // blur the cols
+
+ for (col = 0 ; !m_cancel && (col < width) ; col++)
+ {
+ for (int n = 0 ; n < height ; n++)
+ memcpy(src + n*bytes, destPR + (col + width*n)*bytes, bytes);
+
+ for (int n = 0 ; n < height ; n++)
+ memcpy(dest + n*bytes, srcPR + (col + width*n)*bytes, bytes);
+
+ blur_line (data+w, data2+w, buffer+w, rbuf+w, tbuf+w, src, dest, height);
+
+ for (int n = 0 ; n < height ; n++)
+ memcpy(destPR + (col + width*n)*bytes, dest + n*bytes, bytes);
+
+ progress = (int)(20.0 + ((double)col * 20.0) / width);
+ if ( progress%2 == 0 )
+ postProgress( progress );
+ }
+
+ // merge the source and destination (which currently contains
+ // the blurred version) images
+
+ for (row = 0 ; !m_cancel && (row < height) ; row++)
+ {
+ uchar *s = src;
+ uchar *d = dest;
+ unsigned short *s16 = (unsigned short *)src;
+ unsigned short *d16 = (unsigned short *)dest;
+ float value;
+ int u, v;
+
+ // get source row
+
+ memcpy(src, srcPR + row*width*bytes, width*bytes);
+ memcpy(dest, destPR + row*width*bytes, width*bytes);
+
+ // get dest row and combine the two
+
+ float t = m_csmooth;
+ float t2 = m_lsmooth;
+
+ // Values are squared, so that sliders get a nonlinear chracteristic
+ // for better adjustment accuracy when values are small.
+ t*=t;
+ t2*=t2;
+
+ for (u = 0 ; !m_cancel && (u < width) ; u++)
+ {
+ float dpix[3], spix[3];
+ float lum, red, green, blue;
+ float lum2, red2, green2, blue2;
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ {
+ red = (float) s16[2]/(float)m_clampMax;
+ green = (float) s16[1]/(float)m_clampMax;
+ blue = (float) s16[0]/(float)m_clampMax;
+ }
+ else // 8 bits image
+ {
+ red = (float) s[2]/(float)m_clampMax;
+ green = (float) s[1]/(float)m_clampMax;
+ blue = (float) s[0]/(float)m_clampMax;
+ }
+
+ spix[2] = red;
+ spix[1] = green;
+ spix[0] = blue;
+
+ lum = (FR*red + FG*green + FB*blue);
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ {
+ red2 = (float) d16[2]/(float)m_clampMax;
+ green2 = (float) d16[1]/(float)m_clampMax;
+ blue2 = (float) d16[0]/(float)m_clampMax;
+ }
+ else // 8 bits image
+ {
+ red2 = (float) d[2]/(float)m_clampMax;
+ green2 = (float) d[1]/(float)m_clampMax;
+ blue2 = (float) d[0]/(float)m_clampMax;
+ }
+
+ lum2 = (FR*red2 + FG*green2 + FB*blue2);
+
+ // Calculate luminance error (contrast error) for filtered template.
+ // This error is biggest, where edges are. Edges anyway cannot be filtered.
+ // Therefore we can correct luminance error in edges without increasing noise.
+ // Should be adjusted carefully, or not so carefully if you intentionally want to add noise.
+ // Noise, if not colorized, /can/ look good, so this makes sense.
+
+ float dl = lum - lum2;
+
+ // Multiply dl with first derivative of gamma curve divided by derivative value for midtone 0.5
+ // So bright tones will be corrected more (get more luminance noise and -information) than
+ // darker values because bright parts of image generally are less noisy, this is what we want.
+
+ dl *= pow(lum2/0.5, m_gamma-1.0);
+
+ if (t2 > 0.0)
+ dl *= (1.0 - exp(-dl*dl/(2.0*t2*t2)));
+
+ // NOTE: commented from original implementation
+ // if (dl > p) dl = p;
+ // if (dl < -p) dl = -p;
+
+ dpix[2] = red2 + dl;
+ dpix[1] = green2 + dl;
+ dpix[0] = blue2 + dl;
+
+ for (v = 0 ; !m_cancel && (v < 3) ; v++)
+ {
+ float value = spix[v];
+ float fvalue = dpix[v];
+ float mvalue = (value + fvalue)/2.0;
+ float diff = (value) - (fvalue);
+
+ // Multiply diff with first derivative of gamma curve divided by derivative value for midtone 0.5
+ // So midtones will stay unchanged, darker values get more blur and brighter values get less blur
+ // when we increase gamma.
+
+ diff *= pow(mvalue/0.5, m_gamma-1.0);
+
+ // Calculate noise probability for pixel
+ // TODO : probably it is not probability but an arbitrary curve.
+ // Probably we should provide a GUI-interface for this!!!
+
+ if (t > 0.0)
+ prob = exp(-diff*diff/(2.0*t*t));
+ else
+ prob = 0.0;
+
+ // Allow viewing of raw filter output
+
+ if (t >= 0.99)
+ prob = 1.0;
+
+ dpix[v] = value = fvalue * prob + value * (1.0 - prob);
+ }
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ {
+ value = dpix[0]*(float)m_clampMax+0.5;
+ d16[0] = (unsigned short)CLAMP(value, 0, m_clampMax);
+ value = dpix[1]*(float)m_clampMax+0.5;
+ d16[1] = (unsigned short)CLAMP(value, 0, m_clampMax);
+ value = dpix[2]*(float)m_clampMax+0.5;
+ d16[2] = (unsigned short)CLAMP(value, 0, m_clampMax);
+
+ d16 += 4;
+ s16 += 4;
+ }
+ else // 8 bits image
+ {
+ value = dpix[0]*(float)m_clampMax+0.5;
+ d[0] = (uchar)CLAMP(value, 0, m_clampMax);
+ value = dpix[1]*(float)m_clampMax+0.5;
+ d[1] = (uchar)CLAMP(value, 0, m_clampMax);
+ value = dpix[2]*(float)m_clampMax+0.5;
+ d[2] = (uchar)CLAMP(value, 0, m_clampMax);
+
+ d += 4;
+ s += 4;
+ }
+ }
+
+ memcpy(destPR + row*width*bytes, dest, width*bytes);
+
+ progress = (int)(40.0 + ((double)row * 60.0) / height);
+ if ( progress%2 == 0 )
+ postProgress( progress );
+ }
+
+ delete [] data;
+ delete [] data2;
+ delete [] buffer;
+ delete [] rbuf;
+ delete [] tbuf;
+ delete [] dest;
+ delete [] src;
+}
+
+// This function is written as if it is blurring a column at a time,
+// even though it can operate on rows, too. There is no difference
+// in the processing of the lines, at least to the blur_line function.
+// 'len' is the length of src and dest
+
+void NoiseReduction::blur_line(float* const data, float* const data2, float* const buffer,
+ float* rbuf, float* tbuf, const uchar *src, uchar *dest, int len)
+{
+ int b;
+ int row;
+ int idx;
+
+ unsigned short *src16 = (unsigned short *)src;
+ unsigned short *dest16 = (unsigned short *)dest;
+
+ // Calculate radius factors
+
+ for (row = 0, idx = 0 ; !m_cancel && (idx < len) ; row += 4, idx++)
+ {
+ // Color weigths are chosen proportional to Bayer Sensor pixel count
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ {
+ data[idx] = (float) dest16[row+2] / (float)m_clampMax * 0.25; // Red color
+ data[idx] += (float) dest16[row+1] / (float)m_clampMax * 0.5; // Green color
+ data[idx] += (float) dest16[row] / (float)m_clampMax * 0.25; // Blue color
+ data[idx] = mypow(data[idx], m_gamma);
+ }
+ else // 8 bits image
+ {
+ data[idx] = (float) dest[row+2] / (float)m_clampMax * 0.25; // Red color
+ data[idx] += (float) dest[row+1] / (float)m_clampMax * 0.5; // Green color
+ data[idx] += (float) dest[row] / (float)m_clampMax * 0.25; // Blue color
+ data[idx] = mypow(data[idx], m_gamma);
+ }
+ }
+
+ filter(data, data2, buffer, rbuf, tbuf, len, -1);
+
+ // Do actual filtering
+
+ for (b = 0 ; !m_cancel && (b < 3) ; b++)
+ {
+ for (row = b, idx = 0 ; !m_cancel && (idx < len) ; row += 4, idx++)
+ {
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ data[idx] = (float)src16[row] / (float)m_clampMax;
+ else // 8 bits image
+ data[idx] = (float)src[row] / (float)m_clampMax;
+ }
+
+ filter(data, data2, buffer, rbuf, tbuf, len, b);
+
+ for (row = b, idx = 0 ; !m_cancel && (idx < len) ; row += 4, idx++)
+ {
+ int value = (int)(data[idx] * (float)m_clampMax + 0.5);
+
+ if (m_orgImage.sixteenBit()) // 16 bits image
+ dest16[row] = (unsigned short)CLAMP( value, 0, m_clampMax);
+ else // 8 bits image
+ dest[row] = (uchar)CLAMP( value, 0, m_clampMax);
+ }
+ }
+}
+
+void NoiseReduction::iir_init(double r)
+{
+ if (m_iir.r == r)
+ return;
+
+ // damping settings;
+ m_iir.r = r;
+
+ double q;
+
+ if ( r >= 2.5)
+ q = 0.98711 * r - 0.96330;
+ else
+ q = 3.97156 - 4.14554 * sqrt(1.0 - 0.26891 * r);
+
+ m_iir.q = q;
+ m_iir.b0 = 1.57825 + ((0.422205 * q + 1.4281) * q + 2.44413) * q;
+ m_iir.b1 = ((1.26661 * q +2.85619) * q + 2.44413) * q / m_iir.b0;
+ m_iir.b2 = - ((1.26661*q +1.4281) * q * q ) / m_iir.b0;
+ m_iir.b3 = 0.422205 * q * q * q / m_iir.b0;
+ m_iir.B = 1.0 - (m_iir.b1 + m_iir.b2 + m_iir.b3);
+}
+
+void NoiseReduction::box_filter(double *src, double *end, double *dest, double radius)
+{
+ int boxwidth = 1;
+ float box = (*src);
+ float fbw = 2.0 * radius;
+
+ if (fbw < 1.0)
+ fbw = 1.0;
+
+ while(boxwidth+2 <= (int) fbw) boxwidth+=2, box += (src[boxwidth/2]) + (src[-boxwidth/2]);
+
+ double frac = (fbw - (double) boxwidth) / 2.0;
+ int bh = boxwidth / 2;
+ int bh1 = boxwidth / 2+1;
+
+ for ( ; src <= end ; src++, dest++)
+ {
+ *dest = (box + frac * ((src[bh1])+(src[-bh1]))) / fbw;
+ box = box - (src[-bh]) + (src[bh1]);
+ }
+}
+
+// Bidirectional IIR-filter, speed optimized
+
+void NoiseReduction::iir_filter(float* const start, float* const end, float* dstart,
+ double radius, const int type)
+{
+ if (!dstart)
+ dstart = start;
+
+ int width;
+ float *src = start;
+ float *dest = dstart;
+ float *dend = dstart + (end - start);
+
+ radius = floor((radius + 0.1) / 0.5) * 0.5;
+
+ // NOTE: commented from original implementation
+ // gfloat boxwidth = radius * 2.0;
+ // gint bw = (gint) boxwidth;
+
+ int ofs = (int)radius;
+ if (ofs < 1) ofs = 1;
+
+ double d1, d2, d3;
+
+ width = end - start + 1;
+
+ if (radius < 0.25)
+ {
+ if ( start != dest )
+ {
+ memcpy(dest, start, width*sizeof(*dest));
+ return;
+ }
+ }
+
+ iir_init(radius);
+
+ const double b1 = m_iir.b1;
+ const double b2 = m_iir.b2 / m_iir.b1;
+ const double b3 = m_iir.b3 / m_iir.b2;
+ const double b = m_iir.B / m_iir.b3;
+
+ switch(type)
+ {
+ case Gaussian:
+
+ d1 = d2 = d3 = *dest;
+ dend -= 6;
+ src--;
+ dest--;
+
+ while (dest < dend)
+ {
+ IIR1(*(++dest), *(++src));
+ IIR2(*(++dest), *(++src));
+ IIR3(*(++dest), *(++src));
+ IIR1(*(++dest), *(++src));
+ IIR2(*(++dest), *(++src));
+ IIR3(*(++dest), *(++src));
+ }
+
+ dend += 6;
+
+ while (1)
+ {
+ if (++dest > dend) break;
+ IIR1(*dest,*(++src));
+ if (++dest > dend) break;
+ IIR2(*dest,*(++src));
+ if (++dest > dend) break;
+ IIR3(*dest,*(++src));
+ }
+
+ d1 = d2 = d3 = dest[-1];
+ dstart += 6;
+
+ while (dest > dstart)
+ {
+ --dest, IIR1(*dest, *dest);
+ --dest, IIR2(*dest, *dest);
+ --dest, IIR3(*dest, *dest);
+ --dest, IIR1(*dest, *dest);
+ --dest, IIR2(*dest, *dest);
+ --dest, IIR3(*dest, *dest);
+ }
+
+ dstart -= 6;
+
+ while (1)
+ {
+ if (--dest < dstart) break;
+ IIR1(*dest, *dest);
+ if (--dest < dstart) break;
+ IIR2(*dest, *dest);
+ if (--dest < dstart) break;
+ IIR3(*dest, *dest);
+ }
+
+ break;
+
+ case SecondDerivative: // rectified and filtered second derivative, source and dest may be equal
+
+ d1 = d2 = d3 = 0.0;
+ dest[0] = dest[ofs] = 0.0;
+ dend -= 6;
+ dest--;
+ src--;
+
+ while (dest < dend)
+ {
+ ++src, IIR1(*(++dest), src[ofs]-src[0]);
+ ++src, IIR2(*(++dest), src[ofs]-src[0]);
+ ++src, IIR3(*(++dest), src[ofs]-src[0]);
+ ++src, IIR1(*(++dest), src[ofs]-src[0]);
+ ++src, IIR2(*(++dest), src[ofs]-src[0]);
+ ++src, IIR3(*(++dest), src[ofs]-src[0]);
+ }
+
+ dend += 6;
+
+ while (1)
+ {
+ if (++dest > dend) break;
+ ++src, IIR1(*dest, src[ofs]-src[0]);
+ if (++dest > dend) break;
+ ++src, IIR2(*dest, src[ofs]-src[0]);
+ if (++dest > dend) break;
+ ++src, IIR3(*dest, src[ofs]-src[0]);
+ }
+
+ d1 = d2 = d3 = 0.0;
+ dest[-1] = dest[-ofs-1] = 0.0;
+ dstart += 6;
+
+ while (dest > dstart)
+ {
+ --dest, IIR1A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR2A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR3A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR1A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR2A(*dest, dest[0]-dest[-ofs]);
+ --dest, IIR3A(*dest, dest[0]-dest[-ofs]);
+ }
+
+ dstart -= 6;
+
+ while (1)
+ {
+ if (--dest < dstart) break;
+ IIR1A(*dest, dest[0]-dest[-ofs]);
+ if (--dest < dstart) break;
+ IIR2A(*dest, dest[0]-dest[-ofs]);
+ if (--dest < dstart) break;
+ IIR3A(*dest, dest[0]-dest[-ofs]);
+ }
+
+ break;
+ }
+}
+
+// A forward-backward box filter is used here and the radius is adapted to luminance jump.
+// Radius is calculated fron 1st and 2nd derivative of intensity values.
+// (Its not exactly 2nd derivative, but something similar, optimized by experiment)
+// The radius variations are filtered. This reduces spatial phase jitter.
+
+void NoiseReduction::filter(float *buffer, float *data, float *data2, float *rbuf,
+ float */*tbuf*/, int width, int color)
+{
+ float *lp = data;
+ float *rp = data + width-1;
+ float *lp2 = data2;
+ float *blp = buffer;
+ float *brp = buffer + width-1;
+ float *rbuflp = rbuf;
+ float *rbufrp = rbuf + width-1;
+ float fboxwidth = m_radius*2.0;
+ float fradius = m_radius;
+ float *p1, *p2;
+
+ if (fboxwidth < 1.0) fboxwidth = 1.0 ;
+ if (fradius < 0.5) fradius = 0.5;
+
+ int i, pass;
+ int ofs, ofs2;
+ float maxrad;
+ float fbw;
+ float val;
+ double rfact = m_effect*m_effect;
+ double sharp = m_sharp;
+
+ ofs2 = (int)floor(m_damping * 2.0 + 0.1);
+ ofs = (int)floor(m_lookahead * 2.0 + 0.1);
+ int w = (int)(fboxwidth + m_damping + m_lookahead + m_phase + 2.0);
+
+ // Mirror image edges
+
+ for (i=1 ; i <= w ; i++)
+ blp[-i] = blp[i];
+
+ for (i=1 ; i <= w ; i++)
+ brp[i] = brp[-i];
+
+ if (color < 0) // Calc 2nd derivative
+ {
+ // boost high frequency in rbuf
+
+ for (p1 = blp, p2 = rbuflp ; p1 <= brp ; p1++, p2++)
+ {
+ *p2 = (sharp+1.0) * p1[0] - sharp * 0.5 * (p1[-ofs]+p1[ofs]);
+ }
+
+ iir_filter(rbuflp-w, rbufrp+w, blp-w, m_lookahead, SecondDerivative);
+
+ // Mirror image edges
+
+ for (i = 1 ; i <= w ; i++)
+ blp[-i] = blp[i];
+
+ for (i = 1 ; i <= w ; i++)
+ brp[i] = brp[-i];
+
+ // boost high frequency in rbuf
+
+ for (p1 = blp, p2 = rbuflp ; p1 <= brp ; p1++, p2++)
+ {
+ *p2 = ((sharp+1.0) * (p1[0]) - sharp * 0.5 * ((p1[-ofs2])+(p1[ofs2])));
+ }
+
+ // Mirror rbuf edges
+
+ for (i = 1 ; i <= w ; i++)
+ rbuflp[-i] = rbuflp[i];
+
+ for (i = 1 ; i <= w ; i++)
+ rbufrp[i] = rbufrp[-i];
+
+ // Lowpass (gauss) filter rbuf, remove phase jitter
+
+ iir_filter(rbuflp-w+5, rbufrp+w-5, rbuflp-w+5, m_damping, Gaussian);
+
+ for (i = -w+5; i < width-1+w-5 ; i++)
+ {
+ // NOTE: commented from original implementation
+ // val = rbuflp[i];
+
+ val = rbuflp[i]-rfact;
+
+ // Avoid division by zero, clip negative filter overshoot
+
+ if (val < rfact/fradius) val=rfact/fradius;
+
+ val = rfact/val;
+
+ // NOTE: commented from original implementation
+ // val = pow(val/fradius,m_phase)*fradius;
+
+ if (val < 0.5) val = 0.5;
+
+ rbuflp[i] = val*2.0;
+ }
+
+ // Mirror rbuf edges
+
+ for (i=1 ; i <= w ; i++)
+ rbuflp[-i] = rbuflp[i];
+
+ for (i=1 ; i <= w ; i++)
+ rbufrp[i] = rbufrp[-i];
+
+ return;
+ }
+
+ // Calc lowpass filtered input signal
+
+ iir_filter(blp-w+1, brp+w-1, lp2-w+1, m_radius, Gaussian);
+
+ // Subtract low frequency from input signal (aka original image data)
+ // and predistort this signal
+
+ val = m_texture + 1.0;
+
+ for (i = -w+1 ; i <= width-1+w-1 ; i++)
+ {
+ blp[i] = mypow(blp[i] - lp2[i], val);
+ }
+
+ float *src, *dest;
+ val = m_texture + 1.0;
+
+ pass = 2;
+
+ while (pass--)
+ {
+ float sum;
+ int ibw;
+ src = blp;
+ dest = lp;
+ maxrad = 0.0;
+
+ // Mirror left edge
+
+ for (i=1 ; i <= w ; i++)
+ src[-i] = src[i];
+
+ sum = (src[-1] += src[-2]);
+
+ // forward pass
+
+ for (rbuf = rbuflp-(int) m_phase ; rbuf <= rbufrp; src++, dest++, rbuf++)
+ {
+ // NOTE: commented from original implementation
+ //fbw = fabs( rbuf[-ofs2]*ll2+rbuf[-ofs2-1]*rl2);
+
+ fbw = *rbuf;
+
+ if (fbw > (maxrad += 1.0)) fbw = maxrad;
+ else if (fbw < maxrad) maxrad = fbw;
+
+ ibw = (int)fbw;
+ *src = sum += *src;
+ *dest = (sum-src[-ibw]+(src[-ibw]-src[-ibw-1])*(fbw-ibw))/fbw;
+ }
+
+ src = rp;
+ dest = brp;
+ maxrad = 0.0;
+
+ // Mirror right edge
+
+ for (i=1 ; i <= w ; i++)
+ src[i] = src[-i];
+
+ sum = (src[1] += src[2]);
+
+ // backward pass
+
+ for ( rbuf = rbufrp +(int) m_phase ; rbuf >= rbuflp; src--, dest--, rbuf--)
+ {
+ // NOTE: commented from original implementation
+ //fbw = fabs( rbuf[ofs2]*ll2+rbuf[ofs2+1]*rl2);
+
+ fbw = *rbuf;
+
+ if (fbw > (maxrad +=1.0)) fbw = maxrad;
+ else if (fbw < maxrad) maxrad = fbw;
+
+ ibw = (int)fbw;
+
+ *src = sum += *src;
+ *dest = (sum-src[ibw]+(src[ibw]-src[ibw+1])*(fbw-ibw))/fbw;
+ }
+ }
+
+ val = 1.0 / (m_texture + 1.0);
+
+ for (i = -w+1 ; i <= width-1+w-1 ; i++)
+ {
+ // Undo predistortion
+
+ blp[i]= mypow(blp[i],val);
+
+ // Add in low frequency
+
+ blp[i] += lp2[i];
+
+ // NOTE: commented from original implementation
+ // if (blp[i] >= 0.0) blp[i] = pow(blp[i],val);
+ // else blp[i] = 0.0;
+ }
+}
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
diff --git a/src/imageplugins/noisereduction/noisereduction.h b/src/imageplugins/noisereduction/noisereduction.h
new file mode 100644
index 00000000..69e14123
--- /dev/null
+++ b/src/imageplugins/noisereduction/noisereduction.h
@@ -0,0 +1,257 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Noise Reduction threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original Noise Filter algorithm copyright (C) 2005
+ * Peter Heckert <peter dot heckert at arcor dot de>
+ * from dcamnoise2 gimp plugin available at this url :
+ * http://home.arcor.de/peter.heckert/dcamnoise2-0.63.c
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef NOISE_REDUCTION_H
+#define NOISE_REDUCTION_H
+
+// C++ includes.
+
+#include <cmath>
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+/**============= NOTICE TO USE THE FILTER ===============================================================
+ *
+ * Let me explain, how the filter works, some understanding is necessary to use it:
+ *
+ * Hint for the novice user:
+ * In most cases only Filter Max Radius, Filter treshold and Texture Detail are needed and the other
+ * params can be left at their default setting.
+ *
+ * Main Filter (Preprocessing)
+ * First, a filtered template is generated, using an adaptive filter.
+ * To see this template, we must set _Luminance tolerance, _Color tolerance to 1.0.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Filter max. Radius" is preset to 5.0
+ * This is good for most noise situations.
+ * In any case it must be about the same size as noise granularity ore somewhat more.
+ * If it is set higher than necessary, then it can cause unwanted blur.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Filter Threshold" should be set so that edges are clearly visible and noise is smoothed out.
+ * This threshold value is not bound to any intensity value, it is bound to the second derivative of
+ * intensity values.
+ * Simply adjust it and watch the preview. Adjustment must be made carefully, because the gap
+ * between "noisy", "smooth", and "blur" is very small. Adjust it as carefully as you would adjust
+ * the focus of a camera.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Lookahead" defines the pixel distance in which the filter looks ahead for luminance variations
+ * Normally the default value should do.
+ * When _Lookahead is increased, then spikenoise is erased.
+ * Eventually readjust Filter treshold, when you changed lookahead.
+ * When the value is to high, then the adaptive filter cannot longer accurately track image details, and
+ * noise can reappear or blur can occur.
+ *
+ * Minimum value is 1.0, this gives best accuracy when blurring very weak noise.
+ *
+ * I never had good success with other values than 2.0.
+ * However, for images with extemely high or low resolution another value possibly is better.
+ * Use it only as a last ressort.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Phase Jitter Damping" defines how fast the adaptive filter-radius reacts to luminance variations.
+ * I have preset a value, that should do in most cases.
+ * If increased, then edges appear smoother, if too high, then blur may occur.
+ * If at minimum then noise and phase jitter at edges can occur.
+ * It can suppress Spike noise when increased and this is the preferred method to remove spike noise.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Sharpness" does just what it says, it improves sharpness. It improves the frequency response for the filter.
+ * When it is too strong then not all noise can be removed, or spike noise may appear.
+ * Set it near to maximum, if you want to remove weak noise or JPEG-artifacts, without loosing detail.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Erosion". The new filter gives better sharpness and this also gives problems
+ * with spike noise. The Erosion param erodes singular spikes and it has a smooth effect to edges, and sharpens
+ * edges by erosion, so noise at edges is eroded.
+ * The effect is dependant from sharpness,phase-jitter damping and lookahead.
+ * Set it to minimum (zero), if you want to remove weak noise or JPEG-artifacts.
+ * When "Erosion" is increased, then also increasing "Phase Jitter Damping" is often useful
+ *
+ * It works nicely. Apart from removing spike noise it has a sharpening and antialiasing effect to edges
+ * (Sharpening occurs by erosion, not by deconvolution)
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * "Texture Detail" can be used, to get more or less texture accuracy.
+ * When decreased, then noise and texture are blurred out, when increased then texture is
+ * amplified, but also noise will increase.
+ * It has almost no effect to image edges, opposed to Filter theshold, which would blur edges, when increased.
+ *
+ * E.g. if Threshold is adjusted in away so that edges are sharp, and there is still too much area noise, then
+ * Texture detail could be used to reduce noise without blurring edges.
+ * (Another way would be to decrease radius and to increase threshold)
+ *
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * The filtered image that is now seen in the preview, is used as template for the following processing steps,
+ * therefore it is important to do this adjustment in first place and to do it as good as possible.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * Combining original image and filtered image, using tolerance thresholds (Postprocessing)
+ * This can give a final touch of sharpness to your image.
+ * It is not necessary to do this, if you want to reduce JPEG-artifacts or weak noise.
+ * It's purpose is to master strong noise without loosing too much sharpness.
+ *
+ * Note, that this all is done in one filter invocation. Preprocessing and postprocessing is done in one run,
+ * but logically and in the algorithm they are different and ordered processes.
+ *
+ *
+ * Adjust _Color tolerance or/and Luminance tolerance, (if necessary) so that you get the final image.
+ * I recommend to use only one, either _Color or _Luminance.
+ * These settings do not influence the main smoothing process. What they really do is this:
+ *
+ * The tolerance values are used as error-thresholds to compare the filtered template with the original
+ * image. The plugin algorithm uses them to combine the filtered template with the original image
+ * so that noise and filter errors (blur) are thrown out.
+ * A filtered pixel, that is too far away from the original pixel will be overridden by original image content.
+ *
+ * Hint:
+ * If you cange other sliders, like lookahead or Texture Detail, then you should set color tolerance and
+ * luminance tolerance to 1.0 (right end), because otherwise the filtered template is partially hidden
+ * and e.g. the effects for the damping filter cant be seen clearly and cant be optimized.
+ *------------------------------------------------------------------------------------------------------------
+ *
+ * _Gamma can be used to increase the tolerance values for darker areas (which commonly are more noisy)
+ * This results in more blur for shadow areas.
+ *
+ * Hint for users of previous versions:
+ * Gamma also influences the main-filter process. While the previous version did not have this feature,
+ * I have reimplemented it, however, the algorithm used is totally new.
+ *
+ *
+ * Keep in mind, how the filter works, then usage should be easy!
+ *
+ *
+ * ================ THEORY AND TECHNIC =======================================================================
+ *
+ * Some interesting things (theoretic and technic)
+ * This plugin bases on the assumption, that noise has no 2-dimensional correlation and therefore
+ * can be removed in a 1-dimensional process.
+ * To remove noise, I use a four-times boxfilter with variable radius.
+ *
+ * The radius is calculated from 2nd derivative of pixeldata.
+ * A gauss filter is used to calculte 2nd derivative.
+ * The filter has some inbuilt features to clip low amplitude noise to clip very high values that would
+ * slow down response time.
+ * The 2nd derivative is lowpassfiltered and then radius is calculated as (Filter Treshold)/2nd_derivative.
+ * The radius modulation data is precalulated and buffered an is used to steer filter radius when
+ * the actual filtering occurs.
+ *
+ * Noise and texture can be further suppressed by nonlinear distortion before adaptive filtering.
+ * To make this possible I subtract low frequency from image data before denoising, so that I get a
+ * bipolar, zerosymmetric image signal.
+ *
+ * The filter works in a /one-dimensional/ way. It is applied to x and then to y axis.
+ *
+ * After filtering a zerodimensional point operator (pixel by pixel comparison) is used, where
+ * filter-errors are thrown out.
+ * This is meant to limit and control filter errors,it can give "final touch" to the image, but it has
+ * nothing to do with the main filter process.
+ *
+ * I do not know if something like this filter already exists.
+ * It is all based on my own ideas and experiments.
+ * Possibly a separable adaptive gauss-filter is a new thing.
+ * Also it is an impossible thing, from a mathemathical point of view ;-)
+ * It is possible only for bandwidth limited images.
+ * Happyly most photographic images are bandwidth limited, or when they are noisy then we want
+ * to limit banwith locally. And this is, what the filter does: It limits bandwidth locally, dependent
+ * from (approximately) 2nd derivative of intensity.
+ *
+ * Because gauss filtering is essentially linear diffusion, and because this filter uses a variable
+ * nonlinear modulated gaussfilter (four box passes are almost gauss) we could say, that this filter
+ * implements a special subclass of nonlinear adaptive diffusion, which is separable, and indeed,
+ * results are very similar to nonlinear diffusion filters.
+ * However, because the filter is separable, it is much faster and needs less memory.
+ */
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+class NoiseReduction : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ NoiseReduction(Digikam::DImg *orgImage, TQObject *parent,
+ double radius, double lsmooth, double effect, double texture, double sharp,
+ double csmooth, double lookahead, double gamma, double damping, double phase);
+ ~NoiseReduction(){};
+
+private:
+
+ void filterImage(void);
+
+ void iir_init(double r);
+ void box_filter(double *src, double *end, double *dest, double radius);
+ void iir_filter(float* const start, float* const end, float* dstart, double radius, const int type);
+ void filter(float *buffer, float *data, float *data2, float *rbuf, float *tbuf, int width, int color);
+ void blur_line(float* const data, float* const data2, float* const buffer,
+ float* rbuf, float* tbuf, const uchar *src, uchar *dest, int len);
+
+ inline double mypow(double val, double ex)
+ {
+ if (fabs(val) < 1e-16) return 0.0;
+ if (val > 0.0) return exp(log(val)*ex);
+ return -exp(log(-val)*ex);
+ };
+
+private:
+
+ struct iir_param
+ {
+ double B, b1, b2, b3, b0, r, q;
+ double *p;
+ } m_iir;
+
+ enum IIRFilteringMode
+ {
+ Gaussian=0,
+ SecondDerivative
+ };
+
+ int m_clampMax;
+
+ double m_radius;
+ double m_lsmooth;
+ double m_csmooth;
+ double m_effect;
+ double m_lookahead;
+ double m_gamma;
+ double m_damping;
+ double m_phase;
+ double m_texture;
+ double m_sharp;
+};
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
+
+#endif /* NOISE_REDUCTION_H */
diff --git a/src/imageplugins/noisereduction/noisereductiontool.cpp b/src/imageplugins/noisereduction/noisereductiontool.cpp
new file mode 100644
index 00000000..d1e4908a
--- /dev/null
+++ b/src/imageplugins/noisereduction/noisereductiontool.cpp
@@ -0,0 +1,536 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqfile.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqstring.h>
+#include <tqtabwidget.h>
+#include <tqtextstream.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "noisereduction.h"
+#include "noisereductiontool.h"
+#include "noisereductiontool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+NoiseReductionTool::NoiseReductionTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("noisereduction");
+ setToolName(i18n("Noise Reduction"));
+ setToolIcon(SmallIcon("noisereduction"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 1, 1);
+
+ TQTabWidget *mainTab = new TQTabWidget(m_gboxSettings->plainPage());
+ TQWidget* firstPage = new TQWidget( mainTab );
+ TQGridLayout* grid1 = new TQGridLayout(firstPage, 6, 1);
+
+ TQLabel *label1 = new TQLabel(i18n("Radius:"), firstPage);
+
+ m_radiusInput = new RDoubleNumInput(firstPage);
+ m_radiusInput->setPrecision(1);
+ m_radiusInput->setRange(0.0, 10.0, 0.1);
+ m_radiusInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_radiusInput, i18n("<p><b>Radius</b>: this control selects the "
+ "gliding window size used for the filter. Larger values do not increase "
+ "the amount of time needed to filter each pixel in the image but "
+ "can cause blurring. This window moves across the image, and the "
+ "color in it is smoothed to remove imperfections. "
+ "In any case it must be about the same size as the noise granularity "
+ "or somewhat more. If it is set higher than necessary, then it "
+ "can cause unwanted blur."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Threshold:"), firstPage);
+
+ m_thresholdInput = new RDoubleNumInput(firstPage);
+ m_thresholdInput->setPrecision(2);
+ m_thresholdInput->setRange(0.0, 1.0, 0.01);
+ m_thresholdInput->setDefaultValue(0.08);
+ TQWhatsThis::add( m_thresholdInput, i18n("<p><b>Threshold</b>: use the slider for coarse adjustment, "
+ "and the spin control for fine adjustment to control edge detection sensitivity. "
+ "This value should be set so that edges and details are clearly visible "
+ "and noise is smoothed out. "
+ "Adjustment must be made carefully, because the gap between \"noisy\", "
+ "\"smooth\", and \"blur\" is very small. Adjust it as carefully as you would adjust "
+ "the focus of a camera."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label4 = new TQLabel(i18n("Texture:"), firstPage);
+
+ m_textureInput = new RDoubleNumInput(firstPage);
+ m_textureInput->setPrecision(2);
+ m_textureInput->setRange(-0.99, 0.99, 0.01);
+ m_textureInput->setDefaultValue(0.0);
+ TQWhatsThis::add( m_textureInput, i18n("<p><b>Texture</b>: this control sets the texture accuracy. "
+ "This value can be used, to get more or less texture accuracy. When decreased, "
+ "then noise and texture are blurred out, when increased then texture is "
+ "amplified, but also noise will increase. It has almost no effect on image edges."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label7 = new TQLabel(i18n("Sharpness:"), firstPage); // Filter setting "Lookahead".
+
+ m_sharpnessInput = new RDoubleNumInput(firstPage);
+ m_sharpnessInput->setPrecision(2);
+ m_sharpnessInput->setRange(0.0, 1.0, 0.1);
+ m_sharpnessInput->setDefaultValue(0.25);
+ TQWhatsThis::add( m_sharpnessInput, i18n("<p><b>Sharpness</b>: "
+ "This value improves the frequency response for the filter. "
+ "When it is too strong then not all noise can be removed, or spike noise may appear. "
+ "Set it near to maximum, if you want to remove very weak noise or JPEG-artifacts, "
+ "without losing detail."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label5 = new TQLabel(i18n("Edge Lookahead:"), firstPage); // Filter setting "Sharp".
+
+ m_lookaheadInput = new RDoubleNumInput(firstPage);
+ m_lookaheadInput->setPrecision(2);
+ m_lookaheadInput->setRange(0.01, 20.0, 0.01);
+ m_lookaheadInput->setDefaultValue(2.0);
+ TQWhatsThis::add( m_lookaheadInput, i18n("<p><b>Edge</b>: "
+ "This value defines the pixel distance to which the filter looks ahead for edges. "
+ "When this value is increased, then spike noise is erased. "
+ "You can eventually re-adjust the <b>Edge</b> filter, when you have changed this setting. "
+ "When this value is too high, the adaptive filter can no longer accurately track "
+ "image details, and noise or blurring can occur."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label10 = new TQLabel(i18n("Erosion:"), firstPage);
+
+ m_phaseInput = new RDoubleNumInput(firstPage);
+ m_phaseInput->setPrecision(1);
+ m_phaseInput->setRange(0.5, 20.0, 0.5);
+ m_phaseInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_phaseInput, i18n("<p><b>Erosion</b>: "
+ "Use this to increase edge noise erosion and spike noise erosion "
+ "(noise is removed by erosion)."));
+
+ grid1->addMultiCellWidget(label1, 0, 0, 0, 0);
+ grid1->addMultiCellWidget(m_radiusInput, 0, 0, 1, 1);
+ grid1->addMultiCellWidget(label3, 1, 1, 0, 0);
+ grid1->addMultiCellWidget(m_thresholdInput, 1, 1, 1, 1);
+ grid1->addMultiCellWidget(label4, 2, 2, 0, 0);
+ grid1->addMultiCellWidget(m_textureInput, 2, 2, 1, 1);
+ grid1->addMultiCellWidget(label7, 3, 3, 0, 0);
+ grid1->addMultiCellWidget(m_sharpnessInput, 3, 3, 1, 1);
+ grid1->addMultiCellWidget(label5, 4, 4, 0, 0);
+ grid1->addMultiCellWidget(m_lookaheadInput, 4, 4, 1, 1);
+ grid1->addMultiCellWidget(label10, 5, 5, 0, 0);
+ grid1->addMultiCellWidget(m_phaseInput, 5, 5, 1, 1);
+ grid1->setMargin(m_gboxSettings->spacingHint());
+ grid1->setSpacing(m_gboxSettings->spacingHint());
+ grid1->setColStretch(1, 10);
+ grid1->setRowStretch(6, 10);
+
+ mainTab->addTab( firstPage, i18n("Details") );
+
+ // -------------------------------------------------------------
+
+ TQWidget* secondPage = new TQWidget( mainTab );
+ TQGridLayout* grid2 = new TQGridLayout( secondPage, 4, 1);
+
+ TQLabel *label2 = new TQLabel(i18n("Luminance:"), secondPage);
+
+ m_lumToleranceInput = new RDoubleNumInput(secondPage);
+ m_lumToleranceInput->setPrecision(1);
+ m_lumToleranceInput->setRange(0.0, 1.0, 0.1);
+ m_lumToleranceInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_lumToleranceInput, i18n("<p><b>Luminance</b>: this control sets the luminance tolerance of the image."
+ "We recommend using either the <b>Color</b> or the <b>Luminance</b> tolerance settings "
+ "to make an image correction, not both at the same time. These settings "
+ "do not influence the main smoothing process controlled by the <b>Details</b> "
+ "settings."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label6 = new TQLabel(i18n("Color:"), secondPage);
+
+ m_csmoothInput = new RDoubleNumInput(secondPage);
+ m_csmoothInput->setPrecision(1);
+ m_csmoothInput->setRange(0.0, 1.0, 0.1);
+ m_csmoothInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_csmoothInput, i18n("<p><b>Color</b>: this control sets the color tolerance of the image. It is "
+ "recommended using either the <b>Color</b> or the <b>Luminance</b> tolerance "
+ "to make image correction, not both at the same time. These settings "
+ "do not influence the main smoothing process controlled by the <b>Details</b> "
+ "settings."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label8 = new TQLabel(i18n("Gamma:"), secondPage);
+
+ m_gammaInput = new RDoubleNumInput(secondPage);
+ m_gammaInput->setPrecision(1);
+ m_gammaInput->setRange(0.3, 3.0, 0.1);
+ m_gammaInput->setDefaultValue(1.4);
+ TQWhatsThis::add( m_gammaInput, i18n("<p><b>Gamma</b>: this control sets the gamma tolerance of the image. This value "
+ "can be used to increase the tolerance values for darker areas (which commonly "
+ "are noisier). This results in more blur for shadow areas."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label9 = new TQLabel(i18n("Damping:"), secondPage);
+
+ m_dampingInput = new RDoubleNumInput(secondPage);
+ m_dampingInput->setPrecision(1);
+ m_dampingInput->setRange(0.5, 20.0, 0.5);
+ m_dampingInput->setDefaultValue(5.0);
+ TQWhatsThis::add( m_dampingInput, i18n("<p><b>Damping</b>: this control sets the phase-jitter damping adjustment. "
+ "This value defines how fast the adaptive filter-radius reacts to luminance "
+ "variations. If increased, then edges appear smoother; if too high, then blur "
+ "may occur. If at minimum, then noise and phase jitter at the edges can occur. It "
+ "can suppress spike noise when increased, and this is the preferred method to "
+ "remove it."));
+
+ grid2->addMultiCellWidget(label2, 0, 0, 0, 0);
+ grid2->addMultiCellWidget(m_lumToleranceInput, 0, 0, 1, 1);
+ grid2->addMultiCellWidget(label6, 1, 1, 0, 0);
+ grid2->addMultiCellWidget(m_csmoothInput, 1, 1, 1, 1);
+ grid2->addMultiCellWidget(label8, 2, 2, 0, 0);
+ grid2->addMultiCellWidget(m_gammaInput, 2, 2, 1, 1);
+ grid2->addMultiCellWidget(label9, 3, 3, 0, 0);
+ grid2->addMultiCellWidget(m_dampingInput, 3, 3, 1, 1);
+ grid2->setMargin(m_gboxSettings->spacingHint());
+ grid2->setSpacing(m_gboxSettings->spacingHint());
+ grid2->setColStretch(1, 10);
+ grid2->setRowStretch(4, 10);
+
+ mainTab->addTab( secondPage, i18n("Advanced") );
+
+ grid->addMultiCellWidget(mainTab, 0, 0, 0, 1);
+ grid->setRowStretch(1, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "noisereduction Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+}
+
+NoiseReductionTool::~NoiseReductionTool()
+{
+}
+
+void NoiseReductionTool::renderingFinished()
+{
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+}
+
+void NoiseReductionTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("noisereduction Tool");
+
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ m_radiusInput->setValue(config->readDoubleNumEntry("RadiusAjustment", m_radiusInput->defaultValue()));
+ m_lumToleranceInput->setValue(config->readDoubleNumEntry("LumToleranceAjustment", m_lumToleranceInput->defaultValue()));
+ m_thresholdInput->setValue(config->readDoubleNumEntry("ThresholdAjustment", m_thresholdInput->defaultValue()));
+ m_textureInput->setValue(config->readDoubleNumEntry("TextureAjustment", m_textureInput->defaultValue()));
+ m_sharpnessInput->setValue(config->readDoubleNumEntry("SharpnessAjustment", m_sharpnessInput->defaultValue()));
+ m_csmoothInput->setValue(config->readDoubleNumEntry("CsmoothAjustment", m_csmoothInput->defaultValue()));
+ m_lookaheadInput->setValue(config->readDoubleNumEntry("LookAheadAjustment", m_lookaheadInput->defaultValue()));
+ m_gammaInput->setValue(config->readDoubleNumEntry("GammaAjustment", m_gammaInput->defaultValue()));
+ m_dampingInput->setValue(config->readDoubleNumEntry("DampingAjustment", m_dampingInput->defaultValue()));
+ m_phaseInput->setValue(config->readDoubleNumEntry("PhaseAjustment", m_phaseInput->defaultValue()));
+
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+}
+
+void NoiseReductionTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("noisereduction Tool");
+ config->writeEntry("RadiusAjustment", m_radiusInput->value());
+ config->writeEntry("LumToleranceAjustment", m_lumToleranceInput->value());
+ config->writeEntry("ThresholdAjustment", m_thresholdInput->value());
+ config->writeEntry("TextureAjustment", m_textureInput->value());
+ config->writeEntry("SharpnessAjustment", m_sharpnessInput->value());
+ config->writeEntry("CsmoothAjustment", m_csmoothInput->value());
+ config->writeEntry("LookAheadAjustment", m_lookaheadInput->value());
+ config->writeEntry("GammaAjustment", m_gammaInput->value());
+ config->writeEntry("DampingAjustment", m_dampingInput->value());
+ config->writeEntry("PhaseAjustment", m_phaseInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void NoiseReductionTool::slotResetSettings()
+{
+ m_radiusInput->setEnabled(true);
+ m_lumToleranceInput->setEnabled(true);
+ m_thresholdInput->setEnabled(true);
+ m_textureInput->setEnabled(true);
+ m_sharpnessInput->setEnabled(true);
+ m_csmoothInput->setEnabled(true);
+ m_lookaheadInput->setEnabled(true);
+ m_gammaInput->setEnabled(true);
+ m_dampingInput->setEnabled(true);
+ m_phaseInput->setEnabled(true);
+
+ m_radiusInput->slotReset();
+ m_lumToleranceInput->slotReset();
+ m_thresholdInput->slotReset();
+ m_textureInput->slotReset();
+ m_sharpnessInput->slotReset();
+ m_csmoothInput->slotReset();
+ m_lookaheadInput->slotReset();
+ m_gammaInput->slotReset();
+ m_dampingInput->slotReset();
+ m_phaseInput->slotReset();
+
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+}
+
+void NoiseReductionTool::prepareEffect()
+{
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ double r = m_radiusInput->value();
+ double l = m_lumToleranceInput->value();
+ double th = m_thresholdInput->value();
+ double tx = m_textureInput->value();
+ double s = m_sharpnessInput->value();
+ double c = m_csmoothInput->value();
+ double a = m_lookaheadInput->value();
+ double g = m_gammaInput->value();
+ double d = m_dampingInput->value();
+ double p = m_phaseInput->value();
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new NoiseReduction(&image, this, r, l, th, tx, s, c, a, g, d, p)));
+}
+
+void NoiseReductionTool::prepareFinal()
+{
+ m_radiusInput->setEnabled(false);
+ m_lumToleranceInput->setEnabled(false);
+ m_thresholdInput->setEnabled(false);
+ m_textureInput->setEnabled(false);
+ m_sharpnessInput->setEnabled(false);
+ m_csmoothInput->setEnabled(false);
+ m_lookaheadInput->setEnabled(false);
+ m_gammaInput->setEnabled(false);
+ m_dampingInput->setEnabled(false);
+ m_phaseInput->setEnabled(false);
+
+ double r = m_radiusInput->value();
+ double l = m_lumToleranceInput->value();
+ double th = m_thresholdInput->value();
+ double tx = m_textureInput->value();
+ double s = m_sharpnessInput->value();
+ double c = m_csmoothInput->value();
+ double a = m_lookaheadInput->value();
+ double g = m_gammaInput->value();
+ double d = m_dampingInput->value();
+ double p = m_phaseInput->value();
+
+ ImageIface iface(0, 0);
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new NoiseReduction(iface.getOriginalImg(), this, r, l, th, tx, s, c, a, g, d, p)));
+}
+
+void NoiseReductionTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void NoiseReductionTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Noise Reduction"), filter()->getTargetImage().bits());
+}
+
+void NoiseReductionTool::slotLoadSettings()
+{
+ KURL loadRestorationFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Noise Reduction Settings File to Load")) );
+ if ( loadRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(loadRestorationFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+ if ( stream.readLine() != "# Photograph Noise Reduction Configuration File" )
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" is not a Photograph Noise Reduction settings text file.")
+ .arg(loadRestorationFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+ m_radiusInput->setValue( stream.readLine().toDouble() );
+ m_lumToleranceInput->setValue( stream.readLine().toDouble() );
+ m_thresholdInput->setValue( stream.readLine().toDouble() );
+ m_textureInput->setValue( stream.readLine().toDouble() );
+ m_sharpnessInput->setValue( stream.readLine().toDouble() );
+ m_csmoothInput->setValue( stream.readLine().toDouble() );
+ m_lookaheadInput->setValue( stream.readLine().toDouble() );
+ m_gammaInput->setValue( stream.readLine().toDouble() );
+ m_dampingInput->setValue( stream.readLine().toDouble() );
+ m_phaseInput->setValue( stream.readLine().toDouble() );
+ blockSignals(false);
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot load settings from the Photograph Noise Reduction text file."));
+
+ file.close();
+}
+
+void NoiseReductionTool::slotSaveAsSettings()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Noise Reduction Settings File to Save")) );
+ if ( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# Photograph Noise Reduction Configuration File\n";
+ stream << m_radiusInput->value() << "\n";
+ stream << m_lumToleranceInput->value() << "\n";
+ stream << m_thresholdInput->value() << "\n";
+ stream << m_textureInput->value() << "\n";
+ stream << m_sharpnessInput->value() << "\n";
+ stream << m_csmoothInput->value() << "\n";
+ stream << m_lookaheadInput->value() << "\n";
+ stream << m_gammaInput->value() << "\n";
+ stream << m_dampingInput->value() << "\n";
+ stream << m_phaseInput->value() << "\n";
+
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot save settings to the Photograph Noise Reduction text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
diff --git a/src/imageplugins/noisereduction/noisereductiontool.h b/src/imageplugins/noisereduction/noisereductiontool.h
new file mode 100644
index 00000000..8d7d5828
--- /dev/null
+++ b/src/imageplugins/noisereduction/noisereductiontool.h
@@ -0,0 +1,92 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-24
+ * Description : a plugin to reduce CCD noise.
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef NOISEREDUCTIONTOOL_H
+#define NOISEREDUCTIONTOOL_H
+
+// Local includes.
+
+#include "editortool.h"
+
+namespace KDcrawIface
+{
+class RDoubleNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamNoiseReductionImagesPlugin
+{
+
+class NoiseReductionTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ NoiseReductionTool(TQObject* parent);
+ ~NoiseReductionTool();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private slots:
+
+ void slotSaveAsSettings();
+ void slotLoadSettings();
+ void slotResetSettings();
+
+private:
+
+ KDcrawIface::RDoubleNumInput *m_radiusInput;
+ KDcrawIface::RDoubleNumInput *m_lumToleranceInput;
+ KDcrawIface::RDoubleNumInput *m_thresholdInput;
+ KDcrawIface::RDoubleNumInput *m_textureInput;
+ KDcrawIface::RDoubleNumInput *m_sharpnessInput;
+
+ KDcrawIface::RDoubleNumInput *m_csmoothInput;
+ KDcrawIface::RDoubleNumInput *m_lookaheadInput;
+ KDcrawIface::RDoubleNumInput *m_gammaInput;
+ KDcrawIface::RDoubleNumInput *m_dampingInput;
+ KDcrawIface::RDoubleNumInput *m_phaseInput;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamNoiseReductionImagesPlugin
+
+#endif /* NOISEREDUCTIONTOOL_H */
diff --git a/src/imageplugins/oilpaint/Makefile.am b/src/imageplugins/oilpaint/Makefile.am
new file mode 100644
index 00000000..f50d7408
--- /dev/null
+++ b/src/imageplugins/oilpaint/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_oilpaint_la_SOURCES = imageplugin_oilpaint.cpp \
+ oilpainttool.cpp oilpaint.cpp
+
+digikamimageplugin_oilpaint_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_oilpaint_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_oilpaint.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_oilpaint.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_oilpaint_ui.rc
+
diff --git a/src/imageplugins/oilpaint/digikamimageplugin_oilpaint.desktop b/src/imageplugins/oilpaint/digikamimageplugin_oilpaint.desktop
new file mode 100644
index 00000000..875c7f16
--- /dev/null
+++ b/src/imageplugins/oilpaint/digikamimageplugin_oilpaint.desktop
@@ -0,0 +1,51 @@
+[Desktop Entry]
+Name=ImagePlugin_OilPaint
+Name[bg]=Приставка за снимки - Маслени бои
+Name[da]=Billedplugin_Oliemaling
+Name[el]=ΠρόσθετοΕικόνας_Ελαιογραφίας
+Name[fi]=Öljyvärimaalaus
+Name[hr]=Uljana slika
+Name[it]=PluginImmagini_PitturaAOlio
+Name[nl]=Afbeeldingsplugin_Olieverf
+Name[sr]=Слика у уљу
+Name[sr@Latn]=Slika u ulju
+Name[sv]=Insticksprogram för oljemålning
+Name[tr]=ResimEklentisi_YağlıBoya
+Name[xx]=xxImagePlugin_OilPaintxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Oil paint image effect plugin for digiKam
+Comment[bg]=Приставка на digiKam за наподобяване на картина с маслени бои
+Comment[ca]=Connector pel digiKam d'efecte de pintura a l'oli
+Comment[da]=Plugin med oliemalingeffekt på billeder i Digikam
+Comment[de]=digiKam-Modul zum Erzeugen eines Ölgemäldeeffektes
+Comment[el]=Πρόσθετο ελαιογραφίας για το digiKam
+Comment[es]=Plugin para digiKam con efectos de pintura al óleo
+Comment[et]=DigiKami õlimaali pildiefektiplugin
+Comment[fa]=وصلۀ جلوۀ تصویر رنگ روغن برای digiKam
+Comment[fi]=Jäljittelee öljyvärimaalausta
+Comment[gl]=Un plugin de digiKam para simular unha pintura ao óleo
+Comment[hr]=digiKam dodatak za efekt uljane slike
+Comment[is]=Íforrit fyrir digiKam sem líkir eftir olíumálun
+Comment[it]=Plugin per l'effetto di pittura a olio delle immagini per digiKam
+Comment[ja]=digiKam 油絵効果プラグイン
+Comment[ms]=Plugin kesan imej cat minyak untuk digiKam
+Comment[nds]=digiKam-Moduul för Öölbildeffekten
+Comment[nl]=Digikam-plugin voor olieverfafbeeldingen
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਤੇਲ ਪੇਂਟ ਚਿੱਤਰ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam zmniejszająca szum
+Comment[pt]=Um 'plugin' do digiKam para simular uma pintura a óleo
+Comment[pt_BR]=Plugin de efeito de condensar cor da imagem
+Comment[ru]=Модуль эффект "маслянной краски" для digiKam
+Comment[sk]=digiKam plugin pre efekt olejomaľby
+Comment[sr]=digiKam-ов прикључак за ефекат слике у уљу
+Comment[sr@Latn]=digiKam-ov priključak za efekat slike u ulju
+Comment[sv]=Digikam insticksprogram för oljemålningsbildeffekt
+Comment[tr]=digiKam için resmi yağlıboyaya benzetme eklentisi
+Comment[uk]=Втулок створення ефекту олійних фарб для digiKam
+Comment[vi]=Phần bổ sung hiệu ứng ảnh sơn dầu cho digiKam
+Comment[xx]=xxOil paint image effect plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_oilpaint
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/oilpaint/digikamimageplugin_oilpaint_ui.rc b/src/imageplugins/oilpaint/digikamimageplugin_oilpaint_ui.rc
new file mode 100644
index 00000000..864c09db
--- /dev/null
+++ b/src/imageplugins/oilpaint/digikamimageplugin_oilpaint_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_oilpaint" >
+
+ <MenuBar>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_oilpaint" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_oilpaint" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/oilpaint/imageeffect_oilpaint.cpp b/src/imageplugins/oilpaint/imageeffect_oilpaint.cpp
new file mode 100644
index 00000000..da07be05
--- /dev/null
+++ b/src/imageplugins/oilpaint/imageeffect_oilpaint.cpp
@@ -0,0 +1,201 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-25
+ * Description : a plugin to simulate Oil Painting
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqimage.h>
+#include <tqlayout.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "oilpaint.h"
+#include "imageeffect_oilpaint.h"
+#include "imageeffect_oilpaint.moc"
+
+namespace DigikamOilPaintImagesPlugin
+{
+
+ImageEffect_OilPaint::ImageEffect_OilPaint(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Apply Oil Paint Effect"),
+ "oilpaint", false, false, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Oil Paint"),
+ digikam_version,
+ I18N_NOOP("An oil painting image effect plugin for digiKam."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2005, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://wwww.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Pieter Z. Voloshyn", I18N_NOOP("Oil paint algorithm"),
+ "pieter dot voloshyn at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 3, 1, 0, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Brush size:"), gboxSettings);
+ m_brushSizeInput = new KIntNumInput(gboxSettings);
+ m_brushSizeInput->setRange(1, 5, 1, true);
+ TQWhatsThis::add( m_brushSizeInput, i18n("<p>Set here the brush size to use for "
+ "simulating the oil painting.") );
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_brushSizeInput, 1, 1, 0, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Smooth:"), gboxSettings);
+ m_smoothInput = new KIntNumInput(gboxSettings);
+ m_smoothInput->setRange(10, 255, 1, true);
+ TQWhatsThis::add( m_smoothInput, i18n("<p>This value controls the smoothing effect "
+ "of the brush under the canvas.") );
+
+ gridSettings->addMultiCellWidget(label2, 2, 2, 0, 1);
+ gridSettings->addMultiCellWidget(m_smoothInput, 3, 3, 0, 1);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_brushSizeInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_smoothInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_OilPaint::~ImageEffect_OilPaint()
+{
+}
+
+void ImageEffect_OilPaint::renderingFinished()
+{
+ m_brushSizeInput->setEnabled(true);
+ m_smoothInput->setEnabled(true);
+}
+
+void ImageEffect_OilPaint::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("oilpaint Tool Dialog");
+ m_brushSizeInput->blockSignals(true);
+ m_smoothInput->blockSignals(true);
+ m_brushSizeInput->setValue(config->readNumEntry("BrushSize", 1));
+ m_smoothInput->setValue(config->readNumEntry("SmoothAjustment", 30));
+ m_brushSizeInput->blockSignals(false);
+ m_smoothInput->blockSignals(false);
+}
+
+void ImageEffect_OilPaint::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("oilpaint Tool Dialog");
+ config->writeEntry("BrushSize", m_brushSizeInput->value());
+ config->writeEntry("SmoothAjustment", m_smoothInput->value());
+ config->sync();
+}
+
+void ImageEffect_OilPaint::resetValues()
+{
+ m_brushSizeInput->blockSignals(true);
+ m_smoothInput->blockSignals(true);
+ m_brushSizeInput->setValue(1);
+ m_smoothInput->setValue(30);
+ m_brushSizeInput->blockSignals(false);
+ m_smoothInput->blockSignals(false);
+}
+
+void ImageEffect_OilPaint::prepareEffect()
+{
+ m_brushSizeInput->setEnabled(false);
+ m_smoothInput->setEnabled(false);
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+
+ int b = m_brushSizeInput->value();
+ int s = m_smoothInput->value();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new OilPaint(&image, this, b, s));
+}
+
+void ImageEffect_OilPaint::prepareFinal()
+{
+ m_brushSizeInput->setEnabled(false);
+ m_smoothInput->setEnabled(false);
+
+ int b = m_brushSizeInput->value();
+ int s = m_smoothInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(new OilPaint(iface.getOriginalImg(), this, b, s));
+}
+
+void ImageEffect_OilPaint::putPreviewData(void)
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_OilPaint::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Oil Paint"),
+ m_threadedFilter->getTargetImage().bits());
+}
+
+} // NameSpace DigikamOilPaintImagesPlugin
+
diff --git a/src/imageplugins/oilpaint/imageeffect_oilpaint.h b/src/imageplugins/oilpaint/imageeffect_oilpaint.h
new file mode 100644
index 00000000..527cc2ef
--- /dev/null
+++ b/src/imageplugins/oilpaint/imageeffect_oilpaint.h
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-25
+ * Description : a plugin to simulate Oil Painting
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_OILPAINT_H
+#define IMAGEEFFECT_OILPAINT_H
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+class KIntNumInput;
+
+namespace DigikamOilPaintImagesPlugin
+{
+
+class ImageEffect_OilPaint : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_OilPaint(TQWidget* parent);
+ ~ImageEffect_OilPaint();
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KIntNumInput *m_brushSizeInput;
+ KIntNumInput *m_smoothInput;
+};
+
+} // NameSpace DigikamOilPaintImagesPlugin
+
+#endif /* IMAGEEFFECT_OILPAINT_H */
diff --git a/src/imageplugins/oilpaint/imageplugin_oilpaint.cpp b/src/imageplugins/oilpaint/imageplugin_oilpaint.cpp
new file mode 100644
index 00000000..740e89fc
--- /dev/null
+++ b/src/imageplugins/oilpaint/imageplugin_oilpaint.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-25
+ * Description : a plugin to simulate Oil Painting
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "oilpainttool.h"
+#include "imageplugin_oilpaint.h"
+#include "imageplugin_oilpaint.moc"
+
+using namespace DigikamOilPaintImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_oilpaint,
+ KGenericFactory<ImagePlugin_OilPaint>("digikamimageplugin_oilpaint"));
+
+ImagePlugin_OilPaint::ImagePlugin_OilPaint(TQObject *parent, const char*, const TQStringList&)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_OilPaint")
+{
+ m_oilpaintAction = new TDEAction(i18n("Oil Paint..."), "oilpaint", 0,
+ this, TQ_SLOT(slotOilPaint()),
+ actionCollection(), "imageplugin_oilpaint");
+
+ setXMLFile( "digikamimageplugin_oilpaint_ui.rc" );
+
+ DDebug() << "ImagePlugin_OilPaint plugin loaded" << endl;
+}
+
+ImagePlugin_OilPaint::~ImagePlugin_OilPaint()
+{
+}
+
+void ImagePlugin_OilPaint::setEnabledActions(bool enable)
+{
+ m_oilpaintAction->setEnabled(enable);
+}
+
+void ImagePlugin_OilPaint::slotOilPaint()
+{
+ OilPaintTool *tool = new OilPaintTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/oilpaint/imageplugin_oilpaint.h b/src/imageplugins/oilpaint/imageplugin_oilpaint.h
new file mode 100644
index 00000000..032ee065
--- /dev/null
+++ b/src/imageplugins/oilpaint/imageplugin_oilpaint.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-25
+ * Description : a plugin to simulate Oil Painting
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_OILPAINT_H
+#define IMAGEPLUGIN_OILPAINT_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_OilPaint : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_OilPaint(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_OilPaint();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotOilPaint();
+
+private:
+
+ TDEAction *m_oilpaintAction;
+};
+
+#endif /* IMAGEPLUGIN_OILPAINT_H */
diff --git a/src/imageplugins/oilpaint/oilpaint.cpp b/src/imageplugins/oilpaint/oilpaint.cpp
new file mode 100644
index 00000000..be9697fa
--- /dev/null
+++ b/src/imageplugins/oilpaint/oilpaint.cpp
@@ -0,0 +1,203 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Oil Painting threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original OilPaint algorithm copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimggaussianblur.h"
+#include "dimgimagefilters.h"
+#include "oilpaint.h"
+
+namespace DigikamOilPaintImagesPlugin
+{
+
+OilPaint::OilPaint(Digikam::DImg *orgImage, TQObject *parent, int brushSize, int smoothness)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "OilPaint")
+{
+ m_brushSize = brushSize;
+ m_smoothness = smoothness;
+ initFilter();
+}
+
+void OilPaint::filterImage(void)
+{
+ oilpaintImage(m_orgImage, m_destImage, m_brushSize, m_smoothness);
+}
+
+// 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 OilPaint::oilpaintImage(Digikam::DImg &orgImage, Digikam::DImg &destImage, int BrushSize, int Smoothness)
+{
+ int progress;
+ Digikam::DColor mostFrequentColor;
+ int w,h;
+
+ mostFrequentColor.setSixteenBit(orgImage.sixteenBit());
+ w = (int)orgImage.width();
+ h = (int)orgImage.height();
+ uchar *dest = destImage.bits();
+ int bytesDepth = orgImage.bytesDepth();
+ uchar *dptr;
+
+ // Allocate some arrays to be used.
+ // Do this here once for all to save a few million new / delete operations
+ m_intensityCount = new uchar[Smoothness + 1];
+ m_averageColorR = new uint[Smoothness + 1];
+ m_averageColorG = new uint[Smoothness + 1];
+ m_averageColorB = new uint[Smoothness + 1];
+
+ for (int h2 = 0; !m_cancel && (h2 < h); h2++)
+ {
+ for (int w2 = 0; !m_cancel && (w2 < w); w2++)
+ {
+ mostFrequentColor = MostFrequentColor(orgImage, w2, h2, BrushSize, Smoothness);
+ dptr = dest + w2*bytesDepth + (w*h2*bytesDepth);
+ mostFrequentColor.setPixel(dptr);
+ }
+
+ progress = (int) (((double)h2 * 100.0) / h);
+ if ( progress%5 == 0 )
+ postProgress( progress );
+ }
+
+ // free all the arrays
+ delete [] m_intensityCount;
+ delete [] m_averageColorR;
+ delete [] m_averageColorG;
+ delete [] m_averageColorB;
+}
+
+// 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
+ */
+
+Digikam::DColor OilPaint::MostFrequentColor(Digikam::DImg &src, int X, int Y, int Radius, int Intensity)
+{
+ int i, w, h, I, Width, Height;
+ uint red, green, blue;
+
+ uchar *dest = src.bits();
+ int bytesDepth = src.bytesDepth();
+ uchar *sptr;
+ bool sixteenBit = src.sixteenBit();
+
+ Digikam::DColor mostFrequentColor;
+
+ double Scale = Intensity / (sixteenBit ? 65535.0 : 255.0);
+ Width = (int)src.width();
+ Height = (int)src.height();
+
+ // Erase the array
+ memset(m_intensityCount, 0, (Intensity + 1) * sizeof (uchar));
+
+ for (w = X - Radius; w <= X + Radius; w++)
+ {
+ for (h = Y - Radius; h <= Y + Radius; h++)
+ {
+ // This condition helps to identify when a point doesn't exist
+
+ if ((w >= 0) && (w < Width) && (h >= 0) && (h < Height))
+ {
+ sptr = dest + w*bytesDepth + (Width*h*bytesDepth);
+ Digikam::DColor color(sptr, sixteenBit);
+ red = (uint)color.red();
+ green = (uint)color.green();
+ blue = (uint)color.blue();
+
+ I = lround(GetIntensity (red, green, blue) * Scale);
+ m_intensityCount[I]++;
+
+ if (m_intensityCount[I] == 1)
+ {
+ m_averageColorR[I] = red;
+ m_averageColorG[I] = green;
+ m_averageColorB[I] = blue;
+ }
+ else
+ {
+ m_averageColorR[I] += red;
+ m_averageColorG[I] += green;
+ m_averageColorB[I] += blue;
+ }
+ }
+ }
+ }
+
+ I = 0;
+ int MaxInstance = 0;
+
+ for (i = 0 ; i <= Intensity ; i++)
+ {
+ if (m_intensityCount[i] > MaxInstance)
+ {
+ I = i;
+ MaxInstance = m_intensityCount[i];
+ }
+ }
+
+ // get Alpha channel value from original (unchanged)
+ mostFrequentColor = src.getPixelColor(X, Y);
+
+ // Overwrite RGB values to destination.
+ mostFrequentColor.setRed(m_averageColorR[I] / MaxInstance);
+ mostFrequentColor.setGreen(m_averageColorG[I] / MaxInstance);
+ mostFrequentColor.setBlue(m_averageColorB[I] / MaxInstance);
+
+ return mostFrequentColor;
+}
+
+} // NameSpace DigikamOilPaintImagesPlugin
diff --git a/src/imageplugins/oilpaint/oilpaint.h b/src/imageplugins/oilpaint/oilpaint.h
new file mode 100644
index 00000000..998522a5
--- /dev/null
+++ b/src/imageplugins/oilpaint/oilpaint.h
@@ -0,0 +1,72 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Oil Painting threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef OILPAINT_H
+#define OILPAINT_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamOilPaintImagesPlugin
+{
+
+class OilPaint : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ OilPaint(Digikam::DImg *orgImage, TQObject *parent=0, int brushSize=1, int smoothness=30);
+
+ ~OilPaint(){};
+
+private:
+
+ virtual void filterImage(void);
+
+ void oilpaintImage(Digikam::DImg &orgImage, Digikam::DImg &destImage, int BrushSize, int Smoothness);
+
+ Digikam::DColor MostFrequentColor (Digikam::DImg &src,
+ int X, int Y, int Radius, int Intensity);
+
+ // Function to calculate the color intensity and return the luminance (Y)
+ // component of YIQ color model.
+ inline double GetIntensity(uint Red, uint Green, uint Blue)
+ { return Red * 0.3 + Green * 0.59 + Blue * 0.11; };
+
+private:
+
+ uchar *m_intensityCount;
+
+ int m_brushSize;
+ int m_smoothness;
+
+ uint *m_averageColorR;
+ uint *m_averageColorG;
+ uint *m_averageColorB;
+};
+
+} // NameSpace DigikamOilPaintImagesPlugin
+
+#endif /* OILPAINT_H */
diff --git a/src/imageplugins/oilpaint/oilpainttool.cpp b/src/imageplugins/oilpaint/oilpainttool.cpp
new file mode 100644
index 00000000..25bea302
--- /dev/null
+++ b/src/imageplugins/oilpaint/oilpainttool.cpp
@@ -0,0 +1,208 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-25
+ * Description : a plugin to simulate Oil Painting
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "oilpaint.h"
+#include "oilpainttool.h"
+#include "oilpainttool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamOilPaintImagesPlugin
+{
+
+OilPaintTool::OilPaintTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("oilpaint");
+ setToolName(i18n("Oil Paint"));
+ setToolIcon(SmallIcon("oilpaint"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 4, 1);
+
+ TQLabel *label1 = new TQLabel(i18n("Brush size:"), m_gboxSettings->plainPage());
+ m_brushSizeInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_brushSizeInput->setRange(1, 5, 1);
+ m_brushSizeInput->setDefaultValue(1);
+ TQWhatsThis::add( m_brushSizeInput, i18n("<p>Set here the brush size to use for "
+ "simulating the oil painting.") );
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Smooth:"), m_gboxSettings->plainPage());
+ m_smoothInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_smoothInput->setRange(10, 255, 1);
+ m_smoothInput->setDefaultValue(30);
+ TQWhatsThis::add( m_smoothInput, i18n("<p>This value controls the smoothing effect "
+ "of the brush under the canvas.") );
+
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 1);
+ grid->addMultiCellWidget(m_brushSizeInput, 1, 1, 0, 1);
+ grid->addMultiCellWidget(label2, 2, 2, 0, 1);
+ grid->addMultiCellWidget(m_smoothInput, 3, 3, 0, 1);
+ grid->setRowStretch(4, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "oilpaint Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ // this filter is relative slow, so we should use the try button instead right now
+
+ // connect(m_brushSizeInput, TQ_SIGNAL(valueChanged (int)),
+ // this, TQ_SLOT(slotTimer()));
+ //
+ // connect(m_smoothInput, TQ_SIGNAL(valueChanged (int)),
+ // this, TQ_SLOT(slotTimer()));
+}
+
+OilPaintTool::~OilPaintTool()
+{
+}
+
+void OilPaintTool::renderingFinished()
+{
+ m_brushSizeInput->setEnabled(true);
+ m_smoothInput->setEnabled(true);
+}
+
+void OilPaintTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("oilpaint Tool");
+ m_brushSizeInput->blockSignals(true);
+ m_smoothInput->blockSignals(true);
+
+ m_brushSizeInput->setValue(config->readNumEntry("BrushSize", m_brushSizeInput->defaultValue()));
+ m_smoothInput->setValue(config->readNumEntry("SmoothAjustment", m_smoothInput->defaultValue()));
+
+ m_brushSizeInput->blockSignals(false);
+ m_smoothInput->blockSignals(false);
+}
+
+void OilPaintTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("oilpaint Tool");
+ config->writeEntry("BrushSize", m_brushSizeInput->value());
+ config->writeEntry("SmoothAjustment", m_smoothInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void OilPaintTool::slotResetSettings()
+{
+ m_brushSizeInput->blockSignals(true);
+ m_smoothInput->blockSignals(true);
+
+ m_brushSizeInput->slotReset();
+ m_smoothInput->slotReset();
+
+ m_brushSizeInput->blockSignals(false);
+ m_smoothInput->blockSignals(false);
+}
+
+void OilPaintTool::prepareEffect()
+{
+ m_brushSizeInput->setEnabled(false);
+ m_smoothInput->setEnabled(false);
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+
+ int b = m_brushSizeInput->value();
+ int s = m_smoothInput->value();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new OilPaint(&image, this, b, s)));
+}
+
+void OilPaintTool::prepareFinal()
+{
+ m_brushSizeInput->setEnabled(false);
+ m_smoothInput->setEnabled(false);
+
+ int b = m_brushSizeInput->value();
+ int s = m_smoothInput->value();
+
+ ImageIface iface(0, 0);
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new OilPaint(iface.getOriginalImg(), this, b, s)));
+}
+
+void OilPaintTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void OilPaintTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Oil Paint"), filter()->getTargetImage().bits());
+}
+
+} // NameSpace DigikamOilPaintImagesPlugin
+
diff --git a/src/imageplugins/oilpaint/oilpainttool.h b/src/imageplugins/oilpaint/oilpainttool.h
new file mode 100644
index 00000000..9c488a57
--- /dev/null
+++ b/src/imageplugins/oilpaint/oilpainttool.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-08-25
+ * Description : a plugin to simulate Oil Painting
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef OILPAINTTOOL_H
+#define OILPAINTTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamOilPaintImagesPlugin
+{
+
+class OilPaintTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ OilPaintTool(TQObject* parent);
+ ~OilPaintTool();
+
+private slots:
+
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KDcrawIface::RIntNumInput *m_brushSizeInput;
+ KDcrawIface::RIntNumInput *m_smoothInput;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamOilPaintImagesPlugin
+
+#endif /* OILPAINTTOOL_H */
diff --git a/src/imageplugins/perspective/Makefile.am b/src/imageplugins/perspective/Makefile.am
new file mode 100644
index 00000000..028add37
--- /dev/null
+++ b/src/imageplugins/perspective/Makefile.am
@@ -0,0 +1,35 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_perspective_la_SOURCES = imageplugin_perspective.cpp \
+ perspectivetool.cpp \
+ perspectivewidget.cpp triangle.cpp matrix.cpp
+
+digikamimageplugin_perspective_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_perspective_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_perspective.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_perspective.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_perspective_ui.rc
+
diff --git a/src/imageplugins/perspective/digikamimageplugin_perspective.desktop b/src/imageplugins/perspective/digikamimageplugin_perspective.desktop
new file mode 100644
index 00000000..a6fcc4d3
--- /dev/null
+++ b/src/imageplugins/perspective/digikamimageplugin_perspective.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_Perspective
+Name[bg]=Приставка за снимки - Перспектива
+Name[da]=Billedplugin_Perspektivværktøj
+Name[el]=ΠρόσθετοΕικόνας_Προοπτική
+Name[fi]=Perspektiivimuunnos
+Name[hr]=Perspektiva
+Name[it]=PluginImmagini_Prospettiva
+Name[nl]=Afbeeldingsplugin_Perspectief
+Name[sr]=Перспектива
+Name[sr@Latn]=Perspektiva
+Name[sv]=Insticksprogram för perspektiv
+Name[tr]=ResimEklentisi_Perspektif
+Name[xx]=xxImagePlugin_Perspectivexx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Perspective tool plugin for digiKam
+Comment[bg]=Приставка на digiKam за промяна на перспективата
+Comment[ca]=Connector pel digiKam d'eina de perspectiva
+Comment[da]=Perspektivværktøjs-plugin for Digikam
+Comment[de]=digiKam-Modul zum Justieren der Perspektive eines Bildes
+Comment[el]=Πρόσθετο εργαλείο προοπτικής για το digiKam
+Comment[es]=Plugin para digiKam de herramientas de perspectiva
+Comment[et]=DigiKami perspektiiviplugin
+Comment[fa]=وصلۀ ابزار منظره برای digiKam
+Comment[fi]=Vääristää kuvan perspektiiviä
+Comment[fr]=Module externe pour modifier la perspective dans digiKam
+Comment[gl]=Un plugin de digiKam para a ferramenta de perspectiva
+Comment[hr]=digiKam dodatak za perspektivu
+Comment[it]=Plugin per lo strumento di prospettiva per digiKam
+Comment[ja]=digiKam 視点調整プラグイン
+Comment[ms]=Plugin alatan perspektif untuk digiKam
+Comment[nds]=digiKam-Moduul för den Kietwinkel
+Comment[nl]=Digikam-plugin voor perspectiefaanpassing
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਪਰੋਸਪੈਕਟਿਵ ਸੰਦ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam umożliwiająca korekcję perspektywy
+Comment[pt]=Um 'plugin' do digiKam para a ferramenta de perspectiva
+Comment[pt_BR]=Plugin de ferramenta de Perspectiva
+Comment[ru]=Модуль изменения перспективы для digiKam
+Comment[sk]=digiKam plugin pre nástroj s perspektívou
+Comment[sr]=digiKam-ов прикључак за перспективу
+Comment[sr@Latn]=digiKam-ov priključak za perspektivu
+Comment[sv]=Digikam insticksprogram med perspektivverktyg
+Comment[tr]=digiKam için perspektif aracı eklentisi
+Comment[uk]=Втулок засобу побудови перспективи для digiKam
+Comment[vi]=Phần bổ sung công cụ phối cảnh cho digiKam
+Comment[xx]=xxPerspective tool plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_perspective
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/perspective/digikamimageplugin_perspective_ui.rc b/src/imageplugins/perspective/digikamimageplugin_perspective_ui.rc
new file mode 100644
index 00000000..0f3bca57
--- /dev/null
+++ b/src/imageplugins/perspective/digikamimageplugin_perspective_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="4" name="digikamimageplugin_perspective" >
+
+ <MenuBar>
+
+ <Menu name="Transform" ><text>Tra&amp;nsform</text>
+ <Action name="imageplugin_perspective" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_perspective" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/perspective/imageeffect_perspective.cpp b/src/imageplugins/perspective/imageeffect_perspective.cpp
new file mode 100644
index 00000000..15bef877
--- /dev/null
+++ b/src/imageplugins/perspective/imageeffect_perspective.cpp
@@ -0,0 +1,252 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective .
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqspinbox.h>
+#include <tqpushbutton.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqcheckbox.h>
+
+// KDE includes.
+
+#include <kcolorbutton.h>
+#include <kcursor.h>
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <kseparator.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "perspectivewidget.h"
+#include "imageeffect_perspective.h"
+#include "imageeffect_perspective.moc"
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+ImageEffect_Perspective::ImageEffect_Perspective(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Adjust Photograph Perspective"),
+ "perspective", false, false)
+{
+ TQString whatsThis;
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Perspective"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to process image perspective adjustment."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2006, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(plainPage());
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* l = new TQVBoxLayout(frame, 5, 0);
+ m_previewWidget = new PerspectiveWidget(525, 350, frame);
+ l->addWidget(m_previewWidget);
+ TQWhatsThis::add( m_previewWidget, i18n("<p>This is the perspective transformation operation preview. "
+ "You can use the mouse for dragging the corner to adjust the "
+ "perspective transformation area."));
+ setPreviewAreaWidget(frame);
+
+ // -------------------------------------------------------------
+
+ TQString temp;
+ Digikam::ImageIface iface(0, 0);
+
+ TQWidget *gbox2 = new TQWidget(plainPage());
+ TQGridLayout *gridLayout = new TQGridLayout( gbox2, 13, 2, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("New width:"), gbox2);
+ m_newWidthLabel = new TQLabel(temp.setNum( iface.originalWidth()) + i18n(" px"), gbox2);
+ m_newWidthLabel->setAlignment( AlignBottom | AlignRight );
+
+ TQLabel *label2 = new TQLabel(i18n("New height:"), gbox2);
+ m_newHeightLabel = new TQLabel(temp.setNum( iface.originalHeight()) + i18n(" px"), gbox2);
+ m_newHeightLabel->setAlignment( AlignBottom | AlignRight );
+
+ gridLayout->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridLayout->addMultiCellWidget(m_newWidthLabel, 0, 0, 1, 2);
+ gridLayout->addMultiCellWidget(label2, 1, 1, 0, 0);
+ gridLayout->addMultiCellWidget(m_newHeightLabel, 1, 1, 1, 2);
+
+ // -------------------------------------------------------------
+
+ KSeparator *line = new KSeparator(Horizontal, gbox2);
+
+ TQLabel *angleLabel = new TQLabel(i18n("Angles (in degrees):"), gbox2);
+ TQLabel *label3 = new TQLabel(i18n(" Top left:"), gbox2);
+ m_topLeftAngleLabel = new TQLabel(gbox2);
+ TQLabel *label4 = new TQLabel(i18n(" Top right:"), gbox2);
+ m_topRightAngleLabel = new TQLabel(gbox2);
+ TQLabel *label5 = new TQLabel(i18n(" Bottom left:"), gbox2);
+ m_bottomLeftAngleLabel = new TQLabel(gbox2);
+ TQLabel *label6 = new TQLabel(i18n(" Bottom right:"), gbox2);
+ m_bottomRightAngleLabel = new TQLabel(gbox2);
+
+ gridLayout->addMultiCellWidget(line, 2, 2, 0, 2);
+ gridLayout->addMultiCellWidget(angleLabel, 3, 3, 0, 2);
+ gridLayout->addMultiCellWidget(label3, 4, 4, 0, 0);
+ gridLayout->addMultiCellWidget(m_topLeftAngleLabel, 4, 4, 1, 2);
+ gridLayout->addMultiCellWidget(label4, 5, 5, 0, 0);
+ gridLayout->addMultiCellWidget(m_topRightAngleLabel, 5, 5, 1, 2);
+ gridLayout->addMultiCellWidget(label5, 6, 6, 0, 0);
+ gridLayout->addMultiCellWidget(m_bottomLeftAngleLabel, 6, 6, 1, 2);
+ gridLayout->addMultiCellWidget(label6, 7, 7, 0, 0);
+ gridLayout->addMultiCellWidget(m_bottomRightAngleLabel, 7, 7, 1, 2);
+
+ // -------------------------------------------------------------
+
+ KSeparator *line2 = new KSeparator(Horizontal, gbox2);
+
+ m_drawWhileMovingCheckBox = new TQCheckBox(i18n("Draw preview while moving"), gbox2);
+ gridLayout->addMultiCellWidget(line2, 8, 8, 0, 2);
+ gridLayout->addMultiCellWidget(m_drawWhileMovingCheckBox, 9, 9, 0, 2);
+
+ m_drawGridCheckBox = new TQCheckBox(i18n("Draw grid"), gbox2);
+ gridLayout->addMultiCellWidget(m_drawGridCheckBox, 10, 10, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label7 = new TQLabel(i18n("Guide color:"), gbox2);
+ m_guideColorBt = new KColorButton( TQColor( TQt::red ), gbox2 );
+ TQWhatsThis::add( m_guideColorBt, i18n("<p>Set here the color used to draw guides dashed-lines."));
+ gridLayout->addMultiCellWidget(label7, 11, 11, 0, 0);
+ gridLayout->addMultiCellWidget(m_guideColorBt, 11, 11, 2, 2);
+
+ TQLabel *label8 = new TQLabel(i18n("Guide width:"), gbox2);
+ m_guideSize = new TQSpinBox( 1, 5, 1, gbox2);
+ TQWhatsThis::add( m_guideSize, i18n("<p>Set here the width in pixels used to draw guides dashed-lines."));
+ gridLayout->addMultiCellWidget(label8, 12, 12, 0, 0);
+ gridLayout->addMultiCellWidget(m_guideSize, 12, 12, 2, 2);
+
+ gridLayout->setColStretch(1, 10);
+ gridLayout->setRowStretch(13, 10);
+
+ setUserAreaWidget(gbox2);
+
+ // -------------------------------------------------------------
+
+ connect(m_previewWidget, TQ_SIGNAL(signalPerspectiveChanged(TQRect, float, float, float, float)),
+ this, TQ_SLOT(slotUpdateInfo(TQRect, float, float, float, float)));
+
+ connect(m_drawWhileMovingCheckBox, TQ_SIGNAL(toggled(bool)),
+ m_previewWidget, TQ_SLOT(slotToggleDrawWhileMoving(bool)));
+
+ connect(m_drawGridCheckBox, TQ_SIGNAL(toggled(bool)),
+ m_previewWidget, TQ_SLOT(slotToggleDrawGrid(bool)));
+
+ connect(m_guideColorBt, TQ_SIGNAL(changed(const TQColor &)),
+ m_previewWidget, TQ_SLOT(slotChangeGuideColor(const TQColor &)));
+
+ connect(m_guideSize, TQ_SIGNAL(valueChanged(int)),
+ m_previewWidget, TQ_SLOT(slotChangeGuideSize(int)));
+}
+
+ImageEffect_Perspective::~ImageEffect_Perspective()
+{
+}
+
+void ImageEffect_Perspective::readUserSettings(void)
+{
+ TQColor defaultGuideColor(TQt::red);
+ TDEConfig *config = kapp->config();
+ config->setGroup("perspective Tool Dialog");
+ m_drawWhileMovingCheckBox->setChecked(config->readBoolEntry("Draw While Moving", true));
+ m_drawGridCheckBox->setChecked(config->readBoolEntry("Draw Grid", false));
+ m_guideColorBt->setColor(config->readColorEntry("Guide Color", &defaultGuideColor));
+ m_guideSize->setValue(config->readNumEntry("Guide Width", 1));
+ m_previewWidget->slotToggleDrawWhileMoving(m_drawWhileMovingCheckBox->isChecked());
+ m_previewWidget->slotToggleDrawGrid(m_drawGridCheckBox->isChecked());
+ m_previewWidget->slotChangeGuideColor(m_guideColorBt->color());
+ m_previewWidget->slotChangeGuideSize(m_guideSize->value());
+}
+
+void ImageEffect_Perspective::writeUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("perspective Tool Dialog");
+ config->writeEntry("Draw While Moving", m_drawWhileMovingCheckBox->isChecked());
+ config->writeEntry("Draw Grid", m_drawGridCheckBox->isChecked());
+ config->writeEntry("Guide Color", m_guideColorBt->color());
+ config->writeEntry("Guide Width", m_guideSize->value());
+ config->sync();
+}
+
+void ImageEffect_Perspective::resetValues()
+{
+ m_previewWidget->reset();
+}
+
+void ImageEffect_Perspective::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ m_previewWidget->applyPerspectiveAdjustment();
+ accept();
+ kapp->restoreOverrideCursor();
+}
+
+void ImageEffect_Perspective::slotUpdateInfo(TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle)
+{
+ TQString temp;
+ m_newWidthLabel->setText(temp.setNum( newSize.width()) + i18n(" px") );
+ m_newHeightLabel->setText(temp.setNum( newSize.height()) + i18n(" px") );
+
+ m_topLeftAngleLabel->setText(temp.setNum( topLeftAngle, 'f', 1 ));
+ m_topRightAngleLabel->setText(temp.setNum( topRightAngle, 'f', 1 ));
+ m_bottomLeftAngleLabel->setText(temp.setNum( bottomLeftAngle, 'f', 1 ));
+ m_bottomRightAngleLabel->setText(temp.setNum( bottomRightAngle, 'f', 1 ));
+}
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
diff --git a/src/imageplugins/perspective/imageeffect_perspective.h b/src/imageplugins/perspective/imageeffect_perspective.h
new file mode 100644
index 00000000..41388aa7
--- /dev/null
+++ b/src/imageplugins/perspective/imageeffect_perspective.h
@@ -0,0 +1,89 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective .
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_PERSPECTIVE_H
+#define IMAGEEFFECT_PERSPECTIVE_H
+
+// TQt includes.
+
+#include <tqrect.h>
+
+// Digikam includes.
+
+#include "imagedlgbase.h"
+
+class TQLabel;
+class TQCheckBox;
+class TQSpinBox;
+
+class KColorButton;
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class PerspectiveWidget;
+
+class ImageEffect_Perspective : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Perspective(TQWidget* parent);
+ ~ImageEffect_Perspective();
+
+private slots:
+
+ void slotUpdateInfo(TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle);
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void finalRendering();
+
+private:
+
+ TQLabel *m_newWidthLabel;
+ TQLabel *m_newHeightLabel;
+ TQLabel *m_topLeftAngleLabel;
+ TQLabel *m_topRightAngleLabel;
+ TQLabel *m_bottomLeftAngleLabel;
+ TQLabel *m_bottomRightAngleLabel;
+
+ TQCheckBox *m_drawWhileMovingCheckBox;
+ TQCheckBox *m_drawGridCheckBox;
+
+ TQSpinBox *m_guideSize;
+
+ KColorButton *m_guideColorBt;
+
+ PerspectiveWidget *m_previewWidget;
+};
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
+#endif /* IMAGEEFFECT_PERSPECTIVE_H */
diff --git a/src/imageplugins/perspective/imageplugin_perspective.cpp b/src/imageplugins/perspective/imageplugin_perspective.cpp
new file mode 100644
index 00000000..bb5d0444
--- /dev/null
+++ b/src/imageplugins/perspective/imageplugin_perspective.cpp
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective .
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "perspectivetool.h"
+#include "imageplugin_perspective.h"
+#include "imageplugin_perspective.moc"
+
+using namespace DigikamPerspectiveImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_perspective,
+ KGenericFactory<ImagePlugin_Perspective>("digikamimageplugin_perspective"));
+
+ImagePlugin_Perspective::ImagePlugin_Perspective(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_Perspective")
+{
+ m_perspectiveAction = new TDEAction(i18n("Perspective Adjustment..."), "perspective", 0,
+ this, TQ_SLOT(slotPerspective()),
+ actionCollection(), "imageplugin_perspective");
+
+ setXMLFile("digikamimageplugin_perspective_ui.rc");
+
+ DDebug() << "ImagePlugin_Perspective plugin loaded" << endl;
+}
+
+ImagePlugin_Perspective::~ImagePlugin_Perspective()
+{
+}
+
+void ImagePlugin_Perspective::setEnabledActions(bool enable)
+{
+ m_perspectiveAction->setEnabled(enable);
+}
+
+void ImagePlugin_Perspective::slotPerspective()
+{
+ PerspectiveTool *tool = new PerspectiveTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/perspective/imageplugin_perspective.h b/src/imageplugins/perspective/imageplugin_perspective.h
new file mode 100644
index 00000000..5dee7b1b
--- /dev/null
+++ b/src/imageplugins/perspective/imageplugin_perspective.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective .
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_PERSPECTIVE_H
+#define IMAGEPLUGIN_PERSPECTIVE_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_Perspective : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_Perspective(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_Perspective();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotPerspective();
+
+private:
+
+ TDEAction *m_perspectiveAction;
+};
+
+#endif /* IMAGEPLUGIN_PERSPECTIVE_H */
diff --git a/src/imageplugins/perspective/matrix.cpp b/src/imageplugins/perspective/matrix.cpp
new file mode 100644
index 00000000..65723c56
--- /dev/null
+++ b/src/imageplugins/perspective/matrix.cpp
@@ -0,0 +1,177 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a matrix implementation for image
+ * perspective adjustment.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Matrix3 implementation inspired from gimp 2.0
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstring>
+
+// Local includes.
+
+#include "matrix.h"
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+static double identityMatrix[3][3] = { { 1.0, 0.0, 0.0 },
+ { 0.0, 1.0, 0.0 },
+ { 0.0, 0.0, 1.0 } };
+
+Matrix::Matrix()
+{
+ memcpy(coeff, identityMatrix, sizeof(coeff));
+}
+
+void Matrix::translate (double x, double y)
+{
+ double g, h, i;
+
+ g = coeff[2][0];
+ h = coeff[2][1];
+ i = coeff[2][2];
+
+ coeff[0][0] += x * g;
+ coeff[0][1] += x * h;
+ coeff[0][2] += x * i;
+ coeff[1][0] += y * g;
+ coeff[1][1] += y * h;
+ coeff[1][2] += y * i;
+}
+
+void Matrix::scale(double x, double y)
+{
+ coeff[0][0] *= x;
+ coeff[0][1] *= x;
+ coeff[0][2] *= x;
+
+ coeff[1][0] *= y;
+ coeff[1][1] *= y;
+ coeff[1][2] *= y;
+}
+
+void Matrix::multiply(const Matrix &matrix)
+{
+ int i, j;
+ Matrix tmp;
+ double t1, t2, t3;
+
+ for (i = 0; i < 3; i++)
+ {
+ t1 = matrix.coeff[i][0];
+ t2 = matrix.coeff[i][1];
+ t3 = matrix.coeff[i][2];
+
+ for (j = 0; j < 3; j++)
+ {
+ tmp.coeff[i][j] = t1 * coeff[0][j];
+ tmp.coeff[i][j] += t2 * coeff[1][j];
+ tmp.coeff[i][j] += t3 * coeff[2][j];
+ }
+ }
+
+ *this = tmp;
+}
+
+void Matrix::transformPoint(double x, double y, double *newx, double *newy) const
+{
+ double w;
+
+ w = coeff[2][0] * x + coeff[2][1] * y + coeff[2][2];
+
+ if (w == 0.0)
+ w = 1.0;
+ else
+ w = 1.0/w;
+
+ *newx = (coeff[0][0] * x +
+ coeff[0][1] * y +
+ coeff[0][2]) * w;
+ *newy = (coeff[1][0] * x +
+ coeff[1][1] * y +
+ coeff[1][2]) * w;
+}
+
+void Matrix::invert()
+{
+ Matrix inv;
+ double det;
+
+ det = determinant();
+
+ if (det == 0.0)
+ return;
+
+ det = 1.0 / det;
+
+ inv.coeff[0][0] = (coeff[1][1] * coeff[2][2] -
+ coeff[1][2] * coeff[2][1]) * det;
+
+ inv.coeff[1][0] = - (coeff[1][0] * coeff[2][2] -
+ coeff[1][2] * coeff[2][0]) * det;
+
+ inv.coeff[2][0] = (coeff[1][0] * coeff[2][1] -
+ coeff[1][1] * coeff[2][0]) * det;
+
+ inv.coeff[0][1] = - (coeff[0][1] * coeff[2][2] -
+ coeff[0][2] * coeff[2][1]) * det;
+
+ inv.coeff[1][1] = (coeff[0][0] * coeff[2][2] -
+ coeff[0][2] * coeff[2][0]) * det;
+
+ inv.coeff[2][1] = - (coeff[0][0] * coeff[2][1] -
+ coeff[0][1] * coeff[2][0]) * det;
+
+ inv.coeff[0][2] = (coeff[0][1] * coeff[1][2] -
+ coeff[0][2] * coeff[1][1]) * det;
+
+ inv.coeff[1][2] = - (coeff[0][0] * coeff[1][2] -
+ coeff[0][2] * coeff[1][0]) * det;
+
+ inv.coeff[2][2] = (coeff[0][0] * coeff[1][1] -
+ coeff[0][1] * coeff[1][0]) * det;
+
+ *this = inv;
+}
+
+double Matrix::determinant() const
+{
+ double determinant;
+
+ determinant = (coeff[0][0] *
+ (coeff[1][1] * coeff[2][2] -
+ coeff[1][2] * coeff[2][1]));
+ determinant -= (coeff[1][0] *
+ (coeff[0][1] * coeff[2][2] -
+ coeff[0][2] * coeff[2][1]));
+ determinant += (coeff[2][0] *
+ (coeff[0][1] * coeff[1][2] -
+ coeff[0][2] * coeff[1][1]));
+
+ return determinant;
+}
+
+} // namespace DigikamPerspectiveImagesPlugin
diff --git a/src/imageplugins/perspective/matrix.h b/src/imageplugins/perspective/matrix.h
new file mode 100644
index 00000000..fbc5a1aa
--- /dev/null
+++ b/src/imageplugins/perspective/matrix.h
@@ -0,0 +1,106 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a matrix implementation for image
+ * perspective adjustment.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_PERSPECTIVE_MATRIX_H
+#define IMAGEEFFECT_PERSPECTIVE_MATRIX_H
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class Matrix
+{
+public:
+
+ /**
+ * Matrix:
+ *
+ * Initializes matrix to the identity matrix.
+ */
+ Matrix();
+
+ /**
+ * translate:
+ * @x: Translation in X direction.
+ * @y: Translation in Y direction.
+ *
+ * Translates the matrix by x and y.
+ */
+ void translate(double x, double y);
+
+ /**
+ * scale:
+ * @x: X scale factor.
+ * @y: Y scale factor.
+ *
+ * Scales the matrix by x and y
+ */
+ void scale(double x, double y);
+
+ /**
+ * invert:
+ *
+ * Inverts this matrix.
+ */
+ void invert();
+
+ /**
+ * multiply:
+ * @matrix: The other input matrix.
+ *
+ * Multiplies this matrix with another matrix
+ */
+ void multiply(const Matrix &matrix1);
+
+ /**
+ * transformPoint:
+ * @x: The source X coordinate.
+ * @y: The source Y coordinate.
+ * @newx: The transformed X coordinate.
+ * @newy: The transformed Y coordinate.
+ *
+ * Transforms a point in 2D as specified by the transformation matrix.
+ */
+ void transformPoint(double x, double y, double *newx, double *newy) const;
+
+ /**
+ * determinant:
+ *
+ * Calculates the determinant of this matrix.
+ *
+ * Returns: The determinant.
+ */
+ double determinant() const;
+
+ /**
+ * coeff:
+ *
+ * The 3x3 matrix data
+ */
+ double coeff[3][3];
+};
+
+} // namespace DigikamPerspectiveImagesPlugin
+
+#endif // IMAGEEFFECT_PERSPECTIVE_MATRIX_H
diff --git a/src/imageplugins/perspective/perspectivetool.cpp b/src/imageplugins/perspective/perspectivetool.cpp
new file mode 100644
index 00000000..30d0a2cf
--- /dev/null
+++ b/src/imageplugins/perspective/perspectivetool.cpp
@@ -0,0 +1,244 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqframe.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpushbutton.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kcolorbutton.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdepopupmenu.h>
+#include <kseparator.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "editortoolsettings.h"
+#include "perspectivewidget.h"
+#include "perspectivetool.h"
+#include "perspectivetool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+PerspectiveTool::PerspectiveTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("perspective");
+ setToolName(i18n("Perspective"));
+ setToolIcon(SmallIcon("perspective"));
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(0);
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+ TQVBoxLayout* l = new TQVBoxLayout(frame, 5, 0);
+ m_previewWidget = new PerspectiveWidget(525, 350, frame);
+ l->addWidget(m_previewWidget);
+ TQWhatsThis::add(m_previewWidget, i18n("<p>This is the perspective transformation operation preview. "
+ "You can use the mouse for dragging the corner to adjust the "
+ "perspective transformation area."));
+ setToolView(frame);
+
+ // -------------------------------------------------------------
+
+ TQString temp;
+ Digikam::ImageIface iface(0, 0);
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout *gridLayout = new TQGridLayout( m_gboxSettings->plainPage(), 13, 2);
+
+ TQLabel *label1 = new TQLabel(i18n("New width:"), m_gboxSettings->plainPage());
+ m_newWidthLabel = new TQLabel(temp.setNum( iface.originalWidth()) + i18n(" px"), m_gboxSettings->plainPage());
+ m_newWidthLabel->setAlignment( AlignBottom | AlignRight );
+
+ TQLabel *label2 = new TQLabel(i18n("New height:"), m_gboxSettings->plainPage());
+ m_newHeightLabel = new TQLabel(temp.setNum( iface.originalHeight()) + i18n(" px"), m_gboxSettings->plainPage());
+ m_newHeightLabel->setAlignment( AlignBottom | AlignRight );
+
+ // -------------------------------------------------------------
+
+ KSeparator *line = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ TQLabel *angleLabel = new TQLabel(i18n("Angles (in degrees):"), m_gboxSettings->plainPage());
+ TQLabel *label3 = new TQLabel(i18n(" Top left:"), m_gboxSettings->plainPage());
+ m_topLeftAngleLabel = new TQLabel(m_gboxSettings->plainPage());
+ TQLabel *label4 = new TQLabel(i18n(" Top right:"), m_gboxSettings->plainPage());
+ m_topRightAngleLabel = new TQLabel(m_gboxSettings->plainPage());
+ TQLabel *label5 = new TQLabel(i18n(" Bottom left:"), m_gboxSettings->plainPage());
+ m_bottomLeftAngleLabel = new TQLabel(m_gboxSettings->plainPage());
+ TQLabel *label6 = new TQLabel(i18n(" Bottom right:"), m_gboxSettings->plainPage());
+ m_bottomRightAngleLabel = new TQLabel(m_gboxSettings->plainPage());
+
+ // -------------------------------------------------------------
+
+ KSeparator *line2 = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ m_drawWhileMovingCheckBox = new TQCheckBox(i18n("Draw preview while moving"), m_gboxSettings->plainPage());
+ gridLayout->addMultiCellWidget(line2, 8, 8, 0, 2);
+ gridLayout->addMultiCellWidget(m_drawWhileMovingCheckBox, 9, 9, 0, 2);
+
+ m_drawGridCheckBox = new TQCheckBox(i18n("Draw grid"), m_gboxSettings->plainPage());
+
+ // -------------------------------------------------------------
+
+ TQLabel *label7 = new TQLabel(i18n("Guide color:"), m_gboxSettings->plainPage());
+ m_guideColorBt = new KColorButton( TQColor( TQt::red ), m_gboxSettings->plainPage() );
+ TQWhatsThis::add( m_guideColorBt, i18n("<p>Set here the color used to draw guides dashed-lines."));
+ gridLayout->addMultiCellWidget(label7, 11, 11, 0, 0);
+ gridLayout->addMultiCellWidget(m_guideColorBt, 11, 11, 2, 2);
+
+ TQLabel *label8 = new TQLabel(i18n("Guide width:"), m_gboxSettings->plainPage());
+ m_guideSize = new RIntNumInput(m_gboxSettings->plainPage());
+ m_guideSize->input()->setRange(1, 5, 1, false);
+ m_guideSize->setDefaultValue(1);
+ TQWhatsThis::add( m_guideSize, i18n("<p>Set here the width in pixels used to draw guides dashed-lines."));
+
+ gridLayout->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridLayout->addMultiCellWidget(m_newWidthLabel, 0, 0, 1, 2);
+ gridLayout->addMultiCellWidget(label2, 1, 1, 0, 0);
+ gridLayout->addMultiCellWidget(m_newHeightLabel, 1, 1, 1, 2);
+ gridLayout->addMultiCellWidget(line, 2, 2, 0, 2);
+ gridLayout->addMultiCellWidget(angleLabel, 3, 3, 0, 2);
+ gridLayout->addMultiCellWidget(label3, 4, 4, 0, 0);
+ gridLayout->addMultiCellWidget(m_topLeftAngleLabel, 4, 4, 1, 2);
+ gridLayout->addMultiCellWidget(label4, 5, 5, 0, 0);
+ gridLayout->addMultiCellWidget(m_topRightAngleLabel, 5, 5, 1, 2);
+ gridLayout->addMultiCellWidget(label5, 6, 6, 0, 0);
+ gridLayout->addMultiCellWidget(m_bottomLeftAngleLabel, 6, 6, 1, 2);
+ gridLayout->addMultiCellWidget(label6, 7, 7, 0, 0);
+ gridLayout->addMultiCellWidget(m_bottomRightAngleLabel, 7, 7, 1, 2);
+ gridLayout->addMultiCellWidget(m_drawGridCheckBox, 10, 10, 0, 2);
+ gridLayout->addMultiCellWidget(label8, 12, 12, 0, 0);
+ gridLayout->addMultiCellWidget(m_guideSize, 12, 12, 2, 2);
+ gridLayout->setColStretch(1, 10);
+ gridLayout->setRowStretch(13, 10);
+ gridLayout->setMargin(m_gboxSettings->spacingHint());
+ gridLayout->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_previewWidget, TQ_SIGNAL(signalPerspectiveChanged(TQRect, float, float, float, float)),
+ this, TQ_SLOT(slotUpdateInfo(TQRect, float, float, float, float)));
+
+ connect(m_drawWhileMovingCheckBox, TQ_SIGNAL(toggled(bool)),
+ m_previewWidget, TQ_SLOT(slotToggleDrawWhileMoving(bool)));
+
+ connect(m_drawGridCheckBox, TQ_SIGNAL(toggled(bool)),
+ m_previewWidget, TQ_SLOT(slotToggleDrawGrid(bool)));
+
+ connect(m_guideColorBt, TQ_SIGNAL(changed(const TQColor&)),
+ m_previewWidget, TQ_SLOT(slotChangeGuideColor(const TQColor&)));
+
+ connect(m_guideSize, TQ_SIGNAL(valueChanged(int)),
+ m_previewWidget, TQ_SLOT(slotChangeGuideSize(int)));
+}
+
+PerspectiveTool::~PerspectiveTool()
+{
+}
+
+void PerspectiveTool::readSettings()
+{
+ TQColor defaultGuideColor(TQt::red);
+ TDEConfig *config = kapp->config();
+ config->setGroup("perspective Tool");
+ m_drawWhileMovingCheckBox->setChecked(config->readBoolEntry("Draw While Moving", true));
+ m_drawGridCheckBox->setChecked(config->readBoolEntry("Draw Grid", false));
+ m_guideColorBt->setColor(config->readColorEntry("Guide Color", &defaultGuideColor));
+ m_guideSize->setValue(config->readNumEntry("Guide Width", m_guideSize->defaultValue()));
+ m_previewWidget->slotToggleDrawWhileMoving(m_drawWhileMovingCheckBox->isChecked());
+ m_previewWidget->slotToggleDrawGrid(m_drawGridCheckBox->isChecked());
+ m_previewWidget->slotChangeGuideColor(m_guideColorBt->color());
+ m_previewWidget->slotChangeGuideSize(m_guideSize->value());
+}
+
+void PerspectiveTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("perspective Tool");
+ config->writeEntry("Draw While Moving", m_drawWhileMovingCheckBox->isChecked());
+ config->writeEntry("Draw Grid", m_drawGridCheckBox->isChecked());
+ config->writeEntry("Guide Color", m_guideColorBt->color());
+ config->writeEntry("Guide Width", m_guideSize->value());
+ config->sync();
+}
+
+void PerspectiveTool::slotResetSettings()
+{
+ m_previewWidget->reset();
+}
+
+void PerspectiveTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ m_previewWidget->applyPerspectiveAdjustment();
+ kapp->restoreOverrideCursor();
+}
+
+void PerspectiveTool::slotUpdateInfo(TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle)
+{
+ TQString temp;
+ m_newWidthLabel->setText(temp.setNum( newSize.width()) + i18n(" px") );
+ m_newHeightLabel->setText(temp.setNum( newSize.height()) + i18n(" px") );
+
+ m_topLeftAngleLabel->setText(temp.setNum( topLeftAngle, 'f', 1 ));
+ m_topRightAngleLabel->setText(temp.setNum( topRightAngle, 'f', 1 ));
+ m_bottomLeftAngleLabel->setText(temp.setNum( bottomLeftAngle, 'f', 1 ));
+ m_bottomRightAngleLabel->setText(temp.setNum( bottomRightAngle, 'f', 1 ));
+}
+
+} // NameSpace DigikamPerspectiveImagesPlugin
diff --git a/src/imageplugins/perspective/perspectivetool.h b/src/imageplugins/perspective/perspectivetool.h
new file mode 100644
index 00000000..6186712f
--- /dev/null
+++ b/src/imageplugins/perspective/perspectivetool.h
@@ -0,0 +1,100 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-02-17
+ * Description : a plugin to change image perspective.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_PERSPECTIVE_H
+#define IMAGEEFFECT_PERSPECTIVE_H
+
+// TQt includes.
+
+#include <tqrect.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQLabel;
+class TQCheckBox;
+
+class KColorButton;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+}
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class PerspectiveWidget;
+
+class PerspectiveTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ PerspectiveTool(TQObject* parent);
+ ~PerspectiveTool();
+
+private slots:
+
+ void slotResetSettings();
+ void slotUpdateInfo(TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle);
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+
+private:
+
+ TQLabel *m_newWidthLabel;
+ TQLabel *m_newHeightLabel;
+ TQLabel *m_topLeftAngleLabel;
+ TQLabel *m_topRightAngleLabel;
+ TQLabel *m_bottomLeftAngleLabel;
+ TQLabel *m_bottomRightAngleLabel;
+
+ TQCheckBox *m_drawWhileMovingCheckBox;
+ TQCheckBox *m_drawGridCheckBox;
+
+ KDcrawIface::RIntNumInput *m_guideSize;
+
+ KColorButton *m_guideColorBt;
+
+ PerspectiveWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
+#endif /* IMAGEEFFECT_PERSPECTIVE_H */
diff --git a/src/imageplugins/perspective/perspectivewidget.cpp b/src/imageplugins/perspective/perspectivewidget.cpp
new file mode 100644
index 00000000..ae2c5c03
--- /dev/null
+++ b/src/imageplugins/perspective/perspectivewidget.cpp
@@ -0,0 +1,839 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-18
+ * Description : a widget class to edit perspective.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Matrix3 implementation inspired from gimp 2.0
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+
+// TQt includes.
+
+#include <tqregion.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqbrush.h>
+#include <tqpixmap.h>
+#include <tqimage.h>
+#include <tqpointarray.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdeglobal.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "triangle.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "dimgimagefilters.h"
+#include "perspectivewidget.h"
+#include "perspectivewidget.moc"
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+PerspectiveWidget::PerspectiveWidget(int w, int h, TQWidget *parent)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ setBackgroundMode(TQt::NoBackground);
+ setMinimumSize(w, h);
+ setMouseTracking(true);
+
+ m_drawGrid = false;
+ m_drawWhileMoving = true;
+ m_currentResizing = ResizingNone;
+ m_guideColor = TQt::red;
+ m_guideSize = 1;
+
+ m_iface = new Digikam::ImageIface(w, h);
+ uchar *data = m_iface->setPreviewImageSize(w, h);
+ m_w = m_iface->previewWidth();
+ m_h = m_iface->previewHeight();
+ m_origW = m_iface->originalWidth();
+ m_origH = m_iface->originalHeight();
+ m_previewImage = Digikam::DImg(m_w, m_h, m_iface->previewSixteenBit(), m_iface->previewHasAlpha(), data, false);
+
+ m_pixmap = new TQPixmap(w, h);
+
+ m_rect = TQRect(w/2-m_w/2, h/2-m_h/2, m_w, m_h);
+ m_grid = TQPointArray(60);
+
+ reset();
+}
+
+PerspectiveWidget::~PerspectiveWidget()
+{
+ delete m_iface;
+ delete m_pixmap;
+}
+
+Digikam::ImageIface* PerspectiveWidget::imageIface()
+{
+ return m_iface;
+}
+
+TQPoint PerspectiveWidget::getTopLeftCorner(void)
+{
+ return TQPoint( lroundf((float)(m_topLeftPoint.x()*m_origW) / (float)m_w),
+ lroundf((float)(m_topLeftPoint.y()*m_origH) / (float)m_h));
+}
+
+TQPoint PerspectiveWidget::getTopRightCorner(void)
+{
+ return TQPoint( lroundf((float)(m_topRightPoint.x()*m_origW) / (float)m_w),
+ lroundf((float)(m_topRightPoint.y()*m_origH) / (float)m_h));
+}
+
+TQPoint PerspectiveWidget::getBottomLeftCorner(void)
+{
+ return TQPoint( lroundf((float)(m_bottomLeftPoint.x()*m_origW) / (float)m_w),
+ lroundf((float)(m_bottomLeftPoint.y()*m_origH) / (float)m_h));
+}
+
+TQPoint PerspectiveWidget::getBottomRightCorner(void)
+{
+ return TQPoint( lroundf((float)(m_bottomRightPoint.x()*m_origW) / (float)m_w),
+ lroundf((float)(m_bottomRightPoint.y()*m_origH) / (float)m_h));
+}
+
+TQRect PerspectiveWidget::getTargetSize(void)
+{
+ TQPointArray perspectiveArea;
+
+ perspectiveArea.putPoints( 0, 4,
+ getTopLeftCorner().x(), getTopLeftCorner().y(),
+ getTopRightCorner().x(), getTopRightCorner().y(),
+ getBottomRightCorner().x(), getBottomRightCorner().y(),
+ getBottomLeftCorner().x(), getBottomLeftCorner().y() );
+
+ return perspectiveArea.boundingRect();
+}
+
+float PerspectiveWidget::getAngleTopLeft(void)
+{
+ Triangle topLeft(getTopLeftCorner(), getTopRightCorner(), getBottomLeftCorner());
+ return topLeft.angleBAC();
+}
+
+float PerspectiveWidget::getAngleTopRight(void)
+{
+ Triangle topLeft(getTopRightCorner(), getBottomRightCorner(), getTopLeftCorner());
+ return topLeft.angleBAC();
+}
+
+float PerspectiveWidget::getAngleBottomLeft(void)
+{
+ Triangle topLeft(getBottomLeftCorner(), getTopLeftCorner(), getBottomRightCorner());
+ return topLeft.angleBAC();
+}
+
+float PerspectiveWidget::getAngleBottomRight(void)
+{
+ Triangle topLeft(getBottomRightCorner(), getBottomLeftCorner(), getTopRightCorner());
+ return topLeft.angleBAC();
+}
+
+void PerspectiveWidget::reset(void)
+{
+ m_topLeftPoint.setX(0);
+ m_topLeftPoint.setY(0);
+
+ m_topRightPoint.setX(m_w-1);
+ m_topRightPoint.setY(0);
+
+ m_bottomLeftPoint.setX(0);
+ m_bottomLeftPoint.setY(m_h-1);
+
+ m_bottomRightPoint.setX(m_w-1);
+ m_bottomRightPoint.setY(m_h-1);
+
+ m_spot.setX(m_w / 2);
+ m_spot.setY(m_h / 2);
+
+ m_antiAlias = true;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::applyPerspectiveAdjustment(void)
+{
+ Digikam::DImg *orgImage = m_iface->getOriginalImg();
+ Digikam::DImg destImage(orgImage->width(), orgImage->height(), orgImage->sixteenBit(), orgImage->hasAlpha());
+
+ Digikam::DColor background(0, 0, 0, orgImage->hasAlpha() ? 0 : 255, orgImage->sixteenBit());
+
+ // Perform perspective adjustment.
+
+ buildPerspective(TQPoint(0, 0), TQPoint(m_origW, m_origH),
+ getTopLeftCorner(), getTopRightCorner(),
+ getBottomLeftCorner(), getBottomRightCorner(),
+ orgImage, &destImage, background);
+
+ // Perform an auto-croping around the image.
+
+ Digikam::DImg targetImg = destImage.copy(getTargetSize());
+
+ // Update target image.
+ m_iface->putOriginalImage(i18n("Perspective Adjustment"),
+ targetImg.bits(), targetImg.width(), targetImg.height());
+}
+
+void PerspectiveWidget::slotToggleAntiAliasing(bool a)
+{
+ m_antiAlias = a;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::slotToggleDrawWhileMoving(bool draw)
+{
+ m_drawWhileMoving = draw;
+}
+
+void PerspectiveWidget::slotToggleDrawGrid(bool grid)
+{
+ m_drawGrid = grid;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::slotChangeGuideColor(const TQColor &color)
+{
+ m_guideColor = color;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::slotChangeGuideSize(int size)
+{
+ m_guideSize = size;
+ updatePixmap();
+ repaint(false);
+}
+
+void PerspectiveWidget::updatePixmap(void)
+{
+ m_topLeftCorner.setRect(m_topLeftPoint.x() + m_rect.topLeft().x(),
+ m_topLeftPoint.y() + m_rect.topLeft().y(), 8, 8);
+ m_topRightCorner.setRect(m_topRightPoint.x() - 7 + m_rect.topLeft().x(),
+ m_topRightPoint.y() + m_rect.topLeft().y(), 8, 8);
+ m_bottomLeftCorner.setRect(m_bottomLeftPoint.x() + m_rect.topLeft().x(),
+ m_bottomLeftPoint.y() - 7 + m_rect.topLeft().y(), 8, 8);
+ m_bottomRightCorner.setRect(m_bottomRightPoint.x() - 7 + m_rect.topLeft().x(),
+ m_bottomRightPoint.y() - 7 + m_rect.topLeft().y(), 8, 8);
+
+ // Compute the grid array
+
+ int gXS = m_w / 15;
+ int gYS = m_h / 15;
+
+ for (int i = 0 ; i < 15 ; i++)
+ {
+ int j = i*4;
+
+ //Horizontal line.
+ m_grid.setPoint(j , 0, i*gYS);
+ m_grid.setPoint(j+1, m_w, i*gYS);
+
+ //Vertical line.
+ m_grid.setPoint(j+2, i*gXS, 0);
+ m_grid.setPoint(j+3, i*gXS, m_h);
+ }
+
+ // Draw background
+
+ m_pixmap->fill(colorGroup().background());
+
+ // if we are resizing with the mouse, compute and draw only if drawWhileMoving is set
+ if (m_currentResizing == ResizingNone || m_drawWhileMoving)
+ {
+ // Create preview image
+
+ Digikam::DImg destImage(m_previewImage.width(), m_previewImage.height(),
+ m_previewImage.sixteenBit(), m_previewImage.hasAlpha());
+
+ Digikam::DColor background(colorGroup().background());
+
+ m_transformedCenter = buildPerspective(TQPoint(0, 0), TQPoint(m_w, m_h),
+ m_topLeftPoint, m_topRightPoint,
+ m_bottomLeftPoint, m_bottomRightPoint,
+ &m_previewImage, &destImage, background);
+
+ m_iface->putPreviewImage(destImage.bits());
+
+ // Draw image
+
+ m_iface->paint(m_pixmap, m_rect.x(), m_rect.y(),
+ m_rect.width(), m_rect.height());
+ }
+ else
+ {
+ m_transformedCenter = buildPerspective(TQPoint(0, 0), TQPoint(m_w, m_h),
+ m_topLeftPoint, m_topRightPoint,
+ m_bottomLeftPoint, m_bottomRightPoint);
+ }
+
+ // Drawing selection borders.
+
+ TQPainter p(m_pixmap);
+ p.setPen(TQPen(TQColor(255, 64, 64), 1, TQt::SolidLine));
+ p.drawLine(m_topLeftPoint+m_rect.topLeft(), m_topRightPoint+m_rect.topLeft());
+ p.drawLine(m_topRightPoint+m_rect.topLeft(), m_bottomRightPoint+m_rect.topLeft());
+ p.drawLine(m_bottomRightPoint+m_rect.topLeft(), m_bottomLeftPoint+m_rect.topLeft());
+ p.drawLine(m_bottomLeftPoint+m_rect.topLeft(), m_topLeftPoint+m_rect.topLeft());
+
+ // Drawing selection corners.
+
+ TQBrush brush(TQColor(255, 64, 64));
+ p.fillRect(m_topLeftCorner, brush);
+ p.fillRect(m_topRightCorner, brush);
+ p.fillRect(m_bottomLeftCorner, brush);
+ p.fillRect(m_bottomRightCorner, brush);
+
+ // Drawing the grid.
+
+ if (m_drawGrid)
+ {
+ for (uint i = 0 ; i < m_grid.size() ; i += 4)
+ {
+ //Horizontal line.
+ p.drawLine(m_grid.point(i)+m_rect.topLeft(), m_grid.point(i+1)+m_rect.topLeft());
+
+ //Vertical line.
+ p.drawLine(m_grid.point(i+2)+m_rect.topLeft(), m_grid.point(i+3)+m_rect.topLeft());
+ }
+ }
+
+ // Drawing transformed center.
+
+ p.setPen(TQPen(TQColor(255, 64, 64), 3, TQt::SolidLine));
+ p.drawEllipse( m_transformedCenter.x()+m_rect.topLeft().x()-2,
+ m_transformedCenter.y()+m_rect.topLeft().y()-2, 4, 4 );
+
+ // Drawing vertical and horizontal guide lines.
+
+ int xspot = m_spot.x() + m_rect.x();
+ int yspot = m_spot.y() + m_rect.y();
+ p.setPen(TQPen(TQt::white, m_guideSize, TQt::SolidLine));
+ p.drawLine(xspot, m_rect.top(), xspot, m_rect.bottom());
+ p.drawLine(m_rect.left(), yspot, m_rect.right(), yspot);
+ p.setPen(TQPen(m_guideColor, m_guideSize, TQt::DotLine));
+ p.drawLine(xspot, m_rect.top(), xspot, m_rect.bottom());
+ p.drawLine(m_rect.left(), yspot, m_rect.right(), yspot);
+
+ p.end();
+
+ emit signalPerspectiveChanged(getTargetSize(), getAngleTopLeft(), getAngleTopRight(),
+ getAngleBottomLeft(), getAngleBottomRight());
+}
+
+TQPoint PerspectiveWidget::buildPerspective(TQPoint orignTopLeft, TQPoint orignBottomRight,
+ TQPoint transTopLeft, TQPoint transTopRight,
+ TQPoint transBottomLeft, TQPoint transBottomRight,
+ Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ Digikam::DColor background)
+{
+ Matrix matrix, transform;
+ double scalex;
+ double scaley;
+
+ double x1 = (double)orignTopLeft.x();
+ double y1 = (double)orignTopLeft.y();
+
+ double x2 = (double)orignBottomRight.x();
+ double y2 = (double)orignBottomRight.y();
+
+ double tx1 = (double)transTopLeft.x();
+ double ty1 = (double)transTopLeft.y();
+
+ double tx2 = (double)transTopRight.x();
+ double ty2 = (double)transTopRight.y();
+
+ double tx3 = (double)transBottomLeft.x();
+ double ty3 = (double)transBottomLeft.y();
+
+ double tx4 = (double)transBottomRight.x();
+ double ty4 = (double)transBottomRight.y();
+
+ scalex = scaley = 1.0;
+
+ if ((x2 - x1) > 0)
+ scalex = 1.0 / (double) (x2 - x1);
+
+ if ((y2 - y1) > 0)
+ scaley = 1.0 / (double) (y2 - y1);
+
+ // Determine the perspective transform that maps from
+ // the unit cube to the transformed coordinates
+
+ double dx1, dx2, dx3, dy1, dy2, dy3;
+
+ dx1 = tx2 - tx4;
+ dx2 = tx3 - tx4;
+ dx3 = tx1 - tx2 + tx4 - tx3;
+
+ dy1 = ty2 - ty4;
+ dy2 = ty3 - ty4;
+ dy3 = ty1 - ty2 + ty4 - ty3;
+
+ // Is the mapping affine?
+
+ if ((dx3 == 0.0) && (dy3 == 0.0))
+ {
+ matrix.coeff[0][0] = tx2 - tx1;
+ matrix.coeff[0][1] = tx4 - tx2;
+ matrix.coeff[0][2] = tx1;
+ matrix.coeff[1][0] = ty2 - ty1;
+ matrix.coeff[1][1] = ty4 - ty2;
+ matrix.coeff[1][2] = ty1;
+ matrix.coeff[2][0] = 0.0;
+ matrix.coeff[2][1] = 0.0;
+ }
+ else
+ {
+ double det1, det2;
+
+ det1 = dx3 * dy2 - dy3 * dx2;
+ det2 = dx1 * dy2 - dy1 * dx2;
+
+ if (det1 == 0.0 && det2 == 0.0)
+ matrix.coeff[2][0] = 1.0;
+ else
+ matrix.coeff[2][0] = det1 / det2;
+
+ det1 = dx1 * dy3 - dy1 * dx3;
+
+ if (det1 == 0.0 && det2 == 0.0)
+ matrix.coeff[2][1] = 1.0;
+ else
+ matrix.coeff[2][1] = det1 / det2;
+
+ matrix.coeff[0][0] = tx2 - tx1 + matrix.coeff[2][0] * tx2;
+ matrix.coeff[0][1] = tx3 - tx1 + matrix.coeff[2][1] * tx3;
+ matrix.coeff[0][2] = tx1;
+
+ matrix.coeff[1][0] = ty2 - ty1 + matrix.coeff[2][0] * ty2;
+ matrix.coeff[1][1] = ty3 - ty1 + matrix.coeff[2][1] * ty3;
+ matrix.coeff[1][2] = ty1;
+ }
+
+ matrix.coeff[2][2] = 1.0;
+
+ // transform is initialized to the identity matrix
+ transform.translate(-x1, -y1);
+ transform.scale (scalex, scaley);
+ transform.multiply (matrix);
+
+ // Compute perspective transformation to image if image data containers exist.
+ if (orgImage && destImage)
+ transformAffine(orgImage, destImage, transform, background);
+
+ // Calculate the grid array points.
+ double newX, newY;
+ for (uint i = 0 ; i < m_grid.size() ; i++)
+ {
+ transform.transformPoint(m_grid.point(i).x(), m_grid.point(i).y(), &newX, &newY);
+ m_grid.setPoint(i, lround(newX), lround(newY));
+ }
+
+ // Calculate and return new image center.
+ double newCenterX, newCenterY;
+ transform.transformPoint(x2/2.0, y2/2.0, &newCenterX, &newCenterY);
+
+ return TQPoint(lround(newCenterX), lround(newCenterY));
+}
+
+void PerspectiveWidget::transformAffine(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ const Matrix &matrix, Digikam::DColor background)
+{
+ Matrix m(matrix), inv(matrix);
+
+ int x1, y1, x2, y2; // target bounding box
+ int x, y; // target coordinates
+ int u1, v1, u2, v2; // source bounding box
+ double uinc, vinc, winc; // increments in source coordinates
+ // pr horizontal target coordinate
+
+ double u[5],v[5]; // source coordinates,
+ // 2
+ // / \ 0 is sample in the center of pixel
+ // 1 0 3 1..4 is offset 1 pixel in each
+ // \ / direction (in target space)
+ // 4
+
+ double tu[5],tv[5],tw[5]; // undivided source coordinates and divisor
+
+ uchar *data, *newData;
+ bool sixteenBit;
+ int coords;
+ int width, height;
+ int bytesDepth;
+ int offset;
+ uchar *dest, *d;
+ Digikam::DColor color;
+
+ bytesDepth = orgImage->bytesDepth();
+ data = orgImage->bits();
+ sixteenBit = orgImage->sixteenBit();
+ width = orgImage->width();
+ height = orgImage->height();
+ newData = destImage->bits();
+
+ if (sixteenBit)
+ background.convertToSixteenBit();
+
+ //destImage->fill(background);
+
+ Digikam::DImgImageFilters filters;
+
+ // Find the inverse of the transformation matrix
+ m.invert();
+
+ u1 = 0;
+ v1 = 0;
+ u2 = u1 + width;
+ v2 = v1 + height;
+
+ x1 = u1;
+ y1 = v1;
+ x2 = u2;
+ y2 = v2;
+
+ dest = new uchar[width * bytesDepth];
+
+ uinc = m.coeff[0][0];
+ vinc = m.coeff[1][0];
+ winc = m.coeff[2][0];
+
+ coords = 1;
+
+ // these loops could be rearranged, depending on which bit of code
+ // you'd most like to write more than once.
+
+ for (y = y1; y < y2; y++)
+ {
+ // set up inverse transform steps
+
+ tu[0] = uinc * (x1 + 0.5) + m.coeff[0][1] * (y + 0.5) + m.coeff[0][2] - 0.5;
+ tv[0] = vinc * (x1 + 0.5) + m.coeff[1][1] * (y + 0.5) + m.coeff[1][2] - 0.5;
+ tw[0] = winc * (x1 + 0.5) + m.coeff[2][1] * (y + 0.5) + m.coeff[2][2];
+
+ d = dest;
+
+ for (x = x1; x < x2; x++)
+ {
+ int i; // normalize homogeneous coords
+
+ for (i = 0; i < coords; i++)
+ {
+ if (tw[i] == 1.0)
+ {
+ u[i] = tu[i];
+ v[i] = tv[i];
+ }
+ else if (tw[i] != 0.0)
+ {
+ u[i] = tu[i] / tw[i];
+ v[i] = tv[i] / tw[i];
+ }
+ else
+ {
+ DDebug() << "homogeneous coordinate = 0...\n" << endl;
+ }
+ }
+
+ // Set the destination pixels
+
+ int iu = lround( u [0] );
+ int iv = lround( v [0] );
+
+ if (iu >= u1 && iu < u2 && iv >= v1 && iv < v2)
+ {
+ // u, v coordinates into source
+
+ int u = iu - u1;
+ int v = iv - v1;
+
+ //TODO: Check why antialiasing shows no effect
+ /*if (m_antiAlias)
+ {
+ if (sixteenBit)
+ {
+ unsigned short *d16 = (unsigned short *)d;
+ filters.pixelAntiAliasing16((unsigned short *)data,
+ width, height, u, v, d16+3, d16+2, d16+1, d16);
+ }
+ else
+ {
+ filters.pixelAntiAliasing(data, width, height, u, v,
+ d+3, d+2, d+1, d);
+ }
+ }
+ else
+ {*/
+ offset = (v * width * bytesDepth) + (u * bytesDepth);
+ color.setColor(data + offset, sixteenBit);
+ color.setPixel(d);
+ //}
+
+ d += bytesDepth;
+ }
+ else // not in source range
+ {
+ // set to background color
+
+ background.setPixel(d);
+ d += bytesDepth;
+ }
+
+ for (i = 0; i < coords; i++)
+ {
+ tu[i] += uinc;
+ tv[i] += vinc;
+ tw[i] += winc;
+ }
+ }
+
+ // set the pixel region row
+
+ offset = (y - y1) * width * bytesDepth;
+ memcpy(newData + offset, dest, width * bytesDepth);
+ }
+
+ delete [] dest;
+}
+
+void PerspectiveWidget::paintEvent( TQPaintEvent * )
+{
+ bitBlt(this, 0, 0, m_pixmap);
+}
+
+void PerspectiveWidget::resizeEvent(TQResizeEvent * e)
+{
+ int old_w = m_w;
+ int old_h = m_h;
+
+ delete m_pixmap;
+ int w = e->size().width();
+ int h = e->size().height();
+ uchar *data = m_iface->setPreviewImageSize(w, h);
+ m_w = m_iface->previewWidth();
+ m_h = m_iface->previewHeight();
+ m_previewImage = Digikam::DImg(m_w, m_h, m_iface->previewSixteenBit(), m_iface->previewHasAlpha(), data, false);
+
+ m_pixmap = new TQPixmap(w, h);
+ TQRect oldRect = m_rect;
+ m_rect = TQRect(w/2-m_w/2, h/2-m_h/2, m_w, m_h);
+
+ float xFactor = (float)m_rect.width()/(float)(oldRect.width());
+ float yFactor = (float)m_rect.height()/(float)(oldRect.height());
+
+ m_topLeftPoint = TQPoint(lroundf(m_topLeftPoint.x()*xFactor),
+ lroundf(m_topLeftPoint.y()*yFactor));
+ m_topRightPoint = TQPoint(lroundf(m_topRightPoint.x()*xFactor),
+ lroundf(m_topRightPoint.y()*yFactor));
+ m_bottomLeftPoint = TQPoint(lroundf(m_bottomLeftPoint.x()*xFactor),
+ lroundf(m_bottomLeftPoint.y()*yFactor));
+ m_bottomRightPoint = TQPoint(lroundf(m_bottomRightPoint.x()*xFactor),
+ lroundf(m_bottomRightPoint.y()*yFactor));
+ m_transformedCenter = TQPoint(lroundf(m_transformedCenter.x()*xFactor),
+ lroundf(m_transformedCenter.y()*yFactor));
+
+ m_spot.setX((int)((float)m_spot.x() * ( (float)m_w / (float)old_w)));
+ m_spot.setY((int)((float)m_spot.y() * ( (float)m_h / (float)old_h)));
+
+ updatePixmap();
+}
+
+void PerspectiveWidget::mousePressEvent ( TQMouseEvent * e )
+{
+ if ( e->button() == TQt::LeftButton &&
+ m_rect.contains( e->x(), e->y() ))
+ {
+ if ( m_topLeftCorner.contains( e->x(), e->y() ) )
+ m_currentResizing = ResizingTopLeft;
+ else if ( m_bottomRightCorner.contains( e->x(), e->y() ) )
+ m_currentResizing = ResizingBottomRight;
+ else if ( m_topRightCorner.contains( e->x(), e->y() ) )
+ m_currentResizing = ResizingTopRight;
+ else if ( m_bottomLeftCorner.contains( e->x(), e->y() ) )
+ m_currentResizing = ResizingBottomLeft;
+ else
+ {
+ m_spot.setX(e->x()-m_rect.x());
+ m_spot.setY(e->y()-m_rect.y());
+ }
+ }
+}
+
+void PerspectiveWidget::mouseReleaseEvent ( TQMouseEvent * e )
+{
+ if ( m_currentResizing != ResizingNone )
+ {
+ unsetCursor();
+ m_currentResizing = ResizingNone;
+
+ // in this case, the pixmap has not been drawn on mouse move
+ if (!m_drawWhileMoving)
+ {
+ updatePixmap();
+ repaint(false);
+ }
+ }
+ else
+ {
+ m_spot.setX(e->x()-m_rect.x());
+ m_spot.setY(e->y()-m_rect.y());
+ updatePixmap();
+ repaint(false);
+ }
+}
+
+void PerspectiveWidget::mouseMoveEvent ( TQMouseEvent * e )
+{
+ if ( e->state() == TQt::LeftButton )
+ {
+ if ( m_currentResizing != ResizingNone )
+ {
+ TQPointArray unsablePoints;
+ TQPoint pm(e->x(), e->y());
+
+ if (!m_rect.contains( pm ))
+ {
+ if (pm.x() > m_rect.right())
+ pm.setX(m_rect.right());
+ else if (pm.x() < m_rect.left())
+ pm.setX(m_rect.left());
+
+ if (pm.y() > m_rect.bottom())
+ pm.setY(m_rect.bottom());
+ else if (pm.y() < m_rect.top())
+ pm.setY(m_rect.top());
+ }
+
+ if ( m_currentResizing == ResizingTopLeft )
+ {
+ unsablePoints.putPoints(0, 7,
+ m_w-1, m_h-1,
+ 0, m_h-1,
+ 0, m_bottomLeftPoint.y()-10,
+ m_bottomLeftPoint.x(), m_bottomLeftPoint.y()-10,
+ m_topRightPoint.x()-10, m_topRightPoint.y(),
+ m_topRightPoint.x()-10, 0,
+ m_w-1, 0 );
+ TQRegion unsableArea(unsablePoints);
+
+ if ( unsableArea.contains(pm) ) return;
+
+ m_topLeftPoint = pm - m_rect.topLeft();
+ setCursor( KCursor::sizeFDiagCursor() );
+ }
+
+ else if ( m_currentResizing == ResizingTopRight )
+ {
+ unsablePoints.putPoints(0, 7,
+ 0, m_h-1,
+ 0, 0,
+ m_topLeftPoint.x()+10, 0,
+ m_topLeftPoint.x()+10, m_topLeftPoint.y(),
+ m_bottomRightPoint.x(), m_bottomRightPoint.y()-10,
+ m_w-1, m_bottomRightPoint.y()-10,
+ m_w-1, m_h-1);
+ TQRegion unsableArea(unsablePoints);
+
+ if ( unsableArea.contains(pm) ) return;
+
+ m_topRightPoint = pm - m_rect.topLeft();
+ setCursor( KCursor::sizeBDiagCursor() );
+ }
+
+ else if ( m_currentResizing == ResizingBottomLeft )
+ {
+ unsablePoints.putPoints(0, 7,
+ m_w-1, 0,
+ m_w-1, m_h-1,
+ m_bottomRightPoint.x()-10, m_h-1,
+ m_bottomRightPoint.x()-10, m_bottomRightPoint.y()+10,
+ m_topLeftPoint.x(), m_topLeftPoint.y()+10,
+ 0, m_topLeftPoint.y(),
+ 0, 0);
+ TQRegion unsableArea(unsablePoints);
+
+ if ( unsableArea.contains(pm) ) return;
+
+ m_bottomLeftPoint = pm - m_rect.topLeft();
+ setCursor( KCursor::sizeBDiagCursor() );
+ }
+
+ else if ( m_currentResizing == ResizingBottomRight )
+ {
+ unsablePoints.putPoints(0, 7,
+ 0, 0,
+ m_w-1, 0,
+ m_w-1, m_topRightPoint.y()+10,
+ m_topRightPoint.x(), m_topRightPoint.y()+10,
+ m_bottomLeftPoint.x()+10, m_bottomLeftPoint.y(),
+ m_bottomLeftPoint.x()+10, m_w-1,
+ 0, m_w-1);
+ TQRegion unsableArea(unsablePoints);
+
+ if ( unsableArea.contains(pm) ) return;
+
+ m_bottomRightPoint = pm - m_rect.topLeft();
+ setCursor( KCursor::sizeFDiagCursor() );
+ }
+
+ else
+ {
+ m_spot.setX(e->x()-m_rect.x());
+ m_spot.setY(e->y()-m_rect.y());
+ }
+
+ updatePixmap();
+ repaint(false);
+ }
+ }
+ else
+ {
+ if ( m_topLeftCorner.contains( e->x(), e->y() ) ||
+ m_bottomRightCorner.contains( e->x(), e->y() ) )
+ setCursor( KCursor::sizeFDiagCursor() );
+
+ else if ( m_topRightCorner.contains( e->x(), e->y() ) ||
+ m_bottomLeftCorner.contains( e->x(), e->y() ) )
+ setCursor( KCursor::sizeBDiagCursor() );
+ else
+ unsetCursor();
+ }
+}
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
diff --git a/src/imageplugins/perspective/perspectivewidget.h b/src/imageplugins/perspective/perspectivewidget.h
new file mode 100644
index 00000000..0047c3e8
--- /dev/null
+++ b/src/imageplugins/perspective/perspectivewidget.h
@@ -0,0 +1,172 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-18
+ * Description : a widget class to edit perspective.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef PERSPECTIVEWIDGET_H
+#define PERSPECTIVEWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqpoint.h>
+#include <tqpointarray.h>
+#include <tqcolor.h>
+#include <tqrect.h>
+
+// Digikam includes.
+
+#include "dimg.h"
+
+// Local includes.
+
+#include "matrix.h"
+
+class TQPixmap;
+
+namespace Digikam
+{
+class ImageIface;
+}
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class PerspectiveWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ PerspectiveWidget(int width, int height, TQWidget *parent=0);
+ ~PerspectiveWidget();
+
+ TQRect getTargetSize(void);
+ TQPoint getTopLeftCorner(void);
+ TQPoint getTopRightCorner(void);
+ TQPoint getBottomLeftCorner(void);
+ TQPoint getBottomRightCorner(void);
+ void reset(void);
+
+ float getAngleTopLeft(void);
+ float getAngleTopRight(void);
+ float getAngleBottomLeft(void);
+ float getAngleBottomRight(void);
+
+ void applyPerspectiveAdjustment(void);
+
+ Digikam::ImageIface* imageIface();
+
+public slots:
+
+ void slotToggleAntiAliasing(bool a);
+ void slotToggleDrawWhileMoving(bool draw);
+ void slotToggleDrawGrid(bool grid);
+
+ void slotChangeGuideColor(const TQColor &color);
+ void slotChangeGuideSize(int size);
+
+signals:
+
+ void signalPerspectiveChanged( TQRect newSize, float topLeftAngle, float topRightAngle,
+ float bottomLeftAngle, float bottomRightAngle );
+
+protected:
+
+ void paintEvent( TQPaintEvent *e );
+ void resizeEvent( TQResizeEvent * e );
+ void mousePressEvent ( TQMouseEvent * e );
+ void mouseReleaseEvent ( TQMouseEvent * e );
+ void mouseMoveEvent ( TQMouseEvent * e );
+
+private: // Widget methods.
+
+ void updatePixmap(void);
+
+ void transformAffine(Digikam::DImg *orgImage, Digikam::DImg *destImage,
+ const Matrix &matrix, Digikam::DColor background);
+
+ TQPoint buildPerspective(TQPoint orignTopLeft, TQPoint orignBottomRight,
+ TQPoint transTopLeft, TQPoint transTopRight,
+ TQPoint transBottomLeft, TQPoint transBottomRight,
+ Digikam::DImg *orgImage=0, Digikam::DImg *destImage=0,
+ Digikam::DColor background=Digikam::DColor());
+
+private:
+
+ enum ResizingMode
+ {
+ ResizingNone = 0,
+ ResizingTopLeft,
+ ResizingTopRight,
+ ResizingBottomLeft,
+ ResizingBottomRight
+ };
+
+ bool m_antiAlias;
+ bool m_drawWhileMoving;
+ bool m_drawGrid;
+
+ uint *m_data;
+ int m_w;
+ int m_h;
+ int m_origW;
+ int m_origH;
+
+ int m_currentResizing;
+
+ int m_guideSize;
+
+ TQRect m_rect;
+
+ // Tranformed center area for mouse position control.
+
+ TQPoint m_transformedCenter;
+
+ // Draggable local region selection corners.
+
+ TQRect m_topLeftCorner;
+ TQRect m_topRightCorner;
+ TQRect m_bottomLeftCorner;
+ TQRect m_bottomRightCorner;
+
+ TQPoint m_topLeftPoint;
+ TQPoint m_topRightPoint;
+ TQPoint m_bottomLeftPoint;
+ TQPoint m_bottomRightPoint;
+ TQPoint m_spot;
+
+ TQColor m_guideColor;
+
+ // 60 points will be stored to compute a grid of 15x15 lines.
+ TQPointArray m_grid;
+
+ TQPixmap *m_pixmap;
+
+ Digikam::ImageIface *m_iface;
+ Digikam::DImg m_previewImage;
+};
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
+#endif /* PERSPECTIVEWIDGET_H */
diff --git a/src/imageplugins/perspective/triangle.cpp b/src/imageplugins/perspective/triangle.cpp
new file mode 100644
index 00000000..84f80a07
--- /dev/null
+++ b/src/imageplugins/perspective/triangle.cpp
@@ -0,0 +1,65 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-18
+ * Description : triangle geometry calculation class.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+
+// Local includes.
+
+#include "triangle.h"
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+Triangle::Triangle(TQPoint A, TQPoint B, TQPoint C)
+{
+ m_a = distanceP2P(B, C);
+ m_b = distanceP2P(A, C);
+ m_c = distanceP2P(A, B);
+}
+
+float Triangle::angleABC(void)
+{
+ return( 57.295779513082 * acos( (m_b*m_b - m_a*m_a - m_c*m_c ) / (-2*m_a*m_c ) ) );
+}
+
+float Triangle::angleACB(void)
+{
+ return( 57.295779513082 * acos( (m_c*m_c - m_a*m_a - m_b*m_b ) / (-2*m_a*m_b ) ) );
+}
+
+float Triangle::angleBAC(void)
+{
+ return( 57.295779513082 * acos( (m_a*m_a - m_b*m_b - m_c*m_c ) / (-2*m_b*m_c ) ) );
+}
+
+float Triangle::distanceP2P(const TQPoint& p1, const TQPoint& p2)
+{
+ return(sqrt( abs( p2.x()-p1.x() ) * abs( p2.x()-p1.x() ) +
+ abs( p2.y()-p1.y() ) * abs( p2.y()-p1.y() ) ));
+}
+
+} // NameSpace DigikamPerspectiveImagesPlugin
diff --git a/src/imageplugins/perspective/triangle.h b/src/imageplugins/perspective/triangle.h
new file mode 100644
index 00000000..27fcc087
--- /dev/null
+++ b/src/imageplugins/perspective/triangle.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-18
+ * Description : triangle geometry calculation class.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef TRIANGLE_H
+#define TRIANGLE_H
+
+// TQt includes.
+
+#include <tqpoint.h>
+
+namespace DigikamPerspectiveImagesPlugin
+{
+
+class Triangle
+{
+
+public:
+
+ Triangle(TQPoint A, TQPoint B, TQPoint C);
+ ~Triangle(){};
+
+ float angleABC(void);
+ float angleACB(void);
+ float angleBAC(void);
+
+private:
+
+ float m_a;
+ float m_b;
+ float m_c;
+
+ float distanceP2P(const TQPoint& p1, const TQPoint& p2);
+};
+
+} // NameSpace DigikamPerspectiveImagesPlugin
+
+#endif /* TRIANGLE_H */
diff --git a/src/imageplugins/raindrop/Makefile.am b/src/imageplugins/raindrop/Makefile.am
new file mode 100644
index 00000000..29899232
--- /dev/null
+++ b/src/imageplugins/raindrop/Makefile.am
@@ -0,0 +1,34 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_raindrop_la_SOURCES = imageplugin_raindrop.cpp \
+ raindroptool.cpp raindrop.cpp
+
+digikamimageplugin_raindrop_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_raindrop_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_raindrop.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_raindrop.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_raindrop_ui.rc
+
diff --git a/src/imageplugins/raindrop/digikamimageplugin_raindrop.desktop b/src/imageplugins/raindrop/digikamimageplugin_raindrop.desktop
new file mode 100644
index 00000000..847411b7
--- /dev/null
+++ b/src/imageplugins/raindrop/digikamimageplugin_raindrop.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_RainDrop
+Name[bg]=Приставка за снимки - Дъждовни капки
+Name[da]=Billedplugin_Regndråber
+Name[el]=ΠροσθετοΕικόνας_Βροχή
+Name[fi]=Sadepisarat
+Name[hr]=Kišne kapi
+Name[it]=PluginImmagini_GocciaDiPioggia
+Name[nl]=Afbeeldingsplugin_Regendruppels
+Name[sr]=Кишне капи
+Name[sr@Latn]=Kišne kapi
+Name[sv]=Insticksprogram för regndroppar
+Name[tr]=ResimEklentisi_YağmurDamlaları
+Name[vi]=ImagePlugin_Perspective
+Name[xx]=xxImagePlugin_RainDropxx
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Rain dropping image effect plugin for digiKam
+Comment[bg]=Приставка на digiKam за добавяне на дъждовни капки
+Comment[ca]=Connector pel digiKam d'efecte d'imatge de gotes de pluja
+Comment[da]=Plugin til regndråbeeffekt på billeder i Digikam
+Comment[de]=digiKam-Modul zum Erzeugen eines Regentropfeneffektes
+Comment[el]=Πρόσθετο εφέ πτώσης βροχής για το digiKam
+Comment[es]=Plugin para digiKam de efectos de gotas de lluvia
+Comment[et]=DigiKami vihmapiiskade pildiefektiplugin
+Comment[fa]=وصلۀ جلوۀ تصویر بارش باران برای digiKam
+Comment[fi]=Lisää kuvan pintaan sadepisaroita
+Comment[gl]=Un plugin de digiKam para criar un efeito de pingas de chuvia
+Comment[hr]=digiKam dodatak za efekt padanja kiše
+Comment[is]=Íforrit fyrir digiKam sem setur inn regndropa!!!
+Comment[it]=Plugin per l'effetto a goccia di pioggia delle immagini per digiKam
+Comment[ja]=digiKam 雨滴効果プラグイン
+Comment[ms]=Plugin kesan imej titis hujan untuk digiKam
+Comment[nds]=digiKam-Moduul för Regendrüppeneffekten
+Comment[nl]=Digikam-plugin voor regendruppels
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਕਣੀ ਚਿੱਤਰ ਪਰਭਾਵ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam dodająca efekt kropel deszczu na obrazie
+Comment[pt]=Um 'plugin' do digiKam para criar um efeito de pingos de chuva
+Comment[pt_BR]=Um 'plugin' do digiKam para criar um efeito de pingos de chuva
+Comment[ru]=Модуль эффект "идущего дождя" для digiKam
+Comment[sk]=digiKam plugin pre efekt padajúcich kvapiek
+Comment[sr]=digiKam-ов прикључак за ефекат кишних капи у слици
+Comment[sr@Latn]=digiKam-ov priključak za efekat kišnih kapi u slici
+Comment[sv]=Digikam insticksprogram för regndroppsbildeffekt
+Comment[tr]=digiKam için yağmur damlaları eklentisi
+Comment[uk]=Втулок ефекту падання крапель для digiKam
+Comment[vi]=Phần bổ sung hiệu ứng ảnh giọt mưa cho digiKam
+Comment[xx]=xxRain dropping image effect plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_raindrop
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/raindrop/digikamimageplugin_raindrop_ui.rc b/src/imageplugins/raindrop/digikamimageplugin_raindrop_ui.rc
new file mode 100644
index 00000000..cf28a3f6
--- /dev/null
+++ b/src/imageplugins/raindrop/digikamimageplugin_raindrop_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_raindrop" >
+
+ <MenuBar>
+
+ <Menu name="Filters" ><text>F&amp;ilters</text>
+ <Action name="imageplugin_raindrop" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_raindrop" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/raindrop/imageeffect_raindrop.cpp b/src/imageplugins/raindrop/imageeffect_raindrop.cpp
new file mode 100644
index 00000000..8a82829d
--- /dev/null
+++ b/src/imageplugins/raindrop/imageeffect_raindrop.cpp
@@ -0,0 +1,259 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-30
+ * Description : a plugin to add rain drop over an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "raindrop.h"
+#include "imageeffect_raindrop.h"
+#include "imageeffect_raindrop.moc"
+
+namespace DigikamRainDropImagesPlugin
+{
+
+ImageEffect_RainDrop::ImageEffect_RainDrop(TQWidget* parent)
+ : Digikam::ImageGuideDlg(parent, i18n("Add Raindrops to Photograph"),
+ "raindrops", false, true, false,
+ Digikam::ImageGuideWidget::HVGuideMode)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Raindrops"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to add raindrops to an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2005, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Pieter Z. Voloshyn", I18N_NOOP("Raindrops algorithm"),
+ "pieter dot voloshyn at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ TQWhatsThis::add( m_imagePreviewWidget, i18n("<p>This is the preview of the Raindrop effect."
+ "<p>Note: if you have previously selected an area in the editor, "
+ "this will be unaffected by the filter. You can use this method to "
+ "disable the Raindrops effect on a human face, for example.") );
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 5, 2, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Drop size:"), gboxSettings);
+
+ m_dropInput = new KIntNumInput(gboxSettings);
+ m_dropInput->setRange(0, 200, 1, true);
+ m_dropInput->setValue(80);
+ TQWhatsThis::add( m_dropInput, i18n("<p>Set here the raindrops' size."));
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 2);
+ gridSettings->addMultiCellWidget(m_dropInput, 1, 1, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Number:"), gboxSettings);
+
+ m_amountInput = new KIntNumInput(gboxSettings);
+ m_amountInput->setRange(1, 500, 1, true);
+ m_amountInput->setValue(150);
+ TQWhatsThis::add( m_amountInput, i18n("<p>This value controls the maximum number of raindrops."));
+
+ gridSettings->addMultiCellWidget(label2, 2, 2, 0, 2);
+ gridSettings->addMultiCellWidget(m_amountInput, 3, 3, 0, 2);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Fish eyes:"), gboxSettings);
+
+ m_coeffInput = new KIntNumInput(gboxSettings);
+ m_coeffInput->setRange(1, 100, 1, true);
+ m_coeffInput->setValue(30);
+ TQWhatsThis::add( m_coeffInput, i18n("<p>This value is the fish-eye-effect optical "
+ "distortion coefficient."));
+
+ gridSettings->addMultiCellWidget(label3, 4, 4, 0, 2);
+ gridSettings->addMultiCellWidget(m_coeffInput, 5, 5, 0, 2);
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_dropInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_amountInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_coeffInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_RainDrop::~ImageEffect_RainDrop()
+{
+}
+
+void ImageEffect_RainDrop::renderingFinished()
+{
+ m_dropInput->setEnabled(true);
+ m_amountInput->setEnabled(true);
+ m_coeffInput->setEnabled(true);
+}
+
+void ImageEffect_RainDrop::readUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("raindrops Tool Dialog");
+
+ m_dropInput->blockSignals(true);
+ m_amountInput->blockSignals(true);
+ m_coeffInput->blockSignals(true);
+
+ m_dropInput->setValue(config->readNumEntry("DropAdjustment", 80));
+ m_amountInput->setValue(config->readNumEntry("AmountAdjustment", 150));
+ m_coeffInput->setValue(config->readNumEntry("CoeffAdjustment", 30));
+
+ m_dropInput->blockSignals(false);
+ m_amountInput->blockSignals(false);
+ m_coeffInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void ImageEffect_RainDrop::writeUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("raindrops Tool Dialog");
+ config->writeEntry("DropAdjustment", m_dropInput->value());
+ config->writeEntry("AmountAdjustment", m_amountInput->value());
+ config->writeEntry("CoeffAdjustment", m_coeffInput->value());
+ config->sync();
+}
+
+void ImageEffect_RainDrop::resetValues()
+{
+ m_dropInput->blockSignals(true);
+ m_amountInput->blockSignals(true);
+ m_coeffInput->blockSignals(true);
+
+ m_dropInput->setValue(80);
+ m_amountInput->setValue(150);
+ m_coeffInput->setValue(30);
+
+ m_dropInput->blockSignals(false);
+ m_amountInput->blockSignals(false);
+ m_coeffInput->blockSignals(false);
+}
+
+void ImageEffect_RainDrop::prepareEffect()
+{
+ m_dropInput->setEnabled(false);
+ m_amountInput->setEnabled(false);
+ m_coeffInput->setEnabled(false);
+
+ int d = m_dropInput->value();
+ int a = m_amountInput->value();
+ int c = m_coeffInput->value();
+
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+
+ // Selected data from the image
+ TQRect selection( iface->selectedXOrg(), iface->selectedYOrg(),
+ iface->selectedWidth(), iface->selectedHeight() );
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new RainDrop(iface->getOriginalImg(), this, d, a, c, &selection));
+}
+
+void ImageEffect_RainDrop::prepareFinal()
+{
+ m_dropInput->setEnabled(false);
+ m_amountInput->setEnabled(false);
+ m_coeffInput->setEnabled(false);
+
+ int d = m_dropInput->value();
+ int a = m_amountInput->value();
+ int c = m_coeffInput->value();
+
+ Digikam::ImageIface iface(0, 0);
+
+ // Selected data from the image
+ TQRect selection( iface.selectedXOrg(), iface.selectedYOrg(),
+ iface.selectedWidth(), iface.selectedHeight() );
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new RainDrop(iface.getOriginalImg(), this, d, a, c, &selection));
+}
+
+void ImageEffect_RainDrop::putPreviewData(void)
+{
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage()
+ .smoothScale(iface->previewWidth(), iface->previewHeight());
+ iface->putPreviewImage(imDest.bits());
+
+ m_imagePreviewWidget->updatePreview();
+}
+
+void ImageEffect_RainDrop::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("RainDrop"),
+ m_threadedFilter->getTargetImage().bits());
+}
+
+} // NameSpace DigikamRainDropImagesPlugin
+
diff --git a/src/imageplugins/raindrop/imageeffect_raindrop.h b/src/imageplugins/raindrop/imageeffect_raindrop.h
new file mode 100644
index 00000000..fe567ba3
--- /dev/null
+++ b/src/imageplugins/raindrop/imageeffect_raindrop.h
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-30
+ * Description : a plugin to add rain drop over an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_RAINDROP_H
+#define IMAGEEFFECT_RAINDROP_H
+
+// Digikam includes.
+
+#include "imageguidedlg.h"
+
+class KIntNumInput;
+
+namespace DigikamRainDropImagesPlugin
+{
+
+class ImageEffect_RainDrop : public Digikam::ImageGuideDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_RainDrop(TQWidget *parent);
+ ~ImageEffect_RainDrop();
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KIntNumInput *m_dropInput;
+ KIntNumInput *m_amountInput;
+ KIntNumInput *m_coeffInput;
+};
+
+} // NameSpace DigikamRainDropImagesPlugin
+
+#endif /* IMAGEEFFECT_RAINDROP_H */
diff --git a/src/imageplugins/raindrop/imageplugin_raindrop.cpp b/src/imageplugins/raindrop/imageplugin_raindrop.cpp
new file mode 100644
index 00000000..20744961
--- /dev/null
+++ b/src/imageplugins/raindrop/imageplugin_raindrop.cpp
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-30
+ * Description : a plugin to add rain drop over an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "raindroptool.h"
+#include "imageplugin_raindrop.h"
+#include "imageplugin_raindrop.moc"
+
+using namespace DigikamRainDropImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_raindrop,
+ KGenericFactory<ImagePlugin_RainDrop>("digikamimageplugin_raindrop"));
+
+ImagePlugin_RainDrop::ImagePlugin_RainDrop(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_RainDrop")
+{
+ m_raindropAction = new TDEAction(i18n("Raindrops..."), "raindrop", 0,
+ this, TQ_SLOT(slotRainDrop()),
+ actionCollection(), "imageplugin_raindrop");
+
+ setXMLFile( "digikamimageplugin_raindrop_ui.rc" );
+
+ DDebug() << "ImagePlugin_RainDrop plugin loaded" << endl;
+}
+
+ImagePlugin_RainDrop::~ImagePlugin_RainDrop()
+{
+}
+
+void ImagePlugin_RainDrop::setEnabledActions(bool enable)
+{
+ m_raindropAction->setEnabled(enable);
+}
+
+void ImagePlugin_RainDrop::slotRainDrop()
+{
+ RainDropTool *raindrop = new RainDropTool(this);
+ loadTool(raindrop);
+}
diff --git a/src/imageplugins/raindrop/imageplugin_raindrop.h b/src/imageplugins/raindrop/imageplugin_raindrop.h
new file mode 100644
index 00000000..a85076f8
--- /dev/null
+++ b/src/imageplugins/raindrop/imageplugin_raindrop.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-30
+ * Description : a plugin to add rain drop over an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_RAINDROP_H
+#define IMAGEPLUGIN_RAINDROP_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_RainDrop : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_RainDrop(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_RainDrop();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotRainDrop();
+
+private:
+
+ TDEAction *m_raindropAction;
+};
+
+#endif /* IMAGEPLUGIN_RAINDROP_H */
diff --git a/src/imageplugins/raindrop/raindrop.cpp b/src/imageplugins/raindrop/raindrop.cpp
new file mode 100644
index 00000000..7be977fc
--- /dev/null
+++ b/src/imageplugins/raindrop/raindrop.cpp
@@ -0,0 +1,457 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Raindrop threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
+ *
+ * Original RainDrop algorithm copyrighted 2004-2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqdeepcopy.h>
+#include <tqdatetime.h>
+#include <tqrect.h>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "raindrop.h"
+
+namespace DigikamRainDropImagesPlugin
+{
+
+RainDrop::RainDrop(Digikam::DImg *orgImage, TQObject *parent, int drop,
+ int amount, int coeff, TQRect *selection)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "RainDrop")
+{
+ m_drop = drop;
+ m_amount = amount;
+ m_coeff = coeff;
+
+ m_selectedX = m_selectedY = m_selectedW = m_selectedH = 0;
+
+ if ( selection )
+ {
+ m_selectedX = selection->left();
+ m_selectedY = selection->top();
+ m_selectedW = selection->width();
+ m_selectedH = selection->height();
+ }
+
+ initFilter();
+}
+
+void RainDrop::filterImage(void)
+{
+ int w = m_orgImage.width();
+ int h = m_orgImage.height();
+
+ // If we have a region selection in image, use it to apply the filter modification around,
+ // else, applied the filter on the full image.
+
+ if (m_selectedW && m_selectedH)
+ {
+ Digikam::DImg zone1, zone2, zone3, zone4,
+ zone1Dest, zone2Dest, zone3Dest, zone4Dest,
+ selectedImg;
+ selectedImg = m_orgImage.copy(m_selectedX, m_selectedY, m_selectedW, m_selectedH);
+
+ // Cut the original image in 4 areas without clipping region.
+
+ zone1 = m_orgImage.copy(0, 0, m_selectedX, w);
+ zone2 = m_orgImage.copy(m_selectedX, 0, m_selectedX + m_selectedW, m_selectedY);
+ zone3 = m_orgImage.copy(m_selectedX, m_selectedY + m_selectedH, m_selectedX + m_selectedW, h);
+ zone4 = m_orgImage.copy(m_selectedX + m_selectedW, 0, w, h);
+
+ zone1Dest = Digikam::DImg(zone1.width(), zone1.height(), zone1.sixteenBit(), zone1.hasAlpha());
+ zone2Dest = Digikam::DImg(zone2.width(), zone2.height(), zone2.sixteenBit(), zone2.hasAlpha());
+ zone3Dest = Digikam::DImg(zone3.width(), zone3.height(), zone3.sixteenBit(), zone3.hasAlpha());
+ zone4Dest = Digikam::DImg(zone4.width(), zone4.height(), zone4.sixteenBit(), zone4.hasAlpha());
+
+ // Apply effect on each area.
+
+ rainDropsImage(&zone1, &zone1Dest, 0, m_drop, m_amount, m_coeff, true, 0, 25);
+ rainDropsImage(&zone2, &zone2Dest, 0, m_drop, m_amount, m_coeff, true, 25, 50);
+ rainDropsImage(&zone3, &zone3Dest, 0, m_drop, m_amount, m_coeff, true, 50, 75);
+ rainDropsImage(&zone4, &zone4Dest, 0, m_drop, m_amount, m_coeff, true, 75, 100);
+
+ // Build the target image.
+
+ m_destImage.bitBltImage(&zone1Dest, 0, 0);
+ m_destImage.bitBltImage(&zone2Dest, m_selectedX, 0);
+ m_destImage.bitBltImage(&zone3Dest, m_selectedX, m_selectedY + m_selectedH);
+ m_destImage.bitBltImage(&zone4Dest, m_selectedX + m_selectedW, 0);
+ m_destImage.bitBltImage(&selectedImg, m_selectedX, m_selectedY);
+ }
+ else
+ {
+ rainDropsImage(&m_orgImage, &m_destImage, 0, m_drop, m_amount, m_coeff, true, 0, 100);
+ }
+}
+
+/* Function to apply the RainDrops effect backported from ImageProcessing version 2
+ *
+ * orgImage => The image
+ * MinDropSize => It's the minimum random size for rain drop.
+ * MaxDropSize => It's the minimum random size for rain drop.
+ * Amount => It's the maximum number for rain drops inside the image.
+ * Coeff => It's the fisheye's coefficient.
+ * bLimitRange => If true, the drop will not be cut.
+ * progressMin => Min. value for progress bar (can be different if using clipping area).
+ * progressMax => Max. value for progress bar (can be different if using clipping area).
+ *
+ * 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=MaxDropSize)
+ * will be applied, after this, a shadow will be applied too.
+ * and after this, a blur function will finish the effect.
+ */
+void RainDrop::rainDropsImage(Digikam::DImg *orgImage, Digikam::DImg *destImage, int MinDropSize, int MaxDropSize,
+ int Amount, int Coeff, bool bLimitRange, int progressMin, int progressMax)
+{
+ bool bResp;
+ int nRandSize, i;
+ int nRandX, nRandY;
+ int nCounter = 0;
+ int nWidth = orgImage->width();
+ int nHeight = orgImage->height();
+ bool sixteenBit = orgImage->sixteenBit();
+ int bytesDepth = orgImage->bytesDepth();
+ uchar *data = orgImage->bits();
+ uchar *pResBits = destImage->bits();
+
+ if (Amount <= 0)
+ return;
+
+ if (MinDropSize >= MaxDropSize)
+ MaxDropSize = MinDropSize + 1;
+
+ if (MaxDropSize <= 0)
+ return;
+
+ uchar *pStatusBits = new uchar[nHeight * nWidth];
+ memset(pStatusBits, 0, sizeof(nHeight * nWidth));
+
+ // Initially, copy all pixels to destination
+
+ destImage->bitBltImage(orgImage, 0, 0);
+
+ // Randomize.
+
+ TQDateTime dt = TQDateTime::currentDateTime();
+ TQDateTime Y2000( TQDate(2000, 1, 1), TQTime(0, 0, 0) );
+ uint seed = dt.secsTo(Y2000);
+
+ for (i = 0; !m_cancel && (i < Amount); i++)
+ {
+ nCounter = 0;
+
+ do
+ {
+ nRandX = (int)(rand_r(&seed) * ((double)( nWidth - 1) / RAND_MAX));
+ nRandY = (int)(rand_r(&seed) * ((double)(nHeight - 1) / RAND_MAX));
+
+ nRandSize = (rand() % (MaxDropSize - MinDropSize)) + MinDropSize;
+
+ bResp = CreateRainDrop (data, nWidth, nHeight, sixteenBit, bytesDepth,
+ pResBits, pStatusBits,
+ nRandX, nRandY, nRandSize, Coeff, bLimitRange);
+
+ nCounter++;
+ }
+ while ((bResp == false) && (nCounter < 10000) && !m_cancel);
+
+ // Update the progress bar in dialog.
+ if (nCounter >= 10000)
+ {
+ i = Amount;
+
+ postProgress(progressMax);
+ break;
+ }
+
+ postProgress( (int)(progressMin + ((double)(i) *
+ (double)(progressMax-progressMin)) / (double)Amount) );
+ }
+
+ delete [] pStatusBits;
+}
+
+bool RainDrop::CreateRainDrop(uchar *pBits, int Width, int Height, bool sixteenBit, int bytesDepth,
+ uchar *pResBits, uchar* pStatusBits,
+ int X, int Y, int DropSize, double Coeff, bool bLimitRange)
+{
+ int w, h, nw1, nh1, nw2, nh2;
+ int nHalfSize = DropSize / 2;
+ int nBright;
+ double lfRadius, lfOldRadius, lfAngle, lfDiv;
+
+ Digikam::DColor imageData;
+
+ uint nTotalR, nTotalG, nTotalB, offset;
+ int nBlurPixels, nBlurRadius;
+
+ if (CanBeDropped(Width, Height, pStatusBits, X, Y, DropSize, bLimitRange))
+ {
+ Coeff *= 0.01;
+ lfDiv = (double)nHalfSize / log (Coeff * (double)nHalfSize + 1.0);
+
+ for (h = -nHalfSize; !m_cancel && (h <= nHalfSize); h++)
+ {
+ for (w = -nHalfSize; !m_cancel && (w <= nHalfSize); w++)
+ {
+ lfRadius = sqrt (h * h + w * w);
+ lfAngle = atan2 ((double)h, (double)w);
+
+ if (lfRadius <= (double)nHalfSize)
+ {
+ lfOldRadius = lfRadius;
+ lfRadius = (exp (lfRadius / lfDiv) - 1.0) / Coeff;
+
+ nw1 = (int)((double)X + lfRadius * cos (lfAngle));
+ nh1 = (int)((double)Y + lfRadius * sin (lfAngle));
+
+ nw2 = X + w;
+ nh2 = Y + h;
+
+ if (IsInside(Width, Height, nw1, nh1))
+ {
+ if (IsInside(Width, Height, nw2, nh2))
+ {
+ nBright = 0;
+
+ if (lfOldRadius >= 0.9 * (double)nHalfSize)
+ {
+ if ((lfAngle >= 0.0) && (lfAngle < 2.25))
+ nBright = -80;
+ else if ((lfAngle >= 2.25) && (lfAngle < 2.5))
+ nBright = -40;
+ else if ((lfAngle >= -0.25) && (lfAngle < 0.0))
+ nBright = -40;
+ }
+
+ else if (lfOldRadius >= 0.8 * (double)nHalfSize)
+ {
+ if ((lfAngle >= 0.75) && (lfAngle < 1.50))
+ nBright = -40;
+ else if ((lfAngle >= -0.10) && (lfAngle < 0.75))
+ nBright = -30;
+ else if ((lfAngle >= 1.50) && (lfAngle < 2.35))
+ nBright = -30;
+ }
+
+ else if (lfOldRadius >= 0.7 * (double)nHalfSize)
+ {
+ if ((lfAngle >= 0.10) && (lfAngle < 2.0))
+ nBright = -20;
+ else if ((lfAngle >= -2.50) && (lfAngle < -1.90))
+ nBright = 60;
+ }
+
+ else if (lfOldRadius >= 0.6 * (double)nHalfSize)
+ {
+ if ((lfAngle >= 0.50) && (lfAngle < 1.75))
+ nBright = -20;
+ else if ((lfAngle >= 0.0) && (lfAngle < 0.25))
+ nBright = 20;
+ else if ((lfAngle >= 2.0) && (lfAngle < 2.25))
+ nBright = 20;
+ }
+
+ else if (lfOldRadius >= 0.5 * (double)nHalfSize)
+ {
+ if ((lfAngle >= 0.25) && (lfAngle < 0.50))
+ nBright = 30;
+ else if ((lfAngle >= 1.75 ) && (lfAngle < 2.0))
+ nBright = 30;
+ }
+
+ else if (lfOldRadius >= 0.4 * (double)nHalfSize)
+ {
+ if ((lfAngle >= 0.5) && (lfAngle < 1.75))
+ nBright = 40;
+ }
+
+ else if (lfOldRadius >= 0.3 * (double)nHalfSize)
+ {
+ if ((lfAngle >= 0.0) && (lfAngle < 2.25))
+ nBright = 30;
+ }
+
+ else if (lfOldRadius >= 0.2 * (double)nHalfSize)
+ {
+ if ((lfAngle >= 0.5) && (lfAngle < 1.75))
+ nBright = 20;
+ }
+
+ imageData.setColor(pBits + Offset(Width, nw1, nh1, bytesDepth), sixteenBit);
+
+ if (sixteenBit)
+ {
+ // convert difference to 16-bit range
+ if (nBright > 0)
+ nBright = (nBright + 1) * 256 - 1;
+ else
+ nBright = (nBright - 1) * 256 + 1;
+
+ imageData.setRed (LimitValues16(imageData.red() + nBright));
+ imageData.setGreen(LimitValues16(imageData.green() + nBright));
+ imageData.setBlue (LimitValues16(imageData.blue() + nBright));
+ }
+ else
+ {
+ imageData.setRed (LimitValues8(imageData.red() + nBright));
+ imageData.setGreen(LimitValues8(imageData.green() + nBright));
+ imageData.setBlue (LimitValues8(imageData.blue() + nBright));
+ }
+
+ imageData.setPixel(pResBits + Offset(Width, nw2, nh2, bytesDepth));
+
+ }
+ }
+ }
+ }
+ }
+
+ nBlurRadius = DropSize / 25 + 1;
+
+ for (h = -nHalfSize - nBlurRadius; !m_cancel && (h <= nHalfSize + nBlurRadius); h++)
+ {
+ for (w = -nHalfSize - nBlurRadius; !m_cancel && (w <= nHalfSize + nBlurRadius); w++)
+ {
+ lfRadius = sqrt (h * h + w * w);
+
+ if (lfRadius <= (double)nHalfSize * 1.1)
+ {
+ nTotalR = nTotalG = nTotalB = 0;
+ nBlurPixels = 0;
+
+ for (nh1 = -nBlurRadius; !m_cancel && (nh1 <= nBlurRadius); nh1++)
+ {
+ for (nw1 = -nBlurRadius; !m_cancel && (nw1 <= nBlurRadius); nw1++)
+ {
+ nw2 = X + w + nw1;
+ nh2 = Y + h + nh1;
+
+ if (IsInside (Width, Height, nw2, nh2))
+ {
+ imageData.setColor(pResBits + Offset(Width, nw2, nh2, bytesDepth), sixteenBit);
+
+ nTotalR += imageData.red();
+ nTotalG += imageData.green();
+ nTotalB += imageData.blue();
+ nBlurPixels++;
+ }
+ }
+ }
+
+ nw1 = X + w;
+ nh1 = Y + h;
+
+ if (IsInside (Width, Height, nw1, nh1))
+ {
+ offset = Offset(Width, nw1, nh1, bytesDepth);
+
+ // to preserve alpha channel
+ imageData.setColor(pResBits + offset, sixteenBit);
+
+ imageData.setRed (nTotalR / nBlurPixels);
+ imageData.setGreen(nTotalG / nBlurPixels);
+ imageData.setBlue (nTotalB / nBlurPixels);
+
+ imageData.setPixel(pResBits + offset);
+ }
+ }
+ }
+ }
+
+ SetDropStatusBits (Width, Height, pStatusBits, X, Y, DropSize);
+ }
+ else
+ return (false);
+
+ return (true);
+}
+
+
+bool RainDrop::CanBeDropped(int Width, int Height, uchar *pStatusBits, int X, int Y,
+ int DropSize, bool bLimitRange)
+{
+ int w, h, i = 0;
+ int nHalfSize = DropSize / 2;
+
+ if (pStatusBits == NULL)
+ return (true);
+
+ for (h = Y - nHalfSize; h <= Y + nHalfSize; h++)
+ {
+ for (w = X - nHalfSize; w <= X + nHalfSize; w++)
+ {
+ if (IsInside (Width, Height, w, h))
+ {
+ i = h * Width + w;
+ if (pStatusBits[i])
+ return (false);
+ }
+ else
+ {
+ if (bLimitRange)
+ return (false);
+ }
+ }
+ }
+
+ return (true);
+}
+
+bool RainDrop::SetDropStatusBits (int Width, int Height, uchar *pStatusBits,
+ int X, int Y, int DropSize)
+{
+ int w, h, i = 0;
+ int nHalfSize = DropSize / 2;
+
+ if (pStatusBits == NULL)
+ return (false);
+
+ for (h = Y - nHalfSize; h <= Y + nHalfSize; h++)
+ {
+ for (w = X - nHalfSize; w <= X + nHalfSize; w++)
+ {
+ if (IsInside (Width, Height, w, h))
+ {
+ i = h * Width + w;
+ pStatusBits[i] = 255;
+ }
+ }
+ }
+
+ return (true);
+}
+
+} // NameSpace DigikamRainDropImagesPlugin
diff --git a/src/imageplugins/raindrop/raindrop.h b/src/imageplugins/raindrop/raindrop.h
new file mode 100644
index 00000000..9baca0d1
--- /dev/null
+++ b/src/imageplugins/raindrop/raindrop.h
@@ -0,0 +1,105 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Raindrop threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef RAINDROP_H
+#define RAINDROP_H
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+class TQRect;
+
+namespace DigikamRainDropImagesPlugin
+{
+
+class RainDrop : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ RainDrop(Digikam::DImg *orgImage, TQObject *parent=0, int drop=80,
+ int amount=150, int coeff=30, TQRect *selection=0L);
+
+ ~RainDrop(){};
+
+private:
+
+ virtual void filterImage(void);
+
+ void rainDropsImage(Digikam::DImg *orgImage, Digikam::DImg *destImage, int MinDropSize, int MaxDropSize,
+ int Amount, int Coeff, bool bLimitRange, int progressMin, int progressMax);
+
+ bool CreateRainDrop(uchar *pBits, int Width, int Height, bool sixteenBit, int bytesDepth,
+ uchar *pResBits, uchar* pStatusBits,
+ int X, int Y, int DropSize, double Coeff, bool bLimitRange);
+
+ bool CanBeDropped(int Width, int Height, uchar *pStatusBits, int X, int Y, int DropSize, bool bLimitRange);
+
+ bool SetDropStatusBits (int Width, int Height, uchar *pStatusBits, int X, int Y, int DropSize);
+
+ // 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.
+ inline int LimitValues8(int ColorValue)
+ {
+ if (ColorValue > 255) ColorValue = 255;
+ if (ColorValue < 0) ColorValue = 0;
+ return ColorValue;
+ };
+
+ inline int LimitValues16(int ColorValue)
+ {
+ if (ColorValue > 65535) ColorValue = 65535;
+ if (ColorValue < 0) ColorValue = 0;
+ return ColorValue;
+ };
+
+ inline bool IsInside (int Width, int Height, int X, int Y)
+ {
+ bool bIsWOk = ((X < 0) ? false : (X >= Width ) ? false : true);
+ bool bIsHOk = ((Y < 0) ? false : (Y >= Height) ? false : true);
+ return (bIsWOk && bIsHOk);
+ };
+
+ inline int Offset(int Width, int X, int Y, int bytesDepth)
+ {
+ return (Y * Width * bytesDepth + X * bytesDepth);
+ };
+
+private:
+
+ int m_drop;
+ int m_amount;
+ int m_coeff;
+
+ int m_selectedX;
+ int m_selectedY;
+ int m_selectedW;
+ int m_selectedH;
+};
+
+} // NameSpace DigikamRainDropImagesPlugin
+
+#endif /* RAINDROP_H */
diff --git a/src/imageplugins/raindrop/raindroptool.cpp b/src/imageplugins/raindrop/raindroptool.cpp
new file mode 100644
index 00000000..3d19238d
--- /dev/null
+++ b/src/imageplugins/raindrop/raindroptool.cpp
@@ -0,0 +1,254 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-30
+ * Description : a plugin to add rain drop over an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqframe.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "editortoolsettings.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "raindrop.h"
+#include "raindroptool.h"
+#include "raindroptool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamRainDropImagesPlugin
+{
+
+RainDropTool::RainDropTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("raindrops");
+ setToolName(i18n("Raindrops"));
+ setToolIcon(SmallIcon("raindrop"));
+
+ m_previewWidget = new ImageWidget("raindrops Tool", 0,
+ i18n("<p>This is the preview of the Raindrop effect."
+ "<p>Note: if you have previously selected an area in the editor, "
+ "this will be unaffected by the filter. You can use this method to "
+ "disable the Raindrops effect on a human face, for example."),
+ false);
+
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQGridLayout* gridSettings = new TQGridLayout( m_gboxSettings->plainPage(), 7, 2);
+
+ TQLabel *label1 = new TQLabel(i18n("Drop size:"), m_gboxSettings->plainPage());
+
+ m_dropInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_dropInput->setRange(0, 200, 1);
+ m_dropInput->setDefaultValue(80);
+ TQWhatsThis::add( m_dropInput, i18n("<p>Set here the raindrops' size."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Number:"), m_gboxSettings->plainPage());
+
+ m_amountInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_amountInput->setRange(1, 500, 1);
+ m_amountInput->setDefaultValue(150);
+ TQWhatsThis::add( m_amountInput, i18n("<p>This value controls the maximum number of raindrops."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label3 = new TQLabel(i18n("Fish eyes:"), m_gboxSettings->plainPage());
+
+ m_coeffInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_coeffInput->setRange(1, 100, 1);
+ m_coeffInput->setDefaultValue(30);
+ TQWhatsThis::add( m_coeffInput, i18n("<p>This value is the fish-eye-effect optical "
+ "distortion coefficient."));
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 1);
+ gridSettings->addMultiCellWidget(m_dropInput, 1, 1, 0, 1);
+ gridSettings->addMultiCellWidget(label2, 2, 2, 0, 1);
+ gridSettings->addMultiCellWidget(m_amountInput, 3, 3, 0, 1);
+ gridSettings->addMultiCellWidget(label3, 4, 4, 0, 1);
+ gridSettings->addMultiCellWidget(m_coeffInput, 5, 5, 0, 1);
+ gridSettings->setRowStretch(6, 10);
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_dropInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_amountInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_coeffInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+RainDropTool::~RainDropTool()
+{
+}
+
+void RainDropTool::renderingFinished()
+{
+ m_dropInput->setEnabled(true);
+ m_amountInput->setEnabled(true);
+ m_coeffInput->setEnabled(true);
+}
+
+void RainDropTool::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("raindrops Tool");
+
+ m_dropInput->blockSignals(true);
+ m_amountInput->blockSignals(true);
+ m_coeffInput->blockSignals(true);
+
+ m_dropInput->setValue(config->readNumEntry("DropAdjustment", m_dropInput->defaultValue()));
+ m_amountInput->setValue(config->readNumEntry("AmountAdjustment", m_amountInput->defaultValue()));
+ m_coeffInput->setValue(config->readNumEntry("CoeffAdjustment", m_coeffInput->defaultValue()));
+
+ m_dropInput->blockSignals(false);
+ m_amountInput->blockSignals(false);
+ m_coeffInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void RainDropTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("raindrops Tool");
+ config->writeEntry("DropAdjustment", m_dropInput->value());
+ config->writeEntry("AmountAdjustment", m_amountInput->value());
+ config->writeEntry("CoeffAdjustment", m_coeffInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void RainDropTool::slotResetSettings()
+{
+ m_dropInput->blockSignals(true);
+ m_amountInput->blockSignals(true);
+ m_coeffInput->blockSignals(true);
+
+ m_dropInput->slotReset();
+ m_amountInput->slotReset();
+ m_coeffInput->slotReset();
+
+ m_dropInput->blockSignals(false);
+ m_amountInput->blockSignals(false);
+ m_coeffInput->blockSignals(false);
+
+ slotEffect();
+}
+
+void RainDropTool::prepareEffect()
+{
+ m_dropInput->setEnabled(false);
+ m_amountInput->setEnabled(false);
+ m_coeffInput->setEnabled(false);
+
+ int d = m_dropInput->value();
+ int a = m_amountInput->value();
+ int c = m_coeffInput->value();
+
+ ImageIface* iface = m_previewWidget->imageIface();
+
+ // Selected data from the image
+ TQRect selection(iface->selectedXOrg(), iface->selectedYOrg(),
+ iface->selectedWidth(), iface->selectedHeight());
+
+ setFilter(dynamic_cast<DImgThreadedFilter *>
+ (new RainDrop(iface->getOriginalImg(), this, d, a, c, &selection)));
+}
+
+void RainDropTool::prepareFinal()
+{
+ m_dropInput->setEnabled(false);
+ m_amountInput->setEnabled(false);
+ m_coeffInput->setEnabled(false);
+
+ int d = m_dropInput->value();
+ int a = m_amountInput->value();
+ int c = m_coeffInput->value();
+
+ ImageIface iface(0, 0);
+
+ // Selected data from the image
+ TQRect selection(iface.selectedXOrg(), iface.selectedYOrg(),
+ iface.selectedWidth(), iface.selectedHeight());
+
+ setFilter(dynamic_cast<DImgThreadedFilter *>
+ (new RainDrop(iface.getOriginalImg(), this, d, a, c, &selection)));
+}
+
+void RainDropTool::putPreviewData(void)
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+
+ DImg imDest = filter()->getTargetImage()
+ .smoothScale(iface->previewWidth(), iface->previewHeight());
+ iface->putPreviewImage(imDest.bits());
+
+ m_previewWidget->updatePreview();
+}
+
+void RainDropTool::putFinalData(void)
+{
+ ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("RainDrop"), filter()->getTargetImage().bits());
+}
+
+} // NameSpace DigikamRainDropImagesPlugin
+
diff --git a/src/imageplugins/raindrop/raindroptool.h b/src/imageplugins/raindrop/raindroptool.h
new file mode 100644
index 00000000..d083eb9c
--- /dev/null
+++ b/src/imageplugins/raindrop/raindroptool.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-09-30
+ * Description : a plugin to add rain drop over an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef RAINDROPTOOL_H
+#define RAINDROPTOOL_H
+
+// Digikam includes.
+
+#include "editortool.h"
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+}
+
+namespace Digikam
+{
+class ImageWidget;
+}
+
+namespace DigikamRainDropImagesPlugin
+{
+
+class RainDropTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ RainDropTool(TQObject *parent);
+ ~RainDropTool();
+
+private slots:
+
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ KDcrawIface::RIntNumInput *m_dropInput;
+ KDcrawIface::RIntNumInput *m_amountInput;
+ KDcrawIface::RIntNumInput *m_coeffInput;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamRainDropImagesPlugin
+
+#endif /* RAINDROPTOOL_H */
diff --git a/src/imageplugins/restoration/Makefile.am b/src/imageplugins/restoration/Makefile.am
new file mode 100644
index 00000000..695609be
--- /dev/null
+++ b/src/imageplugins/restoration/Makefile.am
@@ -0,0 +1,35 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ -I$(top_srcdir)/src/libs/greycstoration \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_restoration_la_SOURCES = imageplugin_restoration.cpp \
+ restorationtool.cpp
+
+digikamimageplugin_restoration_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_restoration_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -no-undefined -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_restoration.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_restoration.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_restoration_ui.rc
+
diff --git a/src/imageplugins/restoration/digikamimageplugin_restoration.desktop b/src/imageplugins/restoration/digikamimageplugin_restoration.desktop
new file mode 100644
index 00000000..8d0e7bd8
--- /dev/null
+++ b/src/imageplugins/restoration/digikamimageplugin_restoration.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_Restoration
+Name[bg]=Приставка за снимки - Възстановяване
+Name[da]=Plugin for billedrestaurering
+Name[el]=ΠρόσθετοΕικόνας_Αποκατάσταση
+Name[fi]=Restaurointi
+Name[hr]=Obnavljanje
+Name[it]=PluginImmagini_Restauro
+Name[ms]=ImagePlugin_Pemulihan
+Name[nl]=Afbeeldingsplugin_Restauratie
+Name[sr]=Рестаурација
+Name[sr@Latn]=Restauracija
+Name[sv]=Insticksprogram för bildrestaurering
+Name[tr]=ResimEklentisi_Onarım
+Name[xx]=xxImagePlugin_Restorationxx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=digiKam plugin to restore a photograph
+Comment[bg]=Приставка на digiKam за възстановяване на снимки
+Comment[ca]=Connector pel digiKam per restaurar una fotografia
+Comment[da]=Digikam plugin til restaurering af et fotografi
+Comment[de]=digiKam-Modul zum Restaurieren eines Bildes
+Comment[el]=Πρόσθετο του digiKam για αποκατάσταση μιας φωτογραφίας
+Comment[es]=Plugin para digiKam para restaurar una fotografía
+Comment[et]=DigiKami foto restaureerimimise plugin
+Comment[fa]=وصلۀ digiKam برای ذخیرۀ یک عکس
+Comment[fi]=Korjaa kuvassa esiintyviä virheitä
+Comment[gl]=Un plugin de digiKam para restaurar unha fotografia
+Comment[hr]=digiKam dodatak za obnavljanje fotografije
+Comment[is]=Íforrit fyrir digiKam sem fjarlægir óhreinindi úr myndum
+Comment[it]=Plugin di digiKam per restaurare una fotografia
+Comment[ja]=digiKam 写真復元プラグイン
+Comment[nds]=digiKam-Moduul för't Wedderherstellen vun Fotos
+Comment[nl]=Digikam-plugin voor het herstellen van een foto
+Comment[pa]=ਇੱਕ ਫੋਟੋ ਮੁੜ-ਸਟੋਰ ਕਰਨ ਲਈ ਡਿਜ਼ੀਕੈਮ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam umożliwiająca odrestaurowanie zdjęcia
+Comment[pt]=Um 'plugin' do digiKam para restaurar uma fotografia
+Comment[pt_BR]=Plugin digiKam para restaurar una fotografia
+Comment[ru]=Модуль digiKam для восстановления фотографий
+Comment[sk]=digiKam plugin pre obnovenie fotografie
+Comment[sr]=digiKam-ов прикључак за поправку фотографија
+Comment[sr@Latn]=digiKam-ov priključak za popravku fotografija
+Comment[sv]=Digikam insticksprogram för restaurering av ett fotografi
+Comment[tr]=Fotoğraf onarmak için digiKam eklentisi
+Comment[uk]=Втулок відновлення фотографій для digiKam
+Comment[vi]=Phần bổ sung xây dựng lại ảnh chụp như cũ cho digiKam
+Comment[xx]=xxdigiKam plugin to restore a photographxx
+
+X-TDE-Library=digikamimageplugin_restoration
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/restoration/digikamimageplugin_restoration_ui.rc b/src/imageplugins/restoration/digikamimageplugin_restoration_ui.rc
new file mode 100644
index 00000000..27185294
--- /dev/null
+++ b/src/imageplugins/restoration/digikamimageplugin_restoration_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_restoration" >
+
+ <MenuBar>
+
+ <Menu name="Enhance" ><text>Enh&amp;ance</text>
+ <Action name="imageplugin_restoration" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_restoration" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/restoration/imageeffect_restoration.cpp b/src/imageplugins/restoration/imageeffect_restoration.cpp
new file mode 100644
index 00000000..825ef23d
--- /dev/null
+++ b/src/imageplugins/restoration/imageeffect_restoration.cpp
@@ -0,0 +1,349 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-26
+ * Description : a digiKam image editor plugin to restore
+ * a photograph
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqcombobox.h>
+#include <tqtabwidget.h>
+#include <tqfile.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <kurllabel.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <kstandarddirs.h>
+#include <tdemessagebox.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "greycstorationsettings.h"
+#include "greycstorationwidget.h"
+#include "greycstorationiface.h"
+#include "imageeffect_restoration.h"
+#include "imageeffect_restoration.moc"
+
+namespace DigikamRestorationImagesPlugin
+{
+
+ImageEffect_Restoration::ImageEffect_Restoration(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Photograph Restoration"),
+ "restoration", true, true, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Photograph Restoration"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to restore a photograph."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("David Tschumperle", I18N_NOOP("CImg library"), 0,
+ "http://cimg.sourceforge.net");
+
+ about->addAuthor("Gerhard Kulzer", I18N_NOOP("Feedback and plugin polishing"),
+ "gerhard at kulzer.net");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ m_mainTab = new TQTabWidget( m_imagePreviewWidget );
+
+ TQWidget* firstPage = new TQWidget( m_mainTab );
+ TQGridLayout* grid = new TQGridLayout( firstPage, 2, 2, spacingHint());
+ m_mainTab->addTab( firstPage, i18n("Preset") );
+
+ KURLLabel *cimgLogoLabel = new KURLLabel(firstPage);
+ cimgLogoLabel->setText(TQString());
+ cimgLogoLabel->setURL("http://cimg.sourceforge.net");
+ TDEGlobal::dirs()->addResourceType("logo-cimg", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("logo-cimg", "logo-cimg.png");
+ cimgLogoLabel->setPixmap( TQPixmap( directory + "logo-cimg.png" ) );
+ TQToolTip::add(cimgLogoLabel, i18n("Visit CImg library website"));
+
+ TQLabel *typeLabel = new TQLabel(i18n("Filtering type:"), firstPage);
+ typeLabel->setAlignment ( TQt::AlignRight | TQt::AlignVCenter);
+ m_restorationTypeCB = new TQComboBox( false, firstPage );
+ m_restorationTypeCB->insertItem( i18n("None") );
+ m_restorationTypeCB->insertItem( i18n("Reduce Uniform Noise") );
+ m_restorationTypeCB->insertItem( i18n("Reduce JPEG Artefacts") );
+ m_restorationTypeCB->insertItem( i18n("Reduce Texturing") );
+ TQWhatsThis::add( m_restorationTypeCB, i18n("<p>Select the filter preset to use for photograph restoration:<p>"
+ "<b>None</b>: Most common values. Puts settings to default.<p>"
+ "<b>Reduce Uniform Noise</b>: reduce small image artifacts like sensor noise.<p>"
+ "<b>Reduce JPEG Artefacts</b>: reduce large image artifacts like JPEG compression mosaic.<p>"
+ "<b>Reduce Texturing</b>: reduce image artifacts like paper texture or Moire patterns "
+ "of a scanned image.<p>"));
+
+ grid->addMultiCellWidget(cimgLogoLabel, 0, 0, 1, 1);
+ grid->addMultiCellWidget(typeLabel, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_restorationTypeCB, 1, 1, 1, 1);
+ grid->setRowStretch(1, 10);
+
+ // -------------------------------------------------------------
+
+ m_settingsWidget = new Digikam::GreycstorationWidget( m_mainTab );
+ m_imagePreviewWidget->setUserAreaWidget(m_mainTab);
+
+ // -------------------------------------------------------------
+
+ connect(cimgLogoLabel, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ this, TQ_SLOT(processCImgURL(const TQString&)));
+
+ connect(m_restorationTypeCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotResetValues(int)));
+}
+
+ImageEffect_Restoration::~ImageEffect_Restoration()
+{
+}
+
+void ImageEffect_Restoration::renderingFinished()
+{
+ m_imagePreviewWidget->setEnable(true);
+ m_mainTab->setEnabled(true);
+}
+
+void ImageEffect_Restoration::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("restoration Tool Dialog");
+
+ Digikam::GreycstorationSettings settings;
+ settings.fastApprox = config->readBoolEntry("FastApprox", true);
+ settings.interp = config->readNumEntry("Interpolation",
+ Digikam::GreycstorationSettings::NearestNeighbor);
+ settings.amplitude = config->readDoubleNumEntry("Amplitude", 60.0);
+ settings.sharpness = config->readDoubleNumEntry("Sharpness", 0.7);
+ settings.anisotropy = config->readDoubleNumEntry("Anisotropy", 0.3);
+ settings.alpha = config->readDoubleNumEntry("Alpha", 0.6);
+ settings.sigma = config->readDoubleNumEntry("Sigma", 1.1);
+ settings.gaussPrec = config->readDoubleNumEntry("GaussPrec", 2.0);
+ settings.dl = config->readDoubleNumEntry("Dl", 0.8);
+ settings.da = config->readDoubleNumEntry("Da", 30.0);
+ settings.nbIter = config->readNumEntry("Iteration", 1);
+ settings.tile = config->readNumEntry("Tile", 512);
+ settings.btile = config->readNumEntry("BTile", 4);
+ m_settingsWidget->setSettings(settings);
+
+ int p = config->readNumEntry("Preset", NoPreset);
+ m_restorationTypeCB->setCurrentItem(p);
+ if (p == NoPreset)
+ m_settingsWidget->setEnabled(true);
+ else
+ m_settingsWidget->setEnabled(false);
+}
+
+void ImageEffect_Restoration::writeUserSettings()
+{
+ Digikam::GreycstorationSettings settings = m_settingsWidget->getSettings();
+ TDEConfig* config = kapp->config();
+ config->setGroup("restoration Tool Dialog");
+ config->writeEntry("Preset", m_restorationTypeCB->currentItem());
+ config->writeEntry("FastApprox", settings.fastApprox);
+ config->writeEntry("Interpolation", settings.interp);
+ config->writeEntry("Amplitude", settings.amplitude);
+ config->writeEntry("Sharpness", settings.sharpness);
+ config->writeEntry("Anisotropy", settings.anisotropy);
+ config->writeEntry("Alpha", settings.alpha);
+ config->writeEntry("Sigma", settings.sigma);
+ config->writeEntry("GaussPrec", settings.gaussPrec);
+ config->writeEntry("Dl", settings.dl);
+ config->writeEntry("Da", settings.da);
+ config->writeEntry("Iteration", settings.nbIter);
+ config->writeEntry("Tile", settings.tile);
+ config->writeEntry("BTile", settings.btile);
+ config->sync();
+}
+
+void ImageEffect_Restoration::slotResetValues(int i)
+{
+ if (i == NoPreset)
+ m_settingsWidget->setEnabled(true);
+ else
+ m_settingsWidget->setEnabled(false);
+
+ resetValues();
+}
+
+void ImageEffect_Restoration::resetValues()
+{
+ Digikam::GreycstorationSettings settings;
+ settings.setRestorationDefaultSettings();
+
+ switch(m_restorationTypeCB->currentItem())
+ {
+ case ReduceUniformNoise:
+ {
+ settings.amplitude = 40.0;
+ break;
+ }
+
+ case ReduceJPEGArtefacts:
+ {
+ settings.sharpness = 0.3;
+ settings.sigma = 1.0;
+ settings.amplitude = 100.0;
+ settings.nbIter = 2;
+ break;
+ }
+
+ case ReduceTexturing:
+ {
+ settings.sharpness = 0.5;
+ settings.sigma = 1.5;
+ settings.amplitude = 100.0;
+ settings.nbIter = 2;
+ break;
+ }
+ }
+
+ m_settingsWidget->setSettings(settings);
+}
+
+void ImageEffect_Restoration::processCImgURL(const TQString& url)
+{
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+void ImageEffect_Restoration::prepareEffect()
+{
+ m_mainTab->setEnabled(false);
+
+ Digikam::DImg previewImage = m_imagePreviewWidget->getOriginalRegionImage();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Digikam::GreycstorationIface(
+ &previewImage, m_settingsWidget->getSettings(),
+ Digikam::GreycstorationIface::Restore,
+ 0, 0, 0, this));
+}
+
+void ImageEffect_Restoration::prepareFinal()
+{
+ m_mainTab->setEnabled(false);
+
+ Digikam::ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ Digikam::DImg originalImage(iface.originalWidth(), iface.originalHeight(),
+ iface.originalSixteenBit(), iface.originalHasAlpha(), data);
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Digikam::GreycstorationIface(
+ &originalImage, m_settingsWidget->getSettings(),
+ Digikam::GreycstorationIface::Restore,
+ 0, 0, 0, this));
+
+ delete [] data;
+}
+
+void ImageEffect_Restoration::putPreviewData(void)
+{
+ Digikam::DImg imDest = m_threadedFilter->getTargetImage();
+ m_imagePreviewWidget->setPreviewImage(imDest);
+}
+
+void ImageEffect_Restoration::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+
+ iface.putOriginalImage(i18n("Restoration"),
+ m_threadedFilter->getTargetImage().bits());
+}
+
+void ImageEffect_Restoration::slotUser3()
+{
+ KURL loadRestorationFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Restoration Settings File to Load")) );
+ if( loadRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(loadRestorationFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ if (!m_settingsWidget->loadSettings(file, TQString("# Photograph Restoration Configuration File V2")))
+ {
+ KMessageBox::error(this,
+ i18n("\"%1\" is not a Photograph Restoration settings text file.")
+ .arg(loadRestorationFile.fileName()));
+ file.close();
+ return;
+ }
+
+ slotEffect();
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot load settings from the Photograph Restoration text file."));
+
+ file.close();
+ m_restorationTypeCB->blockSignals(true);
+ m_restorationTypeCB->setCurrentItem(NoPreset);
+ m_restorationTypeCB->blockSignals(false);
+ m_settingsWidget->setEnabled(true);
+}
+
+void ImageEffect_Restoration::slotUser2()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("Photograph Restoration Settings File to Save")) );
+ if( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ m_settingsWidget->saveSettings(file, TQString("# Photograph Restoration Configuration File V2"));
+ else
+ KMessageBox::error(this, i18n("Cannot save settings to the Photograph Restoration text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamRestorationImagesPlugin
+
diff --git a/src/imageplugins/restoration/imageeffect_restoration.h b/src/imageplugins/restoration/imageeffect_restoration.h
new file mode 100644
index 00000000..7c28bd92
--- /dev/null
+++ b/src/imageplugins/restoration/imageeffect_restoration.h
@@ -0,0 +1,94 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-26
+ * Description : a digiKam image editor plugin to restore
+ * a photograph
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_RESTORATION_H
+#define IMAGEEFFECT_RESTORATION_H
+
+// TQt include.
+
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+class TQComboBox;
+class TQTabWidget;
+
+namespace Digikam
+{
+class GreycstorationWidget;
+}
+
+namespace DigikamRestorationImagesPlugin
+{
+
+class ImageEffect_Restoration : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Restoration(TQWidget* parent);
+ ~ImageEffect_Restoration();
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+ void processCImgURL(const TQString&);
+ void readUserSettings();
+ void slotResetValues(int);
+
+private:
+
+ void writeUserSettings();
+ void prepareEffect(void);
+ void prepareFinal(void);
+ void putPreviewData(void);
+ void putFinalData(void);
+ void resetValues(void);
+ void renderingFinished(void);
+
+private:
+
+ enum RestorationFilteringPreset
+ {
+ NoPreset=0,
+ ReduceUniformNoise,
+ ReduceJPEGArtefacts,
+ ReduceTexturing
+ };
+
+ TQTabWidget *m_mainTab;
+
+ TQComboBox *m_restorationTypeCB;
+
+ Digikam::GreycstorationWidget *m_settingsWidget;
+};
+
+} // NameSpace DigikamRestorationImagesPlugin
+
+#endif /* IMAGEEFFECT_RESTORATION_H */
diff --git a/src/imageplugins/restoration/imageplugin_restoration.cpp b/src/imageplugins/restoration/imageplugin_restoration.cpp
new file mode 100644
index 00000000..01cd52f7
--- /dev/null
+++ b/src/imageplugins/restoration/imageplugin_restoration.cpp
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-26
+ * Description : a digiKam image editor plugin to restore
+ * a photograph
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "restorationtool.h"
+#include "imageplugin_restoration.h"
+#include "imageplugin_restoration.moc"
+
+using namespace DigikamRestorationImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_restoration,
+ KGenericFactory<ImagePlugin_Restoration>("digikamimageplugin_restoration"));
+
+ImagePlugin_Restoration::ImagePlugin_Restoration(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_Restoration")
+{
+ m_restorationAction = new TDEAction(i18n("Restoration..."), "restoration", 0,
+ this, TQ_SLOT(slotRestoration()),
+ actionCollection(), "imageplugin_restoration");
+
+ setXMLFile( "digikamimageplugin_restoration_ui.rc" );
+
+ DDebug() << "ImagePlugin_Restoration plugin loaded" << endl;
+}
+
+ImagePlugin_Restoration::~ImagePlugin_Restoration()
+{
+}
+
+void ImagePlugin_Restoration::setEnabledActions(bool enable)
+{
+ m_restorationAction->setEnabled(enable);
+}
+
+void ImagePlugin_Restoration::slotRestoration()
+{
+ RestorationTool *tool = new RestorationTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/restoration/imageplugin_restoration.h b/src/imageplugins/restoration/imageplugin_restoration.h
new file mode 100644
index 00000000..50ac8326
--- /dev/null
+++ b/src/imageplugins/restoration/imageplugin_restoration.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-26
+ * Description : a digiKam image editor plugin to restore
+ * a photograph
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_RESTORATION_H
+#define IMAGEPLUGIN_RESTORATION_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_Restoration : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_Restoration(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_Restoration();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotRestoration();
+
+private:
+
+ TDEAction *m_restorationAction;
+};
+
+#endif /* IMAGEPLUGIN_RESTORATION_H */
diff --git a/src/imageplugins/restoration/restorationtool.cpp b/src/imageplugins/restoration/restorationtool.cpp
new file mode 100644
index 00000000..a6896135
--- /dev/null
+++ b/src/imageplugins/restoration/restorationtool.cpp
@@ -0,0 +1,356 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-26
+ * Description : a digiKam image editor plugin to restore
+ * a photograph
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqtooltip.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqcombobox.h>
+#include <tqtabwidget.h>
+#include <tqfile.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <kurllabel.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <kstandarddirs.h>
+#include <tdemessagebox.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "greycstorationsettings.h"
+#include "greycstorationwidget.h"
+#include "greycstorationiface.h"
+#include "restorationtool.h"
+#include "restorationtool.moc"
+
+using namespace Digikam;
+
+namespace DigikamRestorationImagesPlugin
+{
+
+RestorationTool::RestorationTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("restoration");
+ setToolName(i18n("Restoration"));
+ setToolIcon(SmallIcon("restoration"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Try,
+ EditorToolSettings::PanIcon);
+
+ TQGridLayout* gridSettings = new TQGridLayout(m_gboxSettings->plainPage(), 2, 1);
+ m_mainTab = new TQTabWidget( m_gboxSettings->plainPage() );
+
+ TQWidget* firstPage = new TQWidget( m_mainTab );
+ TQGridLayout* grid = new TQGridLayout(firstPage, 2, 2);
+ m_mainTab->addTab( firstPage, i18n("Preset") );
+
+ KURLLabel *cimgLogoLabel = new KURLLabel(firstPage);
+ cimgLogoLabel->setText(TQString());
+ cimgLogoLabel->setURL("http://cimg.sourceforge.net");
+ TDEGlobal::dirs()->addResourceType("logo-cimg", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("logo-cimg", "logo-cimg.png");
+ cimgLogoLabel->setPixmap( TQPixmap( directory + "logo-cimg.png" ) );
+ TQToolTip::add(cimgLogoLabel, i18n("Visit CImg library website"));
+
+ TQLabel *typeLabel = new TQLabel(i18n("Filtering type:"), firstPage);
+ typeLabel->setAlignment ( TQt::AlignRight | TQt::AlignVCenter);
+ m_restorationTypeCB = new TQComboBox(false, firstPage);
+ m_restorationTypeCB->insertItem( i18n("None") );
+ m_restorationTypeCB->insertItem( i18n("Reduce Uniform Noise") );
+ m_restorationTypeCB->insertItem( i18n("Reduce JPEG Artefacts") );
+ m_restorationTypeCB->insertItem( i18n("Reduce Texturing") );
+ TQWhatsThis::add( m_restorationTypeCB, i18n("<p>Select the filter preset to use for photograph restoration:<p>"
+ "<b>None</b>: Most common values. Puts settings to default.<p>"
+ "<b>Reduce Uniform Noise</b>: reduce small image artifacts like sensor noise.<p>"
+ "<b>Reduce JPEG Artefacts</b>: reduce large image artifacts like JPEG compression mosaic.<p>"
+ "<b>Reduce Texturing</b>: reduce image artifacts like paper texture or Moire patterns "
+ "of a scanned image.<p>"));
+
+ grid->addMultiCellWidget(cimgLogoLabel, 0, 0, 1, 1);
+ grid->addMultiCellWidget(typeLabel, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_restorationTypeCB, 1, 1, 1, 1);
+ grid->setRowStretch(1, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ m_settingsWidget = new GreycstorationWidget( m_mainTab );
+ gridSettings->addMultiCellWidget(m_mainTab, 0, 0, 1, 1);
+ gridSettings->addMultiCellWidget(new TQLabel(m_gboxSettings->plainPage()), 1, 1, 1, 1);
+ gridSettings->setMargin(m_gboxSettings->spacingHint());
+ gridSettings->setSpacing(m_gboxSettings->spacingHint());
+ gridSettings->setRowStretch(2, 10);
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "restoration Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(cimgLogoLabel, TQ_SIGNAL(leftClickedURL(const TQString&)),
+ this, TQ_SLOT(processCImgURL(const TQString&)));
+
+ connect(m_restorationTypeCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotResetValues(int)));
+
+ // -------------------------------------------------------------
+
+ GreycstorationSettings defaults;
+ defaults.setRestorationDefaultSettings();
+ m_settingsWidget->setDefaultSettings(defaults);
+}
+
+RestorationTool::~RestorationTool()
+{
+}
+
+void RestorationTool::renderingFinished()
+{
+ m_previewWidget->setEnable(true);
+ m_mainTab->setEnabled(true);
+}
+
+void RestorationTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("restoration Tool");
+
+ GreycstorationSettings settings;
+ GreycstorationSettings defaults;
+ defaults.setRestorationDefaultSettings();
+
+ settings.fastApprox = config->readBoolEntry("FastApprox", defaults.fastApprox);
+ settings.interp = config->readNumEntry("Interpolation", defaults.interp);
+ settings.amplitude = config->readDoubleNumEntry("Amplitude", defaults.amplitude);
+ settings.sharpness = config->readDoubleNumEntry("Sharpness", defaults.sharpness);
+ settings.anisotropy = config->readDoubleNumEntry("Anisotropy", defaults.anisotropy);
+ settings.alpha = config->readDoubleNumEntry("Alpha", defaults.alpha);
+ settings.sigma = config->readDoubleNumEntry("Sigma", defaults.sigma);
+ settings.gaussPrec = config->readDoubleNumEntry("GaussPrec", defaults.gaussPrec);
+ settings.dl = config->readDoubleNumEntry("Dl", defaults.dl);
+ settings.da = config->readDoubleNumEntry("Da", defaults.da);
+ settings.nbIter = config->readNumEntry("Iteration", defaults.nbIter);
+ settings.tile = config->readNumEntry("Tile", defaults.tile);
+ settings.btile = config->readNumEntry("BTile", defaults.btile);
+ m_settingsWidget->setSettings(settings);
+
+ int p = config->readNumEntry("Preset", NoPreset);
+ m_restorationTypeCB->setCurrentItem(p);
+ if (p == NoPreset)
+ m_settingsWidget->setEnabled(true);
+ else
+ m_settingsWidget->setEnabled(false);
+}
+
+void RestorationTool::writeSettings()
+{
+ GreycstorationSettings settings = m_settingsWidget->getSettings();
+ TDEConfig* config = kapp->config();
+ config->setGroup("restoration Tool");
+ config->writeEntry("Preset", m_restorationTypeCB->currentItem());
+ config->writeEntry("FastApprox", settings.fastApprox);
+ config->writeEntry("Interpolation", settings.interp);
+ config->writeEntry("Amplitude", settings.amplitude);
+ config->writeEntry("Sharpness", settings.sharpness);
+ config->writeEntry("Anisotropy", settings.anisotropy);
+ config->writeEntry("Alpha", settings.alpha);
+ config->writeEntry("Sigma", settings.sigma);
+ config->writeEntry("GaussPrec", settings.gaussPrec);
+ config->writeEntry("Dl", settings.dl);
+ config->writeEntry("Da", settings.da);
+ config->writeEntry("Iteration", settings.nbIter);
+ config->writeEntry("Tile", settings.tile);
+ config->writeEntry("BTile", settings.btile);
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void RestorationTool::slotResetValues(int i)
+{
+ if (i == NoPreset)
+ m_settingsWidget->setEnabled(true);
+ else
+ m_settingsWidget->setEnabled(false);
+
+ slotResetSettings();
+}
+
+void RestorationTool::slotResetSettings()
+{
+ GreycstorationSettings settings;
+ settings.setRestorationDefaultSettings();
+
+ switch(m_restorationTypeCB->currentItem())
+ {
+ case ReduceUniformNoise:
+ {
+ settings.amplitude = 40.0;
+ break;
+ }
+
+ case ReduceJPEGArtefacts:
+ {
+ settings.sharpness = 0.3;
+ settings.sigma = 1.0;
+ settings.amplitude = 100.0;
+ settings.nbIter = 2;
+ break;
+ }
+
+ case ReduceTexturing:
+ {
+ settings.sharpness = 0.5;
+ settings.sigma = 1.5;
+ settings.amplitude = 100.0;
+ settings.nbIter = 2;
+ break;
+ }
+ }
+
+ m_settingsWidget->setSettings(settings);
+}
+
+void RestorationTool::processCImgURL(const TQString& url)
+{
+ TDEApplication::kApplication()->invokeBrowser(url);
+}
+
+void RestorationTool::prepareEffect()
+{
+ m_mainTab->setEnabled(false);
+
+ DImg previewImage = m_previewWidget->getOriginalRegionImage();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new GreycstorationIface(&previewImage,
+ m_settingsWidget->getSettings(), GreycstorationIface::Restore,
+ 0, 0, 0, this)));
+}
+
+void RestorationTool::prepareFinal()
+{
+ m_mainTab->setEnabled(false);
+
+ ImageIface iface(0, 0);
+ uchar *data = iface.getOriginalImage();
+ DImg originalImage(iface.originalWidth(), iface.originalHeight(),
+ iface.originalSixteenBit(), iface.originalHasAlpha(), data);
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new GreycstorationIface(&originalImage,
+ m_settingsWidget->getSettings(), GreycstorationIface::Restore,
+ 0, 0, 0, this)));
+
+ delete [] data;
+}
+
+void RestorationTool::putPreviewData()
+{
+ DImg imDest = filter()->getTargetImage();
+ m_previewWidget->setPreviewImage(imDest);
+}
+
+void RestorationTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Restoration"), filter()->getTargetImage().bits());
+}
+
+void RestorationTool::slotLoadSettings()
+{
+ KURL loadRestorationFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Restoration Settings File to Load")) );
+ if( loadRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(loadRestorationFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ if (!m_settingsWidget->loadSettings(file, TQString("# Photograph Restoration Configuration File V2")))
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" is not a Photograph Restoration settings text file.")
+ .arg(loadRestorationFile.fileName()));
+ file.close();
+ return;
+ }
+
+ slotEffect();
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot load settings from the Photograph Restoration text file."));
+
+ file.close();
+ m_restorationTypeCB->blockSignals(true);
+ m_restorationTypeCB->setCurrentItem(NoPreset);
+ m_restorationTypeCB->blockSignals(false);
+ m_settingsWidget->setEnabled(true);
+}
+
+void RestorationTool::slotSaveAsSettings()
+{
+ KURL saveRestorationFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("Photograph Restoration Settings File to Save")) );
+ if( saveRestorationFile.isEmpty() )
+ return;
+
+ TQFile file(saveRestorationFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ m_settingsWidget->saveSettings(file, TQString("# Photograph Restoration Configuration File V2"));
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot save settings to the Photograph Restoration text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamRestorationImagesPlugin
+
diff --git a/src/imageplugins/restoration/restorationtool.h b/src/imageplugins/restoration/restorationtool.h
new file mode 100644
index 00000000..6242a2b6
--- /dev/null
+++ b/src/imageplugins/restoration/restorationtool.h
@@ -0,0 +1,100 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-26
+ * Description : a digiKam image editor plugin to restore
+ * a photograph
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef RESTORATIONTOOL_H
+#define RESTORATIONTOOL_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQComboBox;
+class TQTabWidget;
+
+namespace Digikam
+{
+class GreycstorationWidget;
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamRestorationImagesPlugin
+{
+
+class RestorationTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ RestorationTool(TQObject* parent);
+ ~RestorationTool();
+
+private slots:
+
+ void slotSaveAsSettings();
+ void slotLoadSettings();
+ void slotResetSettings();
+ void processCImgURL(const TQString&);
+ void slotResetValues(int);
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ enum RestorationFilteringPreset
+ {
+ NoPreset=0,
+ ReduceUniformNoise,
+ ReduceJPEGArtefacts,
+ ReduceTexturing
+ };
+
+ TQTabWidget *m_mainTab;
+
+ TQComboBox *m_restorationTypeCB;
+
+ Digikam::GreycstorationWidget *m_settingsWidget;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamRestorationImagesPlugin
+
+#endif /* RESTORATIONTOOL_H */
diff --git a/src/imageplugins/sheartool/Makefile.am b/src/imageplugins/sheartool/Makefile.am
new file mode 100644
index 00000000..a601b8a5
--- /dev/null
+++ b/src/imageplugins/sheartool/Makefile.am
@@ -0,0 +1,33 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_sheartool_la_SOURCES = imageplugin_sheartool.cpp shear.cpp \
+ sheartool.cpp
+
+digikamimageplugin_sheartool_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_sheartool_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_sheartool.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_sheartool.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_sheartool_ui.rc
diff --git a/src/imageplugins/sheartool/digikamimageplugin_sheartool.desktop b/src/imageplugins/sheartool/digikamimageplugin_sheartool.desktop
new file mode 100644
index 00000000..8884ef27
--- /dev/null
+++ b/src/imageplugins/sheartool/digikamimageplugin_sheartool.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Name=ImagePlugin_ShearTool
+Name[bg]=Приставка за снимки - Инструмент за изрязване
+Name[da]=Billedplugin_Forskydningsværktøj
+Name[el]=ΠρόσθετοΕικόνας_ΕργαλείοΣτρέβλωσης
+Name[fi]=Väännin
+Name[hr]=Smicanje
+Name[it]=PluginImmagini_DistorsioneCurvilinea
+Name[ms]=ImagePlugin_AlatanPemotong
+Name[nl]=Afbeeldingsplugin_SchuinTrekken
+Name[sr]=Алат за искошавање
+Name[sr@Latn]=Alat za iskošavanje
+Name[sv]=Insticksprogram med skjuvningsverktyg
+Name[tr]=ResimEklentisi_EğmeAracı
+Name[xx]=xxImagePlugin_ShearToolxx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Shear tool plugin for digiKam
+Comment[bg]=Приставка на digiKam с инструмент за изрязване на снимки
+Comment[ca]=Connector pel digiKam d'eina per retallar
+Comment[da]=Forskydningsværktøjs-plugin for Digikam
+Comment[de]=digiKam-Modul zum Scheren eines Bildes
+Comment[el]=Πρόσθετο εργαλείο στρέβλωσης για το digiKam
+Comment[es]=Plugin para digiKam con herramientas para cizallar una imagen
+Comment[et]=DigiKami pildinihkeplugin
+Comment[fa]=وصلۀ ابزار چیدن برای digiKam
+Comment[fi]=Vääntää kuvaa vaaka- ja pystysuunnassa
+Comment[gl]=Un plugin de digiKam para inclinar unha imaxe
+Comment[hr]=digiKam dodatak za smicanje
+Comment[is]=Íforrit fyrir digiKam sem snýr upp á myndir
+Comment[it]=Plugin per lo strumento di distorsione curvilinea per digiKam
+Comment[ja]=digiKam 剪断変形プラグイン
+Comment[ms]=Templat plugin pemotong untuk digiKam
+Comment[nds]=digiKam-Warktüüchmoduul för't Scheren
+Comment[nl]=Digikam-plugin voor het schuintrekken van afbeeldingen
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਸ਼ੀਅਰ ਸੰਦ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam umożliwiająca pochylenie obrazu
+Comment[pt]=Um 'plugin' do digiKam para inclinar uma imagem
+Comment[pt_BR]=Um 'plugin' do digiKam para inclinar uma imagem
+Comment[ru]=Модуль сдвига фрагментов для digiKam
+Comment[sk]=digiKam plugin pre orezanie obrázku
+Comment[sr]=digiKam-ов прикључак за искошавање
+Comment[sr@Latn]=digiKam-ov priključak za iskošavanje
+Comment[sv]=Digikam insticksprogram med skjuvningsverktyg
+Comment[tr]=digiKam için eğme aracı eklentisi
+Comment[uk]=Втулок засобу перекошення для digiKam
+Comment[vi]=Phần bổ sung công cụ kéo cắt cho digiKam
+Comment[xx]=xxShear tool plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_sheartool
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/sheartool/digikamimageplugin_sheartool_ui.rc b/src/imageplugins/sheartool/digikamimageplugin_sheartool_ui.rc
new file mode 100644
index 00000000..0a2cf60a
--- /dev/null
+++ b/src/imageplugins/sheartool/digikamimageplugin_sheartool_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="4" name="digikamimageplugin_sheartool" >
+
+ <MenuBar>
+
+ <Menu name="Transform" ><text>Tra&amp;nsform</text>
+ <Action name="imageplugin_sheartool" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_sheartool" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/sheartool/imageeffect_sheartool.cpp b/src/imageplugins/sheartool/imageeffect_sheartool.cpp
new file mode 100644
index 00000000..e65bd91b
--- /dev/null
+++ b/src/imageplugins/sheartool/imageeffect_sheartool.cpp
@@ -0,0 +1,322 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-23
+ * Description : a plugin to shear an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqcheckbox.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+#include <kseparator.h>
+#include <kcursor.h>
+#include <tdeconfig.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "sheartool.h"
+#include "imageeffect_sheartool.h"
+#include "imageeffect_sheartool.moc"
+
+namespace DigikamShearToolImagesPlugin
+{
+
+ImageEffect_ShearTool::ImageEffect_ShearTool(TQWidget* parent)
+ : Digikam::ImageGuideDlg(parent, i18n("Shear Tool"), "sheartool",
+ false, true, true,
+ Digikam::ImageGuideWidget::HVGuideMode)
+{
+ // No need Abort button action.
+ showButton(User1, false);
+
+ TQString whatsThis;
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Shear Tool"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to shear an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2004-2008, Gilles Caulier",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Pieter Z. Voloshyn", I18N_NOOP("Shear algorithm"),
+ "pieter dot voloshyn at gmail dot com");
+
+ setAboutData(about);
+
+ TQWhatsThis::add( m_imagePreviewWidget, i18n("<p>This is the shearing image operation preview. "
+ "If you move the mouse cursor on this preview, "
+ "a vertical and horizontal dashed line will be drawn "
+ "to guide you in adjusting the shearing correction. "
+ "Release the left mouse button to freeze the dashed "
+ "line's position."));
+
+ // -------------------------------------------------------------
+
+ TQString temp;
+ Digikam::ImageIface iface(0, 0);
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 11, 2, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("New width:"), gboxSettings);
+ m_newWidthLabel = new TQLabel(temp.setNum( iface.originalWidth()) + i18n(" px"), gboxSettings);
+ m_newWidthLabel->setAlignment( AlignBottom | AlignRight );
+
+ TQLabel *label2 = new TQLabel(i18n("New height:"), gboxSettings);
+ m_newHeightLabel = new TQLabel(temp.setNum( iface.originalHeight()) + i18n(" px"), gboxSettings);
+ m_newHeightLabel->setAlignment( AlignBottom | AlignRight );
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridSettings->addMultiCellWidget(m_newWidthLabel, 0, 0, 1, 2);
+ gridSettings->addMultiCellWidget(label2, 1, 1, 0, 0);
+ gridSettings->addMultiCellWidget(m_newHeightLabel, 1, 1, 1, 2);
+
+ KSeparator *line = new KSeparator(Horizontal, gboxSettings);
+ gridSettings->addMultiCellWidget(line, 2, 2, 0, 2);
+
+ TQLabel *label3 = new TQLabel(i18n("Main horizontal angle:"), gboxSettings);
+ m_mainHAngleInput = new KIntNumInput(gboxSettings);
+ m_mainHAngleInput->setRange(-45, 45, 1, true);
+ m_mainHAngleInput->setValue(0);
+ TQWhatsThis::add( m_mainHAngleInput, i18n("<p>The main horizontal shearing angle, in degrees."));
+ gridSettings->addMultiCellWidget(label3, 3, 3, 0, 2);
+ gridSettings->addMultiCellWidget(m_mainHAngleInput, 4, 4, 0, 2);
+
+ TQLabel *label4 = new TQLabel(i18n("Fine horizontal angle:"), gboxSettings);
+ m_fineHAngleInput = new KDoubleNumInput(gboxSettings);
+ m_fineHAngleInput->setRange(-5.0, 5.0, 0.01, true);
+ m_fineHAngleInput->setValue(0);
+ TQWhatsThis::add( m_fineHAngleInput, i18n("<p>This value in degrees will be added to main horizontal angle value "
+ "to set fine adjustments."));
+ gridSettings->addMultiCellWidget(label4, 5, 5, 0, 2);
+ gridSettings->addMultiCellWidget(m_fineHAngleInput, 6, 6, 0, 2);
+
+ TQLabel *label5 = new TQLabel(i18n("Main vertical angle:"), gboxSettings);
+ m_mainVAngleInput = new KIntNumInput(gboxSettings);
+ m_mainVAngleInput->setRange(-45, 45, 1, true);
+ m_mainVAngleInput->setValue(0);
+ TQWhatsThis::add( m_mainVAngleInput, i18n("<p>The main vertical shearing angle, in degrees."));
+ gridSettings->addMultiCellWidget(label5, 7, 7, 0, 0);
+ gridSettings->addMultiCellWidget(m_mainVAngleInput, 8, 8, 0, 2);
+
+ TQLabel *label6 = new TQLabel(i18n("Fine vertical angle:"), gboxSettings);
+ m_fineVAngleInput = new KDoubleNumInput(gboxSettings);
+ m_fineVAngleInput->setRange(-5.0, 5.0, 0.01, true);
+ m_fineVAngleInput->setValue(0);
+ TQWhatsThis::add( m_fineVAngleInput, i18n("<p>This value in degrees will be added to main vertical angle value "
+ "to set fine adjustments."));
+ gridSettings->addMultiCellWidget(label6, 9, 9, 0, 2);
+ gridSettings->addMultiCellWidget(m_fineVAngleInput, 10, 10, 0, 2);
+
+ m_antialiasInput = new TQCheckBox(i18n("Anti-Aliasing"), gboxSettings);
+ TQWhatsThis::add( m_antialiasInput, i18n("<p>Enable this option to apply the anti-aliasing filter "
+ "to the sheared image. "
+ "To smooth the target image, it will be blurred a little."));
+ gridSettings->addMultiCellWidget(m_antialiasInput, 11, 11, 0, 2);
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_mainHAngleInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_fineHAngleInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_mainVAngleInput, TQ_SIGNAL(valueChanged (int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_fineVAngleInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_antialiasInput, TQ_SIGNAL(toggled (bool)),
+ this, TQ_SLOT(slotEffect()));
+}
+
+ImageEffect_ShearTool::~ImageEffect_ShearTool()
+{
+}
+
+void ImageEffect_ShearTool::readUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("sheartool Tool Dialog");
+ m_mainHAngleInput->setValue(config->readNumEntry("Main HAngle", 0));
+ m_mainVAngleInput->setValue(config->readNumEntry("Main VAngle", 0));
+ m_fineHAngleInput->setValue(config->readDoubleNumEntry("Fine HAngle", 0.0));
+ m_fineVAngleInput->setValue(config->readDoubleNumEntry("Fine VAngle", 0.0));
+ m_antialiasInput->setChecked(config->readBoolEntry("Anti Aliasing", true));
+ slotEffect();
+}
+
+void ImageEffect_ShearTool::writeUserSettings(void)
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("sheartool Tool Dialog");
+ config->writeEntry("Main HAngle", m_mainHAngleInput->value());
+ config->writeEntry("Main VAngle", m_mainVAngleInput->value());
+ config->writeEntry("Fine HAngle", m_fineHAngleInput->value());
+ config->writeEntry("Fine VAngle", m_fineVAngleInput->value());
+ config->writeEntry("Anti Aliasing", m_antialiasInput->isChecked());
+ config->sync();
+}
+
+void ImageEffect_ShearTool::resetValues()
+{
+ m_mainHAngleInput->blockSignals(true);
+ m_mainVAngleInput->blockSignals(true);
+ m_fineHAngleInput->blockSignals(true);
+ m_fineVAngleInput->blockSignals(true);
+ m_antialiasInput->blockSignals(true);
+ m_mainHAngleInput->setValue(0);
+ m_mainVAngleInput->setValue(0);
+ m_fineHAngleInput->setValue(0.0);
+ m_fineVAngleInput->setValue(0.0);
+ m_antialiasInput->setChecked(true);
+ m_mainHAngleInput->blockSignals(false);
+ m_mainVAngleInput->blockSignals(false);
+ m_fineHAngleInput->blockSignals(false);
+ m_fineVAngleInput->blockSignals(false);
+ m_antialiasInput->blockSignals(false);
+}
+
+void ImageEffect_ShearTool::prepareEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ m_mainHAngleInput->setEnabled(false);
+ m_mainVAngleInput->setEnabled(false);
+ m_fineHAngleInput->setEnabled(false);
+ m_fineVAngleInput->setEnabled(false);
+ m_antialiasInput->setEnabled(false);
+
+ float hAngle = m_mainHAngleInput->value() + m_fineHAngleInput->value();
+ float vAngle = m_mainVAngleInput->value() + m_fineVAngleInput->value();
+ bool antialiasing = m_antialiasInput->isChecked();
+ TQColor background = paletteBackgroundColor().rgb();
+
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+ int orgW = iface->originalWidth();
+ int orgH = iface->originalHeight();
+
+ uchar *data = iface->getPreviewImage();
+ Digikam::DImg image(iface->previewWidth(), iface->previewHeight(), iface->previewSixteenBit(),
+ iface->previewHasAlpha(), data);
+ delete [] data;
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new ShearTool(&image, this, hAngle, vAngle, antialiasing, background, orgW, orgH));
+}
+
+void ImageEffect_ShearTool::prepareFinal()
+{
+ m_mainHAngleInput->setEnabled(false);
+ m_mainVAngleInput->setEnabled(false);
+ m_fineHAngleInput->setEnabled(false);
+ m_fineVAngleInput->setEnabled(false);
+ m_antialiasInput->setEnabled(false);
+
+ float hAngle = m_mainHAngleInput->value() + m_fineHAngleInput->value();
+ float vAngle = m_mainVAngleInput->value() + m_fineVAngleInput->value();
+ bool antialiasing = m_antialiasInput->isChecked();
+ TQColor background = TQt::black;
+
+ Digikam::ImageIface iface(0, 0);
+ int orgW = iface.originalWidth();
+ int orgH = iface.originalHeight();
+
+ uchar *data = iface.getOriginalImage();
+ Digikam::DImg orgImage(orgW, orgH, iface.originalSixteenBit(),
+ iface.originalHasAlpha(), data);
+ delete [] data;
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new ShearTool(&orgImage, this, hAngle, vAngle, antialiasing, background, orgW, orgH));
+}
+
+void ImageEffect_ShearTool::putPreviewData(void)
+{
+ Digikam::ImageIface* iface = m_imagePreviewWidget->imageIface();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+
+ Digikam::DImg imTemp = m_threadedFilter->getTargetImage().smoothScale(w, h, TQSize::ScaleMin);
+ Digikam::DImg imDest( w, h, m_threadedFilter->getTargetImage().sixteenBit(),
+ m_threadedFilter->getTargetImage().hasAlpha() );
+
+ imDest.fill( Digikam::DColor(paletteBackgroundColor().rgb(),
+ m_threadedFilter->getTargetImage().sixteenBit()) );
+ imDest.bitBltImage(&imTemp, (w-imTemp.width())/2, (h-imTemp.height())/2);
+
+ iface->putPreviewImage((imDest.smoothScale(iface->previewWidth(),
+ iface->previewHeight())).bits());
+
+ m_imagePreviewWidget->updatePreview();
+ TQSize newSize = dynamic_cast<ShearTool *>(m_threadedFilter)->getNewSize();
+ TQString temp;
+ m_newWidthLabel->setText(temp.setNum( newSize.width()) + i18n(" px") );
+ m_newHeightLabel->setText(temp.setNum( newSize.height()) + i18n(" px") );
+}
+
+void ImageEffect_ShearTool::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ Digikam::DImg targetImage = m_threadedFilter->getTargetImage();
+ iface.putOriginalImage(i18n("Shear Tool"),
+ targetImage.bits(),
+ targetImage.width(), targetImage.height());
+}
+
+void ImageEffect_ShearTool::renderingFinished()
+{
+ m_mainHAngleInput->setEnabled(true);
+ m_mainVAngleInput->setEnabled(true);
+ m_fineHAngleInput->setEnabled(true);
+ m_fineVAngleInput->setEnabled(true);
+ m_antialiasInput->setEnabled(true);
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamShearToolImagesPlugin
+
diff --git a/src/imageplugins/sheartool/imageeffect_sheartool.h b/src/imageplugins/sheartool/imageeffect_sheartool.h
new file mode 100644
index 00000000..311b4e0d
--- /dev/null
+++ b/src/imageplugins/sheartool/imageeffect_sheartool.h
@@ -0,0 +1,82 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-23
+ * Description : a plugin to shear an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_SHEARTOOL_H
+#define IMAGEEFFECT_SHEARTOOL_H
+
+// Local includes.
+
+#include "imageguidedlg.h"
+
+class TQFrame;
+class TQPushButton;
+class TQCheckBox;
+class TQLabel;
+
+class KIntNumInput;
+class KDoubleNumInput;
+
+namespace DigikamShearToolImagesPlugin
+{
+
+class ImageEffect_ShearTool : public Digikam::ImageGuideDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_ShearTool(TQWidget* parent);
+ ~ImageEffect_ShearTool();
+
+private slots:
+
+ void readUserSettings(void);
+
+protected:
+
+ void writeUserSettings(void);
+ void prepareEffect(void);
+ void prepareFinal(void);
+ void putPreviewData(void);
+ void putFinalData(void);
+ void resetValues(void);
+ void renderingFinished(void);
+
+private:
+
+ TQLabel *m_newWidthLabel;
+ TQLabel *m_newHeightLabel;
+
+ TQCheckBox *m_antialiasInput;
+
+ KIntNumInput *m_mainHAngleInput;
+ KIntNumInput *m_mainVAngleInput;
+
+ KDoubleNumInput *m_fineHAngleInput;
+ KDoubleNumInput *m_fineVAngleInput;
+};
+
+} // NameSpace DigikamShearToolImagesPlugin
+
+#endif /* IMAGEEFFECT_SHEARTOOL_H */
diff --git a/src/imageplugins/sheartool/imageplugin_sheartool.cpp b/src/imageplugins/sheartool/imageplugin_sheartool.cpp
new file mode 100644
index 00000000..34030899
--- /dev/null
+++ b/src/imageplugins/sheartool/imageplugin_sheartool.cpp
@@ -0,0 +1,69 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-23
+ * Description : a plugin to shear an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "sheartool.h"
+#include "imageplugin_sheartool.h"
+#include "imageplugin_sheartool.moc"
+
+using namespace DigikamShearToolImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_sheartool,
+ KGenericFactory<ImagePlugin_ShearTool>("digikamimageplugin_sheartool"));
+
+ImagePlugin_ShearTool::ImagePlugin_ShearTool(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_ShearTool")
+{
+ m_sheartoolAction = new TDEAction(i18n("Shear..."), "shear", 0,
+ this, TQ_SLOT(slotShearTool()),
+ actionCollection(), "imageplugin_sheartool");
+
+ setXMLFile("digikamimageplugin_sheartool_ui.rc");
+
+ DDebug() << "ImagePlugin_ShearTool plugin loaded" << endl;
+}
+
+ImagePlugin_ShearTool::~ImagePlugin_ShearTool()
+{
+}
+
+void ImagePlugin_ShearTool::setEnabledActions(bool enable)
+{
+ m_sheartoolAction->setEnabled(enable);
+}
+
+void ImagePlugin_ShearTool::slotShearTool()
+{
+ ShearTool *tool = new ShearTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/sheartool/imageplugin_sheartool.h b/src/imageplugins/sheartool/imageplugin_sheartool.h
new file mode 100644
index 00000000..2423a1b1
--- /dev/null
+++ b/src/imageplugins/sheartool/imageplugin_sheartool.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-23
+ * Description : a plugin to shear an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_SHEARTOOL_H
+#define IMAGEPLUGIN_SHEARTOOL_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_ShearTool : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_ShearTool(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_ShearTool();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotShearTool();
+
+private:
+
+ TDEAction *m_sheartoolAction;
+};
+
+#endif /* IMAGEPLUGIN_SHEARTOOL_H */
diff --git a/src/imageplugins/sheartool/shear.cpp b/src/imageplugins/sheartool/shear.cpp
new file mode 100644
index 00000000..29af5390
--- /dev/null
+++ b/src/imageplugins/sheartool/shear.cpp
@@ -0,0 +1,185 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-18
+ * Description : Shear threaded image filter.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ *
+ * Original Shear algorithms copyrighted 2005 by
+ * Pieter Z. Voloshyn <pieter dot voloshyn at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Degrees to radian convertion coeff (PI/180). To optimize computation.
+#define DEG2RAD 0.017453292519943
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Local includes.
+
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "shear.h"
+
+namespace DigikamShearToolImagesPlugin
+{
+
+Shear::Shear(Digikam::DImg *orgImage, TQObject *parent, float hAngle, float vAngle,
+ bool antialiasing, TQColor backgroundColor, int orgW, int orgH)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "sheartool")
+{
+ m_hAngle = hAngle;
+ m_vAngle = vAngle;
+ m_orgW = orgW;
+ m_orgH = orgH;
+ m_antiAlias = antialiasing;
+ m_backgroundColor = backgroundColor;
+
+ initFilter();
+}
+
+void Shear::filterImage(void)
+{
+ int progress;
+ int x, y, p = 0, pt;
+ int new_width, new_height;
+ double nx, ny, dx, dy;
+ double horz_factor, vert_factor;
+ double horz_add, vert_add;
+ double horz_beta_angle, vert_beta_angle;
+
+ int nWidth = m_orgImage.width();
+ int nHeight = m_orgImage.height();
+
+ uchar *pBits = m_orgImage.bits();
+ unsigned short *pBits16 = (unsigned short*)m_orgImage.bits();
+
+ // get beta ( complementary ) angle for horizontal and vertical angles
+ horz_beta_angle = ( ( ( m_hAngle < 0.0 ) ? 180.0 : 90.0 ) - m_hAngle ) * DEG2RAD;
+ vert_beta_angle = ( ( ( m_vAngle < 0.0 ) ? 180.0 : 90.0 ) - m_vAngle ) * DEG2RAD;
+
+ // get new distance for width and height values
+ horz_add = nHeight * ( ( m_hAngle < 0.0 ) ? sin( horz_beta_angle ) : cos( horz_beta_angle ) );
+ vert_add = nWidth * ( ( m_vAngle < 0.0 ) ? sin( vert_beta_angle ) : cos( vert_beta_angle ) );
+
+ // get absolute values for the distances
+ horz_add = fabs( horz_add );
+ vert_add = fabs( vert_add );
+
+ // get new image size ( original size + distance )
+ new_width = (int)horz_add + nWidth;
+ new_height = (int)vert_add + nHeight;
+
+ // get scale factor for width and height
+ horz_factor = horz_add / new_height;
+ vert_factor = vert_add / new_width;
+
+ // if horizontal angle is greater than zero...
+ // else, initial distance is equal to maximum distance ( in negative form )
+ if( m_hAngle > 0.0 )
+ {
+ // initial distance is zero and scale is negative ( to decrease )
+ dx = 0;
+ horz_factor *= -1.0;
+ }
+ else
+ {
+ dx = -horz_add;
+ }
+
+ // if vertical angle is greater than zero...
+ // else, initial distance is equal to maximum distance ( in negative form )
+ if( m_vAngle > 0.0 )
+ {
+ // initial distance is zero and scale is negative ( to decrease )
+ dy = 0;
+ vert_factor *= -1.0;
+ }
+ else
+ {
+ dy = -vert_add;
+ }
+
+ // allocates a new image with the new size
+
+ bool sixteenBit = m_orgImage.sixteenBit();
+
+ m_destImage = Digikam::DImg(new_width, new_height, sixteenBit, m_orgImage.hasAlpha());
+ m_destImage.fill( Digikam::DColor(m_backgroundColor.rgb(), sixteenBit) );
+
+ uchar *pResBits = m_destImage.bits();
+ unsigned short *pResBits16 = (unsigned short *)m_destImage.bits();
+
+ Digikam::DImgImageFilters filters;
+
+ for( y = 0; y < new_height; y++)
+ {
+ for( x = 0; x < new_width; x++, p += 4 )
+ {
+ // get new positions
+ nx = x + dx + y * horz_factor;
+ ny = y + dy + x * vert_factor;
+
+ // if is inside the source image
+ if (isInside (nWidth, nHeight, ROUND( nx ), ROUND( ny )))
+ {
+ if( m_antiAlias )
+ {
+ if (!sixteenBit)
+ filters.pixelAntiAliasing(pBits, nWidth, nHeight, nx, ny,
+ &pResBits[p+3], &pResBits[p+2],
+ &pResBits[p+1], &pResBits[p]);
+ else
+ filters.pixelAntiAliasing16(pBits16, nWidth, nHeight, nx, ny,
+ &pResBits16[p+3], &pResBits16[p+2],
+ &pResBits16[p+1], &pResBits16[p]);
+ }
+ else
+ {
+ pt = setPosition (nWidth, ROUND( nx ), ROUND( ny ));
+
+ for (int z = 0 ; z < 4 ; z++)
+ {
+ if (!sixteenBit)
+ pResBits[p+z] = pBits[pt+z];
+ else
+ pResBits16[p+z] = pBits16[pt+z];
+ }
+ }
+ }
+ }
+
+ // Update the progress bar in dialog.
+ progress = (int)(((double)y * 100.0) / new_height);
+ if (progress%5 == 0)
+ postProgress( progress );
+ }
+
+ // To compute the rotated destination image size using original image dimensions.
+ int W = (int)(fabs(m_orgH * ( ( m_hAngle < 0.0 ) ? sin( horz_beta_angle ) : cos( horz_beta_angle ))))+
+ m_orgW;
+ int H = (int)(fabs(m_orgW * ( ( m_vAngle < 0.0 ) ? sin( vert_beta_angle ) : cos( vert_beta_angle ))))+
+ m_orgH;
+
+ m_newSize.setWidth(W);
+ m_newSize.setHeight(H);
+}
+
+} // NameSpace DigikamShearToolImagesPlugin
diff --git a/src/imageplugins/sheartool/shear.h b/src/imageplugins/sheartool/shear.h
new file mode 100644
index 00000000..480d1084
--- /dev/null
+++ b/src/imageplugins/sheartool/shear.h
@@ -0,0 +1,84 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-07-18
+ * Description : Shear threaded image filter.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SHEAR_H
+#define SHEAR_H
+
+// TQt includes.
+
+#include <tqsize.h>
+#include <tqcolor.h>
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamShearToolImagesPlugin
+{
+
+class Shear : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ Shear(Digikam::DImg *orgImage, TQObject *parent=0, float hAngle=0.0, float vAngle=0.0,
+ bool antialiasing=true, TQColor backgroundColor=TQt::black, int orgW=0, int orgH=0);
+
+ ~Shear(){};
+
+ TQSize getNewSize(void){ return m_newSize; };
+
+private:
+
+ virtual void filterImage(void);
+
+ inline int setPosition (int Width, int X, int Y)
+ {
+ return (Y *Width*4 + 4*X);
+ };
+
+ inline bool isInside (int Width, int Height, int X, int Y)
+ {
+ bool bIsWOk = ((X < 0) ? false : (X >= Width ) ? false : true);
+ bool bIsHOk = ((Y < 0) ? false : (Y >= Height) ? false : true);
+ return (bIsWOk && bIsHOk);
+ };
+
+private:
+
+ bool m_antiAlias;
+
+ int m_orgW;
+ int m_orgH;
+
+ float m_hAngle;
+ float m_vAngle;
+
+ TQColor m_backgroundColor;
+
+ TQSize m_newSize;
+};
+
+} // NameSpace DigikamShearToolImagesPlugin
+
+#endif /* SHEAR_H */
diff --git a/src/imageplugins/sheartool/sheartool.cpp b/src/imageplugins/sheartool/sheartool.cpp
new file mode 100644
index 00000000..9f65b6d3
--- /dev/null
+++ b/src/imageplugins/sheartool/sheartool.cpp
@@ -0,0 +1,331 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-23
+ * Description : a plugin to shear an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcheckbox.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kseparator.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "editortoolsettings.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "shear.h"
+#include "sheartool.h"
+#include "sheartool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamShearToolImagesPlugin
+{
+
+ShearTool::ShearTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("sheartool");
+ setToolName(i18n("Shear Tool"));
+ setToolIcon(SmallIcon("sheartool"));
+
+ m_previewWidget = new ImageWidget("sheartool Tool", 0,
+ i18n("<p>This is the shear operation preview. "
+ "If you move the mouse cursor on this preview, "
+ "a vertical and horizontal dashed line will be drawn "
+ "to guide you in adjusting the shear correction. "
+ "Release the left mouse button to freeze the dashed "
+ "line's position."),
+ false, ImageGuideWidget::HVGuideMode);
+
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQString temp;
+ Digikam::ImageIface iface(0, 0);
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel,
+ EditorToolSettings::ColorGuide);
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 12, 2);
+
+ TQLabel *label1 = new TQLabel(i18n("New width:"), m_gboxSettings->plainPage());
+ m_newWidthLabel = new TQLabel(temp.setNum( iface.originalWidth()) + i18n(" px"), m_gboxSettings->plainPage());
+ m_newWidthLabel->setAlignment( AlignBottom | AlignRight );
+
+ TQLabel *label2 = new TQLabel(i18n("New height:"), m_gboxSettings->plainPage());
+ m_newHeightLabel = new TQLabel(temp.setNum( iface.originalHeight()) + i18n(" px"), m_gboxSettings->plainPage());
+ m_newHeightLabel->setAlignment( AlignBottom | AlignRight );
+
+ KSeparator *line = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ TQLabel *label3 = new TQLabel(i18n("Main horizontal angle:"), m_gboxSettings->plainPage());
+ m_mainHAngleInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_mainHAngleInput->setRange(-45, 45, 1);
+ m_mainHAngleInput->setDefaultValue(0);
+ TQWhatsThis::add( m_mainHAngleInput, i18n("<p>The main horizontal shearing angle, in degrees."));
+
+ TQLabel *label4 = new TQLabel(i18n("Fine horizontal angle:"), m_gboxSettings->plainPage());
+ m_fineHAngleInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_fineHAngleInput->setRange(-5.0, 5.0, 0.01);
+ m_fineHAngleInput->setDefaultValue(0);
+ TQWhatsThis::add( m_fineHAngleInput, i18n("<p>This value in degrees will be added to main horizontal angle value "
+ "to set fine adjustments."));
+
+ TQLabel *label5 = new TQLabel(i18n("Main vertical angle:"), m_gboxSettings->plainPage());
+ m_mainVAngleInput = new RIntNumInput(m_gboxSettings->plainPage());
+ m_mainVAngleInput->setRange(-45, 45, 1);
+ m_mainVAngleInput->setDefaultValue(0);
+ TQWhatsThis::add( m_mainVAngleInput, i18n("<p>The main vertical shearing angle, in degrees."));
+
+ TQLabel *label6 = new TQLabel(i18n("Fine vertical angle:"), m_gboxSettings->plainPage());
+ m_fineVAngleInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_fineVAngleInput->setRange(-5.0, 5.0, 0.01);
+ m_fineVAngleInput->setDefaultValue(0);
+ TQWhatsThis::add( m_fineVAngleInput, i18n("<p>This value in degrees will be added to main vertical angle value "
+ "to set fine adjustments."));
+
+ m_antialiasInput = new TQCheckBox(i18n("Anti-Aliasing"), m_gboxSettings->plainPage());
+ TQWhatsThis::add( m_antialiasInput, i18n("<p>Enable this option to apply the anti-aliasing filter "
+ "to the sheared image. "
+ "To smooth the target image, it will be blurred a little."));
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 0);
+ grid->addMultiCellWidget(m_newWidthLabel, 0, 0, 1, 2);
+ grid->addMultiCellWidget(label2, 1, 1, 0, 0);
+ grid->addMultiCellWidget(m_newHeightLabel, 1, 1, 1, 2);
+ grid->addMultiCellWidget(line, 2, 2, 0, 2);
+ grid->addMultiCellWidget(label3, 3, 3, 0, 2);
+ grid->addMultiCellWidget(m_mainHAngleInput, 4, 4, 0, 2);
+ grid->addMultiCellWidget(label4, 5, 5, 0, 2);
+ grid->addMultiCellWidget(m_fineHAngleInput, 6, 6, 0, 2);
+ grid->addMultiCellWidget(label5, 7, 7, 0, 0);
+ grid->addMultiCellWidget(m_mainVAngleInput, 8, 8, 0, 2);
+ grid->addMultiCellWidget(label6, 9, 9, 0, 2);
+ grid->addMultiCellWidget(m_fineVAngleInput, 10, 10, 0, 2);
+ grid->addMultiCellWidget(m_antialiasInput, 11, 11, 0, 2);
+ grid->setRowStretch(12, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_mainHAngleInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_fineHAngleInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_mainVAngleInput, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_fineVAngleInput, TQ_SIGNAL(valueChanged(double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_antialiasInput, TQ_SIGNAL(toggled(bool)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_gboxSettings, TQ_SIGNAL(signalColorGuideChanged()),
+ this, TQ_SLOT(slotColorGuideChanged()));
+}
+
+ShearTool::~ShearTool()
+{
+}
+
+void ShearTool::slotColorGuideChanged()
+{
+ m_previewWidget->slotChangeGuideColor(m_gboxSettings->guideColor());
+ m_previewWidget->slotChangeGuideSize(m_gboxSettings->guideSize());
+}
+
+void ShearTool::readSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("sheartool Tool");
+ m_mainHAngleInput->setValue(config->readNumEntry("Main HAngle", m_mainHAngleInput->defaultValue()));
+ m_mainVAngleInput->setValue(config->readNumEntry("Main VAngle", m_mainVAngleInput->defaultValue()));
+ m_fineHAngleInput->setValue(config->readDoubleNumEntry("Fine HAngle", m_fineHAngleInput->defaultValue()));
+ m_fineVAngleInput->setValue(config->readDoubleNumEntry("Fine VAngle", m_fineVAngleInput->defaultValue()));
+ m_antialiasInput->setChecked(config->readBoolEntry("Anti Aliasing", true));
+ m_gboxSettings->setGuideColor(config->readColorEntry("Guide Color", &TQt::red));
+ m_gboxSettings->setGuideSize(config->readNumEntry("Guide Width", 1));
+
+ slotColorGuideChanged();
+ slotEffect();
+}
+
+void ShearTool::writeSettings()
+{
+ TDEConfig *config = kapp->config();
+ config->setGroup("sheartool Tool");
+ config->writeEntry("Main HAngle", m_mainHAngleInput->value());
+ config->writeEntry("Main VAngle", m_mainVAngleInput->value());
+ config->writeEntry("Fine HAngle", m_fineHAngleInput->value());
+ config->writeEntry("Fine VAngle", m_fineVAngleInput->value());
+ config->writeEntry("Anti Aliasing", m_antialiasInput->isChecked());
+ config->writeEntry("Guide Color", m_gboxSettings->guideColor());
+ config->writeEntry("Guide Width", m_gboxSettings->guideSize());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void ShearTool::slotResetSettings()
+{
+ m_mainHAngleInput->blockSignals(true);
+ m_mainVAngleInput->blockSignals(true);
+ m_fineHAngleInput->blockSignals(true);
+ m_fineVAngleInput->blockSignals(true);
+ m_antialiasInput->blockSignals(true);
+
+ m_mainHAngleInput->slotReset();
+ m_mainVAngleInput->slotReset();
+ m_fineHAngleInput->slotReset();
+ m_fineVAngleInput->slotReset();
+ m_antialiasInput->setChecked(true);
+
+ m_mainHAngleInput->blockSignals(false);
+ m_mainVAngleInput->blockSignals(false);
+ m_fineHAngleInput->blockSignals(false);
+ m_fineVAngleInput->blockSignals(false);
+ m_antialiasInput->blockSignals(false);
+}
+
+void ShearTool::prepareEffect()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ m_mainHAngleInput->setEnabled(false);
+ m_mainVAngleInput->setEnabled(false);
+ m_fineHAngleInput->setEnabled(false);
+ m_fineVAngleInput->setEnabled(false);
+ m_antialiasInput->setEnabled(false);
+
+ float hAngle = m_mainHAngleInput->value() + m_fineHAngleInput->value();
+ float vAngle = m_mainVAngleInput->value() + m_fineVAngleInput->value();
+ bool antialiasing = m_antialiasInput->isChecked();
+ TQColor background = m_previewWidget->paletteBackgroundColor().rgb();
+ ImageIface* iface = m_previewWidget->imageIface();
+ int orgW = iface->originalWidth();
+ int orgH = iface->originalHeight();
+ uchar *data = iface->getPreviewImage();
+ DImg image(iface->previewWidth(), iface->previewHeight(), iface->previewSixteenBit(),
+ iface->previewHasAlpha(), data);
+ delete [] data;
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Shear(&image, this, hAngle, vAngle, antialiasing,
+ background, orgW, orgH)));
+}
+
+void ShearTool::prepareFinal()
+{
+ m_mainHAngleInput->setEnabled(false);
+ m_mainVAngleInput->setEnabled(false);
+ m_fineHAngleInput->setEnabled(false);
+ m_fineVAngleInput->setEnabled(false);
+ m_antialiasInput->setEnabled(false);
+
+ float hAngle = m_mainHAngleInput->value() + m_fineHAngleInput->value();
+ float vAngle = m_mainVAngleInput->value() + m_fineVAngleInput->value();
+ bool antialiasing = m_antialiasInput->isChecked();
+ TQColor background = TQt::black;
+
+ ImageIface iface(0, 0);
+ int orgW = iface.originalWidth();
+ int orgH = iface.originalHeight();
+
+ uchar *data = iface.getOriginalImage();
+ DImg orgImage(orgW, orgH, iface.originalSixteenBit(), iface.originalHasAlpha(), data);
+ delete [] data;
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Shear(&orgImage, this, hAngle, vAngle, antialiasing,
+ background, orgW, orgH)));
+}
+
+void ShearTool::putPreviewData()
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ DImg imTemp = filter()->getTargetImage().smoothScale(w, h, TQSize::ScaleMin);
+ DImg imDest( w, h, filter()->getTargetImage().sixteenBit(),
+ filter()->getTargetImage().hasAlpha() );
+
+ imDest.fill(DColor(m_previewWidget->paletteBackgroundColor().rgb(),
+ filter()->getTargetImage().sixteenBit()) );
+ imDest.bitBltImage(&imTemp, (w-imTemp.width())/2, (h-imTemp.height())/2);
+
+ iface->putPreviewImage((imDest.smoothScale(iface->previewWidth(),
+ iface->previewHeight())).bits());
+
+ m_previewWidget->updatePreview();
+ TQSize newSize = dynamic_cast<Shear*>(filter())->getNewSize();
+ TQString temp;
+ m_newWidthLabel->setText(temp.setNum( newSize.width()) + i18n(" px") );
+ m_newHeightLabel->setText(temp.setNum( newSize.height()) + i18n(" px") );
+}
+
+void ShearTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ DImg targetImage = filter()->getTargetImage();
+ iface.putOriginalImage(i18n("Shear Tool"),
+ targetImage.bits(),
+ targetImage.width(), targetImage.height());
+}
+
+void ShearTool::renderingFinished()
+{
+ m_mainHAngleInput->setEnabled(true);
+ m_mainVAngleInput->setEnabled(true);
+ m_fineHAngleInput->setEnabled(true);
+ m_fineVAngleInput->setEnabled(true);
+ m_antialiasInput->setEnabled(true);
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamShearToolImagesPlugin
diff --git a/src/imageplugins/sheartool/sheartool.h b/src/imageplugins/sheartool/sheartool.h
new file mode 100644
index 00000000..1c8161b4
--- /dev/null
+++ b/src/imageplugins/sheartool/sheartool.h
@@ -0,0 +1,96 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2004-12-23
+ * Description : a plugin to shear an image
+ *
+ * Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SHEARTOOL_H
+#define SHEARTOOL_H
+
+// Local includes.
+
+#include "editortool.h"
+
+class TQFrame;
+class TQPushButton;
+class TQCheckBox;
+class TQLabel;
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RDoubleNumInput;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImageWidget;
+}
+
+namespace DigikamShearToolImagesPlugin
+{
+
+class ShearTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ ShearTool(TQObject* parent);
+ ~ShearTool();
+
+private slots:
+
+ void slotResetSettings();
+ void slotColorGuideChanged();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ TQLabel *m_newWidthLabel;
+ TQLabel *m_newHeightLabel;
+
+ TQCheckBox *m_antialiasInput;
+
+ KDcrawIface::RIntNumInput *m_mainHAngleInput;
+ KDcrawIface::RIntNumInput *m_mainVAngleInput;
+
+ KDcrawIface::RDoubleNumInput *m_fineHAngleInput;
+ KDcrawIface::RDoubleNumInput *m_fineVAngleInput;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamShearToolImagesPlugin
+
+#endif /* SHEARTOOL_H */
diff --git a/src/imageplugins/superimpose/Makefile.am b/src/imageplugins/superimpose/Makefile.am
new file mode 100644
index 00000000..686eff2a
--- /dev/null
+++ b/src/imageplugins/superimpose/Makefile.am
@@ -0,0 +1,35 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/libs/thumbbar \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_superimpose_la_SOURCES = superimposewidget.cpp superimpose.cpp dirselectwidget.cpp \
+ imageplugin_superimpose.cpp superimposetool.cpp
+
+
+digikamimageplugin_superimpose_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_superimpose_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_superimpose.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_superimpose.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_superimpose_ui.rc
diff --git a/src/imageplugins/superimpose/digikamimageplugin_superimpose.desktop b/src/imageplugins/superimpose/digikamimageplugin_superimpose.desktop
new file mode 100644
index 00000000..ef395a4a
--- /dev/null
+++ b/src/imageplugins/superimpose/digikamimageplugin_superimpose.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_SuperImpose
+Name[bg]=Приставка за снимки - Налагане
+Name[da]=Billedplugin_Indkopiering
+Name[el]=ΠρόσθετοΕικόνας_Υπερέκθεση
+Name[fi]=SuperImpose
+Name[hr]=Presvlačenje
+Name[it]=PluginImmagini_Sovrapposizione
+Name[nl]=Afbeeldingsplugin_SjabloonAanbrengen
+Name[sr]=Надоградња
+Name[sr@Latn]=Nadogradnja
+Name[sv]=Insticksprogram för överlagring
+Name[tr]=ResimEklentisi_Büyüt
+Name[xx]=xxImagePlugin_SuperImposexx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=Template superimpose plugin for digiKam
+Comment[bg]=Приставка на digiKam за налагане на снимки една върху друга
+Comment[ca]=Connector pel digiKam per sobreimposar una plantilla
+Comment[da]=Plugin til skabelon-indkopiering i Digikam
+Comment[de]=digiKam-Modul zum Anwenden von Schablonen auf ein Bild
+Comment[el]=Πρόσθετο πρότυπης υπερέκθεσης για το digiKam
+Comment[es]=Plugin de digiKam para superponer una plantilla sobre la imagen
+Comment[et]=DigiKami pildile malli lisamise plugin
+Comment[fa]=وصلۀ افزودن قالب برای digiKam
+Comment[fi]=Liittää useampia kuvia päällekäin
+Comment[gl]=Un plugin de digiKam para sobrepor modelos
+Comment[hr]=digiKam dodatak za presvlačenje predloškom
+Comment[is]=Íforrit fyrir digiKam sem hleður forsniðinni mynd ofan á þá sem unnið er með
+Comment[it]=Plugin di sovrapposizione di modelli per digiKam
+Comment[ja]=digiKam テンプレート重ね合わせプラグイン
+Comment[ms]=Templat plugin superimpose untuk digiKam
+Comment[nds]=digiKam-Moduul för't Vörblennen vun Vörlagen
+Comment[nl]=Digikam-plugin voor het aanbrengen van een sjabloon op de afbeelding
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਨਮੂਨਾ ਸੁਪਰ-ਇਮਪੋਜ਼ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam umożliwiająca nałożenie szablonu na obraz
+Comment[pt]=Um 'plugin' do digiKam para sobrepor modelos
+Comment[pt_BR]=Um 'plugin' do digiKam para sobrepor modelos
+Comment[ru]=Модуль накладывания шаблона для digiKam
+Comment[sk]=digiKam plugin pre prekrytie fotografie šablónou
+Comment[sr]=digiKam-ов прикључак надоградњу шаблонима
+Comment[sr@Latn]=digiKam-ov priključak nadogradnju šablonima
+Comment[sv]=Digikam insticksprogram för överlagringsmall
+Comment[tr]=digiKam için şablon büyütme eklentisi
+Comment[uk]=Втулок накладання шаблону для digiKam
+Comment[vi]=Phần bổ sung đặt biểu mẫu trên cho digiKam
+Comment[xx]=xxTemplate superimpose plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_superimpose
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/superimpose/digikamimageplugin_superimpose_ui.rc b/src/imageplugins/superimpose/digikamimageplugin_superimpose_ui.rc
new file mode 100644
index 00000000..ced7edac
--- /dev/null
+++ b/src/imageplugins/superimpose/digikamimageplugin_superimpose_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="4" name="digikamimageplugin_superimpose" >
+
+ <MenuBar>
+
+ <Menu name="Decorate" ><text>&amp;Decorate</text>
+ <Action name="imageplugin_superimpose" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_superimpose" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/superimpose/dirselectwidget.cpp b/src/imageplugins/superimpose/dirselectwidget.cpp
new file mode 100644
index 00000000..4856d73c
--- /dev/null
+++ b/src/imageplugins/superimpose/dirselectwidget.cpp
@@ -0,0 +1,182 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlayout.h>
+#include <tqheader.h>
+#include <tqlistview.h>
+#include <tqdir.h>
+
+// KDE includes.
+
+#include <tdelocale.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "dirselectwidget.h"
+#include "dirselectwidget.moc"
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+struct DirSelectWidget::Private
+{
+ KFileTreeBranch* m_item;
+ TQStringList m_pendingPath;
+ TQString m_handled;
+ KURL m_rootUrl;
+};
+
+DirSelectWidget::DirSelectWidget(TQWidget* parent, const char* name, TQString headerLabel)
+ : KFileTreeView( parent, name)
+{
+ d = new Private;
+
+ addColumn( headerLabel );
+
+ if ( headerLabel.isNull() )
+ header()->hide();
+
+ setAlternateBackground(TQColor());
+}
+
+DirSelectWidget::DirSelectWidget(KURL rootUrl, KURL currentUrl,
+ TQWidget* parent, const char* name, TQString headerLabel)
+ : KFileTreeView( parent, name)
+{
+ d = new Private;
+
+ addColumn( headerLabel );
+
+ if ( headerLabel.isNull() )
+ header()->hide();
+
+ setAlternateBackground(TQColor());
+ setRootPath(rootUrl, currentUrl);
+}
+
+DirSelectWidget::~DirSelectWidget()
+{
+ delete d;
+}
+
+KURL DirSelectWidget::path() const
+{
+ return currentURL();
+}
+
+void DirSelectWidget::load()
+{
+ if ( d->m_pendingPath.isEmpty() )
+ {
+ disconnect( d->m_item, TQ_SIGNAL( populateFinished(KFileTreeViewItem *) ),
+ this, TQ_SLOT( load() ) );
+
+ emit folderItemSelected(currentURL());
+ return;
+ }
+
+ TQString item = d->m_pendingPath.front();
+ d->m_pendingPath.pop_front();
+ d->m_handled += item;
+ KFileTreeViewItem* branch = findItem( d->m_item, d->m_handled );
+
+ if ( !branch )
+ {
+ DDebug() << "Unable to open " << d->m_handled << endl;
+ }
+ else
+ {
+ branch->setOpen( true );
+ setSelected( branch, true );
+ ensureItemVisible ( branch );
+ d->m_handled += '/';
+
+ if ( branch->alreadyListed() )
+ load();
+ }
+}
+
+void DirSelectWidget::setCurrentPath(KURL currentUrl)
+{
+ if ( !currentUrl.isValid() )
+ return;
+
+ TQString currentPath = TQDir::cleanDirPath(currentUrl.path());
+ currentPath = currentPath.mid( d->m_rootUrl.path().length() );
+ d->m_pendingPath.clear();
+ d->m_handled = TQString("");
+ d->m_pendingPath = TQStringList::split( "/", currentPath, true );
+
+ if ( !d->m_pendingPath[0].isEmpty() )
+ d->m_pendingPath.prepend( "" ); // ensure we open the root first.
+
+ connect( d->m_item, TQ_SIGNAL( populateFinished(KFileTreeViewItem *) ),
+ this, TQ_SLOT( load() ) );
+ load();
+}
+
+void DirSelectWidget::setRootPath(KURL rootUrl, KURL currentUrl)
+{
+ d->m_rootUrl = rootUrl;
+ clear();
+ TQString root = TQDir::cleanDirPath(rootUrl.path());
+
+ if ( !root.endsWith("/"))
+ root.append("/");
+
+ TQString currentPath = TQDir::cleanDirPath(currentUrl.isValid() ? currentUrl.path() : root);
+
+ d->m_item = addBranch( rootUrl, rootUrl.fileName() );
+ setDirOnlyMode( d->m_item, true );
+ currentPath = currentPath.mid( root.length() );
+ d->m_pendingPath = TQStringList::split( "/", currentPath, true );
+
+ if ( !d->m_pendingPath[0].isEmpty() )
+ d->m_pendingPath.prepend( "" ); // ensure we open the root first.
+
+ connect( d->m_item, TQ_SIGNAL( populateFinished(KFileTreeViewItem *) ),
+ this, TQ_SLOT( load() ) );
+
+ load();
+
+ connect( this, TQ_SIGNAL( executed(TQListViewItem *) ),
+ this, TQ_SLOT( slotFolderSelected(TQListViewItem *) ) );
+}
+
+KURL DirSelectWidget::rootPath(void)
+{
+ return d->m_rootUrl;
+}
+
+void DirSelectWidget::slotFolderSelected(TQListViewItem *)
+{
+ emit folderItemSelected(currentURL());
+}
+
+} // NameSpace DigikamSuperImposeImagesPlugin
+
diff --git a/src/imageplugins/superimpose/dirselectwidget.h b/src/imageplugins/superimpose/dirselectwidget.h
new file mode 100644
index 00000000..1ee4abc2
--- /dev/null
+++ b/src/imageplugins/superimpose/dirselectwidget.h
@@ -0,0 +1,78 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef DIRSELECTWIDGET_H
+#define DIRSELECTWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqstring.h>
+
+// KDE includes.
+
+#include <tdefiletreeview.h>
+#include <kurl.h>
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+class DirSelectWidget : public KFileTreeView
+{
+TQ_OBJECT
+
+
+public:
+
+ DirSelectWidget(TQWidget* parent, const char* name=0, TQString headerLabel=TQString());
+
+ DirSelectWidget(KURL rootUrl=KURL("/"), KURL currentUrl=KURL(),
+ TQWidget* parent=0, const char* name=0, TQString headerLabel=TQString());
+
+ ~DirSelectWidget();
+
+ KURL path() const;
+ KURL rootPath(void);
+ void setRootPath(KURL rootUrl, KURL currentUrl=KURL(TQString()));
+ void setCurrentPath(KURL currentUrl);
+
+signals :
+
+ void folderItemSelected(const KURL &url);
+
+protected slots:
+
+ void load();
+ void slotFolderSelected(TQListViewItem *);
+
+private:
+
+ struct Private;
+ Private* d;
+};
+
+} // NameSpace DigikamSuperImposeImagesPlugin
+
+#endif /* DIRSELECTWIDGET_H */
diff --git a/src/imageplugins/superimpose/imageeffect_superimpose.cpp b/src/imageplugins/superimpose/imageeffect_superimpose.cpp
new file mode 100644
index 00000000..1cea3e08
--- /dev/null
+++ b/src/imageplugins/superimpose/imageeffect_superimpose.cpp
@@ -0,0 +1,280 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqvgroupbox.h>
+#include <tqgroupbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqpixmap.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqdir.h>
+#include <tqfile.h>
+#include <tqhbuttongroup.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+#include <knuminput.h>
+#include <kiconloader.h>
+#include <tdefiledialog.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <tdeglobalsettings.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "thumbbar.h"
+#include "superimposewidget.h"
+#include "dirselectwidget.h"
+#include "imageeffect_superimpose.h"
+#include "imageeffect_superimpose.moc"
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+ImageEffect_SuperImpose::ImageEffect_SuperImpose(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("Template Superimpose to Photograph"),
+ "superimpose", false, false)
+{
+ TQString whatsThis;
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Template Superimpose"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to superimpose a template onto a photograph."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2006, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(plainPage());
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+
+ TQGridLayout* gridFrame = new TQGridLayout( frame, 1, 2, spacingHint());
+ m_previewWidget = new SuperImposeWidget(400, 300, frame);
+ gridFrame->addMultiCellWidget(m_previewWidget, 0, 0, 0, 2);
+ gridFrame->setRowStretch(0, 10);
+ TQWhatsThis::add( m_previewWidget, i18n("<p>This is the preview of the template "
+ "superimposed onto the image.") );
+
+ // -------------------------------------------------------------
+
+ TQHButtonGroup *bGroup = new TQHButtonGroup(frame);
+ TDEIconLoader icon;
+ bGroup->addSpace(0);
+ TQPushButton *zoomInButton = new TQPushButton( bGroup );
+ bGroup->insert(zoomInButton, ZOOMIN);
+ zoomInButton->setPixmap( icon.loadIcon( "zoom-in", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ zoomInButton->setToggleButton(true);
+ TQToolTip::add( zoomInButton, i18n( "Zoom in" ) );
+ bGroup->addSpace(20);
+ TQPushButton *zoomOutButton = new TQPushButton( bGroup );
+ bGroup->insert(zoomOutButton, ZOOMOUT);
+ zoomOutButton->setPixmap( icon.loadIcon( "zoom-out", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ zoomOutButton->setToggleButton(true);
+ TQToolTip::add( zoomOutButton, i18n( "Zoom out" ) );
+ bGroup->addSpace(20);
+ TQPushButton *moveButton = new TQPushButton( bGroup );
+ bGroup->insert(moveButton, MOVE);
+ moveButton->setPixmap( icon.loadIcon( "move", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ moveButton->setToggleButton(true);
+ moveButton->setOn(true);
+ TQToolTip::add( moveButton, i18n( "Move" ) );
+ bGroup->addSpace(20);
+ bGroup->setExclusive(true);
+ bGroup->setFrameShape(TQFrame::NoFrame);
+ gridFrame->addMultiCellWidget(bGroup, 1, 1, 1, 1);
+ gridFrame->setColStretch(0, 10);
+ gridFrame->setColStretch(2, 10);
+
+ setPreviewAreaWidget(frame);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gbox2 = new TQWidget(plainPage());
+ TQGridLayout* grid = new TQGridLayout( gbox2, 1, 1, marginHint(), spacingHint());
+
+ m_thumbnailsBar = new Digikam::ThumbBarView(gbox2);
+ m_dirSelect = new DirSelectWidget(gbox2);
+ TQPushButton *templateDirButton = new TQPushButton( i18n("Root Directory..."), gbox2 );
+ TQWhatsThis::add( templateDirButton, i18n("<p>Set here the current templates' root directory.") );
+
+ grid->addMultiCellWidget(m_thumbnailsBar, 0, 1, 0, 0);
+ grid->addMultiCellWidget(m_dirSelect, 0, 0, 1, 1);
+ grid->addMultiCellWidget(templateDirButton, 1, 1, 1, 1);
+ grid->setColStretch(1, 10);
+
+ setUserAreaWidget(gbox2);
+
+ // -------------------------------------------------------------
+
+ connect(bGroup, TQ_SIGNAL(released(int)),
+ m_previewWidget, TQ_SLOT(slotEditModeChanged(int)));
+
+ connect(m_thumbnailsBar, TQ_SIGNAL(signalURLSelected(const KURL&)),
+ m_previewWidget, TQ_SLOT(slotSetCurrentTemplate(const KURL&)));
+
+ connect(m_dirSelect, TQ_SIGNAL(folderItemSelected(const KURL &)),
+ this, TQ_SLOT(slotTemplateDirChanged(const KURL &)));
+
+ connect(templateDirButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotRootTemplateDirChanged()));
+
+ // -------------------------------------------------------------
+
+ populateTemplates();
+}
+
+ImageEffect_SuperImpose::~ImageEffect_SuperImpose()
+{
+}
+
+void ImageEffect_SuperImpose::populateTemplates(void)
+{
+ m_thumbnailsBar->clear(true);
+
+ if (!m_templatesUrl.isValid() || !m_templatesUrl.isLocalFile())
+ return;
+
+ TQDir dir(m_templatesUrl.path(), "*.png *.PNG");
+
+ if (!dir.exists())
+ return;
+
+ dir.setFilter ( TQDir::Files | TQDir::NoSymLinks );
+
+ const TQFileInfoList* fileinfolist = dir.entryInfoList();
+ if (!fileinfolist)
+ return;
+
+ TQFileInfoListIterator it(*fileinfolist);
+ TQFileInfo* fi;
+
+ while( (fi = it.current() ) )
+ {
+ new Digikam::ThumbBarItem( m_thumbnailsBar, KURL(fi->filePath()) );
+ ++it;
+ }
+}
+
+void ImageEffect_SuperImpose::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("Album Settings");
+ KURL albumDBUrl( config->readPathEntry("Album Path", TDEGlobalSettings::documentPath()) );
+ config->setGroup("superimpose Tool Dialog");
+ config->setGroup("Template Superimpose Tool Settings");
+ m_templatesRootUrl.setPath( config->readEntry("Templates Root URL", albumDBUrl.path()) );
+ m_templatesUrl.setPath( config->readEntry("Templates URL", albumDBUrl.path()) );
+ m_dirSelect->setRootPath(m_templatesRootUrl, m_templatesUrl);
+}
+
+void ImageEffect_SuperImpose::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("superimpose Tool Dialog");
+ config->writeEntry( "Templates Root URL", m_dirSelect->rootPath().path() );
+ config->writeEntry( "Templates URL", m_templatesUrl.path() );
+ config->sync();}
+
+void ImageEffect_SuperImpose::resetValues()
+{
+ m_previewWidget->resetEdit();
+}
+
+void ImageEffect_SuperImpose::slotRootTemplateDirChanged(void)
+{
+ KURL url = KFileDialog::getExistingDirectory(m_templatesRootUrl.path(), kapp->activeWindow(),
+ i18n("Select Template Root Directory to Use"));
+
+ if( url.isValid() )
+ {
+ m_dirSelect->setRootPath(url);
+ m_templatesRootUrl = url;
+ m_templatesUrl = url;
+ populateTemplates();
+ }
+}
+
+void ImageEffect_SuperImpose::slotTemplateDirChanged(const KURL& url)
+{
+ if( url.isValid() )
+ {
+ m_templatesUrl = url;
+ populateTemplates();
+ }
+}
+
+void ImageEffect_SuperImpose::finalRendering()
+{
+ setCursor(KCursor::waitCursor());
+ m_previewWidget->setEnabled(false);
+ m_dirSelect->setEnabled(false);
+ m_thumbnailsBar->setEnabled(false);
+
+ Digikam::ImageIface iface(0, 0);
+ Digikam::DImg img = m_previewWidget->makeSuperImpose();
+ iface.putOriginalImage(i18n("Super Impose"), img.bits(),
+ img.width(), img.height() );
+
+ m_previewWidget->setEnabled(true);
+ m_dirSelect->setEnabled(true);
+ m_thumbnailsBar->setEnabled(true);
+ unsetCursor();
+ accept();
+}
+
+} // NameSpace DigikamSuperImposeImagesPlugin
+
diff --git a/src/imageplugins/superimpose/imageeffect_superimpose.h b/src/imageplugins/superimpose/imageeffect_superimpose.h
new file mode 100644
index 00000000..8eb8c18f
--- /dev/null
+++ b/src/imageplugins/superimpose/imageeffect_superimpose.h
@@ -0,0 +1,87 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_SUPERIMPOSE_H
+#define IMAGEEFFECT_SUPERIMPOSE_H
+
+// KDE include.
+
+#include <kurl.h>
+
+// Digikam includes.
+
+#include "imagedlgbase.h"
+
+class TQPushButton;
+
+namespace Digikam
+{
+class ThumbBarView;
+}
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+class DirSelectWidget;
+class SuperImposeWidget;
+
+class ImageEffect_SuperImpose : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_SuperImpose(TQWidget* parent);
+ ~ImageEffect_SuperImpose();
+
+private slots:
+
+ void slotTemplateDirChanged(const KURL& url);
+ void slotRootTemplateDirChanged(void);
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+ void populateTemplates(void);
+ void finalRendering();
+
+private:
+
+ KURL m_templatesUrl;
+ KURL m_templatesRootUrl;
+
+ Digikam::ThumbBarView *m_thumbnailsBar;
+
+ SuperImposeWidget *m_previewWidget;
+
+ DirSelectWidget *m_dirSelect;
+};
+
+} // NameSpace DigikamSuperImposeImagesPlugin
+
+#endif /* IMAGEEFFECT_SUPERIMPOSE_H */
diff --git a/src/imageplugins/superimpose/imageplugin_superimpose.cpp b/src/imageplugins/superimpose/imageplugin_superimpose.cpp
new file mode 100644
index 00000000..ceba44ef
--- /dev/null
+++ b/src/imageplugins/superimpose/imageplugin_superimpose.cpp
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "superimposetool.h"
+#include "imageplugin_superimpose.h"
+#include "imageplugin_superimpose.moc"
+
+using namespace DigikamSuperImposeImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_superimpose,
+ KGenericFactory<ImagePlugin_SuperImpose>("digikamimageplugin_superimpose"));
+
+ImagePlugin_SuperImpose::ImagePlugin_SuperImpose(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_SuperImpose")
+{
+ m_superimposeAction = new TDEAction(i18n("Template Superimpose..."), "superimpose", 0,
+ this, TQ_SLOT(slotSuperImpose()),
+ actionCollection(), "imageplugin_superimpose");
+
+ setXMLFile("digikamimageplugin_superimpose_ui.rc");
+
+ DDebug() << "ImagePlugin_SuperImpose plugin loaded" << endl;
+}
+
+ImagePlugin_SuperImpose::~ImagePlugin_SuperImpose()
+{
+}
+
+void ImagePlugin_SuperImpose::setEnabledActions(bool enable)
+{
+ m_superimposeAction->setEnabled(enable);
+}
+
+void ImagePlugin_SuperImpose::slotSuperImpose()
+{
+ SuperImposeTool *tool = new SuperImposeTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/superimpose/imageplugin_superimpose.h b/src/imageplugins/superimpose/imageplugin_superimpose.h
new file mode 100644
index 00000000..6f3c3a69
--- /dev/null
+++ b/src/imageplugins/superimpose/imageplugin_superimpose.h
@@ -0,0 +1,58 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_SUPERIMPOSE_H
+#define IMAGEPLUGIN_SUPERIMPOSE_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_SuperImpose : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_SuperImpose(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_SuperImpose();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotSuperImpose();
+
+private:
+
+ TDEAction *m_superimposeAction;
+};
+
+#endif /* IMAGEPLUGIN_SUPERIMPOSE_H */
diff --git a/src/imageplugins/superimpose/superimpose.cpp b/src/imageplugins/superimpose/superimpose.cpp
new file mode 100644
index 00000000..7c0ac74b
--- /dev/null
+++ b/src/imageplugins/superimpose/superimpose.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-18-03
+ * Description : Superimpose filter.
+ *
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// Local includes.
+
+#include "superimpose.h"
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+SuperImpose::SuperImpose(Digikam::DImg *orgImage, Digikam::DImg *templ,
+ TQRect orgImageSelection,
+ Digikam::DColorComposer::CompositingOperation compositeRule)
+{
+ m_orgImage = *orgImage;
+ m_template = *templ;
+ m_selection = orgImageSelection;
+ m_compositeRule = compositeRule;
+
+ filterImage();
+}
+
+void SuperImpose::filterImage(void)
+{
+ if (m_template.isNull())
+ return;
+
+ int templateWidth = m_template.width();
+ int templateHeight = m_template.height();
+
+ // take selection of src image and scale it to size of template
+ m_destImage = m_orgImage.smoothScaleSection(m_selection.x(), m_selection.y(),
+ m_selection.width(), m_selection.height(), templateWidth, templateHeight);
+
+ // convert depth if necessary
+ m_template.convertToDepthOfImage(&m_destImage);
+
+ // get composer for compositing rule
+ Digikam::DColorComposer *composer = Digikam::DColorComposer::getComposer(m_compositeRule);
+ Digikam::DColorComposer::MultiplicationFlags flags = Digikam::DColorComposer::NoMultiplication;
+ if (m_compositeRule != Digikam::DColorComposer::PorterDuffNone)
+ flags = Digikam::DColorComposer::MultiplicationFlagsDImg;
+
+ // do alpha blending of template on dest image
+ m_destImage.bitBlendImage(composer, &m_template, 0, 0, templateWidth, templateHeight, 0, 0, flags);
+
+ delete composer;
+}
+
+} // namespace DigikamSuperImposeImagesPlugin
diff --git a/src/imageplugins/superimpose/superimpose.h b/src/imageplugins/superimpose/superimpose.h
new file mode 100644
index 00000000..a0b7b6da
--- /dev/null
+++ b/src/imageplugins/superimpose/superimpose.h
@@ -0,0 +1,67 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2006-18-03
+ * Description : Superimpose filter.
+ *
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SUPERIMPOSE_H
+#define SUPERIMPOSE_H
+
+// TQt includes.
+
+#include <tqrect.h>
+
+// Digikam includes.
+
+#include "dimg.h"
+#include "dcolor.h"
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+class SuperImpose
+{
+
+public:
+
+ SuperImpose(Digikam::DImg *orgImage, Digikam::DImg *templ,
+ TQRect orgImageSelection,
+ Digikam::DColorComposer::CompositingOperation
+ compositeRule = Digikam::DColorComposer::PorterDuffNone);
+
+ Digikam::DImg getTargetImage() { return m_destImage; }
+
+private:
+
+ void filterImage(void);
+
+private:
+
+ TQRect m_selection;
+
+ Digikam::DImg m_orgImage;
+ Digikam::DImg m_template;
+ Digikam::DImg m_destImage;
+ Digikam::DColorComposer::CompositingOperation m_compositeRule;
+};
+
+} // namespace DigikamSuperImposeImagesPlugin
+
+#endif /* SUPERIMPOSE_H */
diff --git a/src/imageplugins/superimpose/superimposetool.cpp b/src/imageplugins/superimpose/superimposetool.cpp
new file mode 100644
index 00000000..f035559c
--- /dev/null
+++ b/src/imageplugins/superimpose/superimposetool.cpp
@@ -0,0 +1,271 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqvgroupbox.h>
+#include <tqgroupbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqpixmap.h>
+#include <tqwhatsthis.h>
+#include <tqtooltip.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqdir.h>
+#include <tqfile.h>
+#include <tqhbuttongroup.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+#include <knuminput.h>
+#include <kiconloader.h>
+#include <tdefiledialog.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <tdeglobalsettings.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "editortoolsettings.h"
+#include "thumbbar.h"
+#include "superimposewidget.h"
+#include "dirselectwidget.h"
+#include "superimposetool.h"
+#include "superimposetool.moc"
+
+using namespace Digikam;
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+SuperImposeTool::SuperImposeTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("superimpose");
+ setToolName(i18n("Template Superimpose"));
+ setToolIcon(SmallIcon("superimpose"));
+
+ // -------------------------------------------------------------
+
+ TQFrame *frame = new TQFrame(0);
+ frame->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
+
+ TQGridLayout* gridFrame = new TQGridLayout(frame, 1, 2);
+ m_previewWidget = new SuperImposeWidget(400, 300, frame);
+ TQWhatsThis::add( m_previewWidget, i18n("<p>This is the preview of the template "
+ "superimposed onto the image.") );
+
+ // -------------------------------------------------------------
+
+ TQHButtonGroup *bGroup = new TQHButtonGroup(frame);
+ TDEIconLoader icon;
+ bGroup->addSpace(0);
+ TQPushButton *zoomInButton = new TQPushButton( bGroup );
+ bGroup->insert(zoomInButton, ZOOMIN);
+ zoomInButton->setPixmap( icon.loadIcon( "zoom-in", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ zoomInButton->setToggleButton(true);
+ TQToolTip::add( zoomInButton, i18n( "Zoom in" ) );
+ bGroup->addSpace(20);
+ TQPushButton *zoomOutButton = new TQPushButton( bGroup );
+ bGroup->insert(zoomOutButton, ZOOMOUT);
+ zoomOutButton->setPixmap( icon.loadIcon( "zoom-out", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ zoomOutButton->setToggleButton(true);
+ TQToolTip::add( zoomOutButton, i18n( "Zoom out" ) );
+ bGroup->addSpace(20);
+ TQPushButton *moveButton = new TQPushButton( bGroup );
+ bGroup->insert(moveButton, MOVE);
+ moveButton->setPixmap( icon.loadIcon( "move", (TDEIcon::Group)TDEIcon::Toolbar ) );
+ moveButton->setToggleButton(true);
+ moveButton->setOn(true);
+ TQToolTip::add( moveButton, i18n( "Move" ) );
+ bGroup->addSpace(20);
+ bGroup->setExclusive(true);
+ bGroup->setFrameShape(TQFrame::NoFrame);
+
+ gridFrame->addMultiCellWidget(m_previewWidget, 0, 0, 0, 2);
+ gridFrame->addMultiCellWidget(bGroup, 1, 1, 1, 1);
+ gridFrame->setRowStretch(0, 10);
+ gridFrame->setColStretch(0, 10);
+ gridFrame->setColStretch(2, 10);
+ gridFrame->setMargin(0);
+ gridFrame->setSpacing(0);
+
+ setToolView(frame);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+ TQGridLayout* grid = new TQGridLayout(m_gboxSettings->plainPage(), 1, 1);
+
+ m_thumbnailsBar = new ThumbBarView(m_gboxSettings->plainPage());
+ m_dirSelect = new DirSelectWidget(m_gboxSettings->plainPage());
+ TQPushButton *templateDirButton = new TQPushButton( i18n("Root Directory..."), m_gboxSettings->plainPage() );
+ TQWhatsThis::add( templateDirButton, i18n("<p>Set here the current templates' root directory.") );
+
+ grid->addMultiCellWidget(m_thumbnailsBar, 0, 1, 0, 0);
+ grid->addMultiCellWidget(m_dirSelect, 0, 0, 1, 1);
+ grid->addMultiCellWidget(templateDirButton, 1, 1, 1, 1);
+ grid->setMargin(0);
+ grid->setSpacing(m_gboxSettings->spacingHint());
+ grid->setColStretch(1, 10);
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(bGroup, TQ_SIGNAL(released(int)),
+ m_previewWidget, TQ_SLOT(slotEditModeChanged(int)));
+
+ connect(m_thumbnailsBar, TQ_SIGNAL(signalURLSelected(const KURL&)),
+ m_previewWidget, TQ_SLOT(slotSetCurrentTemplate(const KURL&)));
+
+ connect(m_dirSelect, TQ_SIGNAL(folderItemSelected(const KURL &)),
+ this, TQ_SLOT(slotTemplateDirChanged(const KURL &)));
+
+ connect(templateDirButton, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotRootTemplateDirChanged()));
+
+ // -------------------------------------------------------------
+
+ populateTemplates();
+}
+
+SuperImposeTool::~SuperImposeTool()
+{
+}
+
+void SuperImposeTool::populateTemplates()
+{
+ m_thumbnailsBar->clear(true);
+
+ if (!m_templatesUrl.isValid() || !m_templatesUrl.isLocalFile())
+ return;
+
+ TQDir dir(m_templatesUrl.path(), "*.png *.PNG");
+
+ if (!dir.exists())
+ return;
+
+ dir.setFilter ( TQDir::Files | TQDir::NoSymLinks );
+
+ const TQFileInfoList* fileinfolist = dir.entryInfoList();
+ if (!fileinfolist)
+ return;
+
+ TQFileInfoListIterator it(*fileinfolist);
+ TQFileInfo* fi;
+
+ while( (fi = it.current() ) )
+ {
+ new ThumbBarItem( m_thumbnailsBar, KURL(fi->filePath()) );
+ ++it;
+ }
+}
+
+void SuperImposeTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("Album Settings");
+ KURL albumDBUrl( config->readPathEntry("Album Path", TDEGlobalSettings::documentPath()) );
+ config->setGroup("superimpose Tool");
+ config->setGroup("Template Superimpose Tool Settings");
+ m_templatesRootUrl.setPath( config->readEntry("Templates Root URL", albumDBUrl.path()) );
+ m_templatesUrl.setPath( config->readEntry("Templates URL", albumDBUrl.path()) );
+ m_dirSelect->setRootPath(m_templatesRootUrl, m_templatesUrl);
+}
+
+void SuperImposeTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("superimpose Tool");
+ config->writeEntry( "Templates Root URL", m_dirSelect->rootPath().path() );
+ config->writeEntry( "Templates URL", m_templatesUrl.path() );
+ config->sync();
+}
+
+void SuperImposeTool::slotResetSettings()
+{
+ m_previewWidget->resetEdit();
+}
+
+void SuperImposeTool::slotRootTemplateDirChanged()
+{
+ KURL url = KFileDialog::getExistingDirectory(m_templatesRootUrl.path(), kapp->activeWindow(),
+ i18n("Select Template Root Directory to Use"));
+
+ if( url.isValid() )
+ {
+ m_dirSelect->setRootPath(url);
+ m_templatesRootUrl = url;
+ m_templatesUrl = url;
+ populateTemplates();
+ }
+}
+
+void SuperImposeTool::slotTemplateDirChanged(const KURL& url)
+{
+ if( url.isValid() )
+ {
+ m_templatesUrl = url;
+ populateTemplates();
+ }
+}
+
+void SuperImposeTool::finalRendering()
+{
+ kapp->setOverrideCursor(KCursor::waitCursor());
+ m_previewWidget->setEnabled(false);
+ m_dirSelect->setEnabled(false);
+ m_thumbnailsBar->setEnabled(false);
+
+ ImageIface iface(0, 0);
+ DImg img = m_previewWidget->makeSuperImpose();
+ iface.putOriginalImage(i18n("Super Impose"), img.bits(),
+ img.width(), img.height() );
+
+ m_previewWidget->setEnabled(true);
+ m_dirSelect->setEnabled(true);
+ m_thumbnailsBar->setEnabled(true);
+ kapp->restoreOverrideCursor();
+}
+
+} // NameSpace DigikamSuperImposeImagesPlugin
diff --git a/src/imageplugins/superimpose/superimposetool.h b/src/imageplugins/superimpose/superimposetool.h
new file mode 100644
index 00000000..7501f23f
--- /dev/null
+++ b/src/imageplugins/superimpose/superimposetool.h
@@ -0,0 +1,90 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_SUPERIMPOSE_H
+#define IMAGEEFFECT_SUPERIMPOSE_H
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQPushButton;
+
+namespace Digikam
+{
+class ThumbBarView;
+class EditorToolSettings;
+}
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+class DirSelectWidget;
+class SuperImposeWidget;
+
+class SuperImposeTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ SuperImposeTool(TQObject* parent);
+ ~SuperImposeTool();
+
+private slots:
+
+ void slotTemplateDirChanged(const KURL& url);
+ void slotRootTemplateDirChanged();
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void populateTemplates();
+ void finalRendering();
+
+private:
+
+ KURL m_templatesUrl;
+ KURL m_templatesRootUrl;
+
+ Digikam::ThumbBarView *m_thumbnailsBar;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+
+ SuperImposeWidget *m_previewWidget;
+
+ DirSelectWidget *m_dirSelect;
+};
+
+} // NameSpace DigikamSuperImposeImagesPlugin
+
+#endif /* IMAGEEFFECT_SUPERIMPOSE_H */
diff --git a/src/imageplugins/superimpose/superimposewidget.cpp b/src/imageplugins/superimpose/superimposewidget.cpp
new file mode 100644
index 00000000..edae15aa
--- /dev/null
+++ b/src/imageplugins/superimpose/superimposewidget.cpp
@@ -0,0 +1,329 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cstdio>
+
+// TQt includes.
+
+#include <tqpainter.h>
+
+// KDE includes.
+
+#include <kstandarddirs.h>
+#include <kcursor.h>
+#include <tdeglobal.h>
+
+// Local includes.
+
+#include "superimpose.h"
+#include "superimposewidget.h"
+#include "superimposewidget.moc"
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+SuperImposeWidget::SuperImposeWidget(int w, int h, TQWidget *parent)
+ : TQWidget(parent, 0, TQt::WDestructiveClose)
+{
+ m_pixmap = new TQPixmap(w, h);
+ m_editMode = MOVE;
+
+ Digikam::ImageIface iface(0, 0);
+ m_w = iface.originalWidth();
+ m_h = iface.originalHeight();
+
+ setBackgroundMode(TQt::NoBackground);
+ setMinimumSize(w, h);
+ setMouseTracking(true);
+
+ resetEdit();
+}
+
+SuperImposeWidget::~SuperImposeWidget()
+{
+ if(m_pixmap)
+ delete m_pixmap;
+}
+
+Digikam::DImg SuperImposeWidget::makeSuperImpose(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ SuperImpose superimpose(iface.getOriginalImg(), &m_template, m_currentSelection);
+ return superimpose.getTargetImage();
+}
+
+void SuperImposeWidget::resetEdit(void)
+{
+ m_zoomFactor = 1.0;
+ m_currentSelection = TQRect(m_w/2 - m_rect.width()/2, m_h/2 - m_rect.height()/2,
+ m_rect.width(), m_rect.height());
+ makePixmap();
+ repaint(false);
+}
+
+void SuperImposeWidget::makePixmap(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ SuperImpose superimpose(iface.getOriginalImg(), &m_templateScaled, m_currentSelection);
+ Digikam::DImg image = superimpose.getTargetImage();
+
+ m_pixmap->fill(colorGroup().background());
+ TQPainter p(m_pixmap);
+ TQPixmap imagePix = image.convertToPixmap();
+ p.drawPixmap(m_rect.x(), m_rect.y(), imagePix, 0, 0, m_rect.width(), m_rect.height());
+ p.end();
+}
+
+void SuperImposeWidget::resizeEvent(TQResizeEvent * e)
+{
+ blockSignals(true);
+ delete m_pixmap;
+ int w = e->size().width();
+ int h = e->size().height();
+ m_pixmap = new TQPixmap(w, h);
+
+ if (!m_template.isNull())
+ {
+ int templateWidth = m_template.width();
+ int templateHeight = m_template.height();
+
+ if (templateWidth < templateHeight)
+ {
+ int neww = (int) ((float)height() / (float)templateHeight * (float)templateWidth);
+ m_rect = TQRect(width()/2-neww/2, 0, neww, height());
+ }
+ else
+ {
+ int newh = (int) ((float)width() / (float)templateWidth * (float)templateHeight);
+ m_rect = TQRect(0, height()/2-newh/2, width(), newh);
+ }
+
+ m_templateScaled = m_template.smoothScale(m_rect.width(), m_rect.height());
+ makePixmap();
+ }
+ else
+ {
+ m_rect = TQRect();
+ m_pixmap->fill(colorGroup().background());
+ }
+
+ blockSignals(false);
+}
+
+void SuperImposeWidget::paintEvent( TQPaintEvent * )
+{
+ bitBlt(this, 0, 0, m_pixmap);
+}
+
+void SuperImposeWidget::slotEditModeChanged(int mode)
+{
+ m_editMode = mode;
+}
+
+void SuperImposeWidget::slotSetCurrentTemplate(const KURL& url)
+{
+ m_template.load(url.path());
+
+ if (m_template.isNull())
+ {
+ m_rect = TQRect();
+ return;
+ }
+
+ int templateWidth = m_template.width();
+ int templateHeight = m_template.height();
+
+ if (templateWidth < templateHeight)
+ {
+ int neww = (int) ((float)height() / (float)templateHeight * (float)templateWidth);
+ m_rect = TQRect(width()/2-neww/2, 0, neww, height());
+ }
+ else
+ {
+ int newh = (int) ((float)width() / (float)templateWidth * (float)templateHeight);
+ m_rect = TQRect(0, height()/2-newh/2, width(), newh);
+ }
+
+ m_templateScaled = m_template.smoothScale(m_rect.width(), m_rect.height());
+
+ m_currentSelection = TQRect(m_w/2 - m_rect.width()/2, m_h/2 - m_rect.height()/2, m_rect.width(), m_rect.height());
+ zoomSelection(0);
+}
+
+void SuperImposeWidget::moveSelection(int dx, int dy)
+{
+ TQRect selection = m_currentSelection;
+ float wf = (float)selection.width() / (float)m_rect.width();
+ float hf = (float)selection.height() / (float)m_rect.height();
+
+ selection.moveBy( -(int)(wf*(float)dx), -(int)(hf*(float)dy) );
+
+ if (selection.left() < 0)
+ selection.moveLeft(0);
+ if (selection.top() < 0)
+ selection.moveTop(0);
+ if (selection.bottom() > m_h)
+ selection.moveBottom(m_h);
+ if (selection.right() > m_w)
+ selection.moveRight(m_w);
+
+ m_currentSelection = selection;
+}
+
+bool SuperImposeWidget::zoomSelection(float deltaZoomFactor)
+{
+ float newZoom = m_zoomFactor + deltaZoomFactor;
+
+ if (newZoom < 0.0)
+ return false;
+
+ TQRect selection = m_currentSelection;
+ int wf = (int)((float)m_rect.width() / newZoom);
+ int hf = (int)((float)m_rect.height() / newZoom);
+ int deltaX = (m_currentSelection.width() - wf) / 2;
+ int deltaY = (m_currentSelection.height() - hf) / 2;
+
+ selection.setLeft(m_currentSelection.left() + deltaX);
+ selection.setTop(m_currentSelection.top() + deltaY);
+ selection.setWidth(wf);
+ selection.setHeight(hf);
+
+ // check that selection is still inside original image
+ TQRect orgImageRect(0, 0, m_w, m_h);
+ if (!orgImageRect.contains(selection))
+ {
+ // try to adjust
+ if (selection.left() < 0)
+ selection.moveLeft(0);
+ if (selection.top() < 0)
+ selection.moveTop(0);
+ if (selection.bottom() > m_h)
+ selection.moveBottom(m_h);
+ if (selection.right() > m_w)
+ selection.moveRight(m_w);
+
+ // was it successful?
+ if (selection.contains(orgImageRect))
+ return false;
+
+ }
+
+ m_zoomFactor = newZoom;
+ m_currentSelection = selection;
+
+ makePixmap();
+ repaint(false);
+
+ return true;
+}
+
+void SuperImposeWidget::mousePressEvent ( TQMouseEvent * e )
+{
+ if ( isEnabled() && e->button() == TQt::LeftButton &&
+ rect().contains( e->x(), e->y() ) )
+ {
+ switch (m_editMode)
+ {
+ case ZOOMIN:
+ if (zoomSelection(+0.05))
+ moveSelection(width()/2 - e->x(), height()/2 - e->y());
+ break;
+
+ case ZOOMOUT:
+ if (zoomSelection(-0.05))
+ moveSelection(width()/2 - e->x(), height()/2 - e->y());
+ break;
+
+ case MOVE:
+ m_xpos = e->x();
+ m_ypos = e->y();
+ }
+ }
+}
+
+void SuperImposeWidget::mouseReleaseEvent ( TQMouseEvent * )
+{
+ setEditModeCursor();
+}
+
+void SuperImposeWidget::mouseMoveEvent ( TQMouseEvent * e )
+{
+ if ( isEnabled() )
+ {
+ if ( e->state() == TQt::LeftButton )
+ {
+ switch (m_editMode)
+ {
+ case ZOOMIN:
+ case ZOOMOUT:
+ break;
+
+ case MOVE:
+ int newxpos = e->x();
+ int newypos = e->y();
+
+ if (newxpos < m_rect.left())
+ newxpos = m_rect.left();
+ if (newxpos > m_rect.right())
+ newxpos = m_rect.right();
+ if (newxpos < m_rect.top())
+ newxpos = m_rect.top();
+ if (newxpos > m_rect.bottom())
+ newxpos = m_rect.bottom();
+
+ moveSelection(newxpos - m_xpos, newypos - m_ypos);
+ makePixmap();
+ repaint(false);
+
+ m_xpos = newxpos;
+ m_ypos = newypos;
+ setCursor( KCursor::handCursor() );
+ break;
+ }
+ }
+ else if (rect().contains( e->x(), e->y() ))
+ {
+ setEditModeCursor();
+ }
+ }
+}
+
+void SuperImposeWidget::setEditModeCursor()
+{
+ switch (m_editMode)
+ {
+ case ZOOMIN:
+ case ZOOMOUT:
+ setCursor ( KCursor::crossCursor() );
+ break;
+
+ case MOVE:
+ setCursor ( KCursor::sizeAllCursor() );
+ }
+}
+
+} // NameSpace DigikamSuperImposeImagesPlugin
diff --git a/src/imageplugins/superimpose/superimposewidget.h b/src/imageplugins/superimpose/superimposewidget.h
new file mode 100644
index 00000000..8b3fb048
--- /dev/null
+++ b/src/imageplugins/superimpose/superimposewidget.h
@@ -0,0 +1,118 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-01-04
+ * Description : a Digikam image editor plugin for superimpose a
+ * template to an image.
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef SUPERIMPOSEWIDGET_H
+#define SUPERIMPOSEWIDGET_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqimage.h>
+#include <tqrect.h>
+#include <tqsize.h>
+#include <tqpixmap.h>
+
+// KDE includes.
+
+#include <kurl.h>
+
+// Digikam includes.
+
+#include "imageiface.h"
+#include "dimg.h"
+
+class TQPixmap;
+
+namespace Digikam
+{
+class ImageIface;
+}
+
+namespace DigikamSuperImposeImagesPlugin
+{
+
+enum Action
+{
+ ZOOMIN=0,
+ ZOOMOUT,
+ MOVE
+};
+
+class SuperImposeWidget : public TQWidget
+{
+TQ_OBJECT
+
+
+public:
+
+ SuperImposeWidget(int w, int h, TQWidget *parent=0);
+ ~SuperImposeWidget();
+
+ void setEditMode(int mode);
+ void resetEdit(void);
+ TQRect getCurrentSelection(void);
+ TQSize getTemplateSize(void);
+ Digikam::DImg makeSuperImpose(void);
+
+public slots:
+
+ void slotEditModeChanged(int mode);
+ void slotSetCurrentTemplate(const KURL& url);
+
+protected:
+
+ void paintEvent( TQPaintEvent *e );
+ void resizeEvent( TQResizeEvent * e );
+ void mousePressEvent ( TQMouseEvent * e );
+ void mouseReleaseEvent ( TQMouseEvent * e );
+ void mouseMoveEvent ( TQMouseEvent * e );
+
+ bool zoomSelection(float deltaZoomFactor);
+ void moveSelection(int x, int y);
+ void makePixmap(void);
+ void setEditModeCursor();
+
+private:
+
+ int m_w;
+ int m_h;
+
+ int m_xpos;
+ int m_ypos;
+ int m_editMode;
+ float m_zoomFactor;
+
+ TQPixmap *m_pixmap; // For image region selection manipulations.
+
+ TQRect m_rect; // For mouse drag position.
+ TQRect m_currentSelection; // Region selection in image displayed in the widget.
+
+ Digikam::DImg m_template; // Full template data.
+ Digikam::DImg m_templateScaled; // Template scaled to preview widget
+};
+
+} // NameSpace DigikamSuperImposeImagesPlugin
+
+#endif /* SUPERIMPOSEWIDGET_H */
diff --git a/src/imageplugins/texture/Makefile.am b/src/imageplugins/texture/Makefile.am
new file mode 100644
index 00000000..22697c65
--- /dev/null
+++ b/src/imageplugins/texture/Makefile.am
@@ -0,0 +1,35 @@
+METASOURCES = AUTO
+SUBDIRS = patterns
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_texture_la_SOURCES = imageplugin_texture.cpp \
+ texturetool.cpp texture.cpp
+
+digikamimageplugin_texture_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_texture_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_texture.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_texture.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_texture_ui.rc
+
diff --git a/src/imageplugins/texture/digikamimageplugin_texture.desktop b/src/imageplugins/texture/digikamimageplugin_texture.desktop
new file mode 100644
index 00000000..4caf7e41
--- /dev/null
+++ b/src/imageplugins/texture/digikamimageplugin_texture.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=ImagePlugin_Texture
+Name[bg]=Приставка за снимки - Текстури
+Name[el]=ΠρόσθετοΕικόνας_Υφή
+Name[fi]=Taustapinta
+Name[hr]=Tekstura
+Name[it]=PluginImmagini_Trama
+Name[ms]=ImagePlugin_Tekstur
+Name[nl]=Afbeeldingsplugin_Textuur
+Name[sr]=Текстуре
+Name[sr@Latn]=Teksture
+Name[sv]=Insticksprogram för struktur
+Name[tr]=ResimEklentisi_Doku
+Name[xx]=xxImagePlugin_Texturexx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=digiKam plugin to apply texture on image
+Comment[bg]=Приставка на digiKam за добавяне на текстури към снимки
+Comment[ca]=Connector pel digiKam per aplicar una textura a una imatge
+Comment[da]=digiKam-plugin til at anvende tekstur på billedet
+Comment[de]=digiKam-Modul für das Anwenden von Texturen auf ein Bild
+Comment[el]=Πρόσθετο εφαρμογής υφής σε εικόνα για το digiKam
+Comment[es]=Plugin para digiKam para aplicar una textura sobre una imagen
+Comment[et]=DigiKami pildile tekstuuri lisamise plugin
+Comment[fa]=وصلۀ digiKam جهت اعمال بافت در تصویر
+Comment[fi]=Lisää kuvaan taustapinnan
+Comment[fr]=Module externe pour appliquer une texture sur une image dans digiKam
+Comment[gl]=Un plugin de digiKam para aplicar unha textura nunha imaxe
+Comment[hr]=digiKam dodatak za primjenu teksture u slici
+Comment[is]=Íforrit fyrir digiKam sem setur áferð á mynd
+Comment[it]=Plugin di digiKam per applicare una trama su un'immagine
+Comment[ja]=digiKam テクスチャ適用プラグイン
+Comment[nds]=digiKam-Moduul för't Överdregen vun Texturen
+Comment[nl]=Digikam-plugin voor het aanbrengen van textuur op een afbeelding
+Comment[pa]=ਚਿੱਤਰ ਉੱਤੇ ਪਾਠ ਲਿਖਣ ਲਈ ਡਿਜ਼ੀਕੈਮ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam pozwalająca na nakładanie tekstury na obraz
+Comment[pt]=Um 'plugin' do digiKam para aplicar uma textura numa imagem
+Comment[pt_BR]=Um 'plugin' do digiKam para aplicar uma textura numa imagem
+Comment[ru]=Модуль digiKam для наложения текстур на изображение
+Comment[sk]=digiKam plugin pre aplikovanie textúry na obrázok
+Comment[sr]=digiKam-ов прикључак за додавање текстура у слику
+Comment[sr@Latn]=digiKam-ov priključak za dodavanje tekstura u sliku
+Comment[sv]=Digikam insticksprogram för att lägga till struktur på en bild
+Comment[tr]=Bir resme doku eklemek için digiKam eklentisi
+Comment[uk]=Втулок застосування текстури для digiKam
+Comment[vi]=Phần bổ sung áp dụng hoạ tiết trên ảnh cho digiKam
+Comment[xx]=xxdigiKam plugin to apply texture on imagexx
+
+X-TDE-Library=digikamimageplugin_texture
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/texture/digikamimageplugin_texture_ui.rc b/src/imageplugins/texture/digikamimageplugin_texture_ui.rc
new file mode 100644
index 00000000..122833cc
--- /dev/null
+++ b/src/imageplugins/texture/digikamimageplugin_texture_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="4" name="digikamimageplugin_texture" >
+
+ <MenuBar>
+
+ <Menu name="Decorate" ><text>&amp;Decorate</text>
+ <Action name="imageplugin_texture" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action shortcut="" name="imageplugin_texture" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/texture/imageeffect_texture.cpp b/src/imageplugins/texture/imageeffect_texture.cpp
new file mode 100644
index 00000000..5f5d7e9f
--- /dev/null
+++ b/src/imageplugins/texture/imageeffect_texture.cpp
@@ -0,0 +1,291 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-10
+ * Description : a plugin to apply texture over an image
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqlabel.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqcombobox.h>
+#include <tqimage.h>
+
+// KDE includes.
+
+#include <tdeconfig.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <kstandarddirs.h>
+#include <knuminput.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "texture.h"
+#include "imageeffect_texture.h"
+#include "imageeffect_texture.moc"
+
+namespace DigikamTextureImagesPlugin
+{
+
+ImageEffect_Texture::ImageEffect_Texture(TQWidget* parent)
+ : Digikam::CtrlPanelDlg(parent, i18n("Apply Texture"),
+ "texture", false, false, true,
+ Digikam::ImagePannelWidget::SeparateViewAll)
+{
+ TQString whatsThis;
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("Apply Texture"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to apply a decorative "
+ "texture to an image."),
+ TDEAboutData::License_GPL,
+ "(c) 2005, Gilles Caulier\n"
+ "(c) 2006-2008, Gilles Caulier and Marcel Wiesweg",
+ 0,
+ "http://www.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Marcel Wiesweg", I18N_NOOP("Developer"),
+ "marcel dot wiesweg at gmx dot de");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(m_imagePreviewWidget);
+ TQGridLayout* gridSettings = new TQGridLayout( gboxSettings, 2, 1, 0, spacingHint());
+ TQLabel *label1 = new TQLabel(i18n("Type:"), gboxSettings);
+
+ m_textureType = new TQComboBox( false, gboxSettings );
+ m_textureType->insertItem( i18n("Paper") );
+ m_textureType->insertItem( i18n("Paper 2") );
+ m_textureType->insertItem( i18n("Fabric") );
+ m_textureType->insertItem( i18n("Burlap") );
+ m_textureType->insertItem( i18n("Bricks") );
+ m_textureType->insertItem( i18n("Bricks 2") );
+ m_textureType->insertItem( i18n("Canvas") );
+ m_textureType->insertItem( i18n("Marble") );
+ m_textureType->insertItem( i18n("Marble 2") );
+ m_textureType->insertItem( i18n("Blue Jean") );
+ m_textureType->insertItem( i18n("Cell Wood") );
+ m_textureType->insertItem( i18n("Metal Wire") );
+ m_textureType->insertItem( i18n("Modern") );
+ m_textureType->insertItem( i18n("Wall") );
+ m_textureType->insertItem( i18n("Moss") );
+ m_textureType->insertItem( i18n("Stone") );
+ TQWhatsThis::add( m_textureType, i18n("<p>Set here the texture type to apply to the image."));
+
+ gridSettings->addMultiCellWidget(label1, 0, 0, 0, 0);
+ gridSettings->addMultiCellWidget(m_textureType, 0, 0, 1, 1);
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Relief:"), gboxSettings);
+
+ m_blendGain = new KIntNumInput(gboxSettings);
+ m_blendGain->setRange(1, 255, 1, true);
+ m_blendGain->setValue(200);
+ TQWhatsThis::add( m_blendGain, i18n("<p>Set here the relief gain used to merge texture and image."));
+
+ gridSettings->addMultiCellWidget(label2, 1, 1, 0, 1);
+ gridSettings->addMultiCellWidget(m_blendGain, 2, 2, 0, 1);
+
+ m_imagePreviewWidget->setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_textureType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_blendGain, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+ImageEffect_Texture::~ImageEffect_Texture()
+{
+}
+
+void ImageEffect_Texture::renderingFinished()
+{
+ m_textureType->setEnabled(true);
+ m_blendGain->setEnabled(true);
+}
+
+void ImageEffect_Texture::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("texture Tool Dialog");
+ m_textureType->blockSignals(true);
+ m_blendGain->blockSignals(true);
+ m_textureType->setCurrentItem(config->readNumEntry("TextureType", PaperTexture));
+ m_blendGain->setValue(config->readNumEntry("BlendGain", 200));
+ m_textureType->blockSignals(false);
+ m_blendGain->blockSignals(false);
+}
+
+void ImageEffect_Texture::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("texture Tool Dialog");
+ config->writeEntry("TextureType", m_textureType->currentItem());
+ config->writeEntry("BlendGain", m_blendGain->value());
+ config->sync();
+}
+
+void ImageEffect_Texture::resetValues()
+{
+ m_textureType->blockSignals(true);
+ m_blendGain->blockSignals(true);
+ m_textureType->setCurrentItem(PaperTexture);
+ m_blendGain->setValue(200);
+ m_textureType->blockSignals(false);
+ m_blendGain->blockSignals(false);
+}
+
+void ImageEffect_Texture::prepareEffect()
+{
+ m_textureType->setEnabled(false);
+ m_blendGain->setEnabled(false);
+
+ Digikam::DImg image = m_imagePreviewWidget->getOriginalRegionImage();
+ TQString texture = getTexturePath( m_textureType->currentItem() );
+
+ int b = 255 - m_blendGain->value();
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Texture(&image, this, b, texture));
+}
+
+void ImageEffect_Texture::prepareFinal()
+{
+ m_textureType->setEnabled(false);
+ m_blendGain->setEnabled(false);
+
+ int b = 255 - m_blendGain->value();
+
+ Digikam::ImageIface iface(0, 0);
+ TQString texture = getTexturePath( m_textureType->currentItem() );
+
+ m_threadedFilter = dynamic_cast<Digikam::DImgThreadedFilter *>(
+ new Texture(iface.getOriginalImg(), this, b, texture));
+}
+
+void ImageEffect_Texture::putPreviewData(void)
+{
+ m_imagePreviewWidget->setPreviewImage(m_threadedFilter->getTargetImage());
+}
+
+void ImageEffect_Texture::putFinalData(void)
+{
+ Digikam::ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Texture"), m_threadedFilter->getTargetImage().bits());
+}
+
+TQString ImageEffect_Texture::getTexturePath(int texture)
+{
+ TQString pattern;
+
+ switch (texture)
+ {
+ case PaperTexture:
+ pattern = "paper-texture";
+ break;
+
+ case Paper2Texture:
+ pattern = "paper2-texture";
+ break;
+
+ case FabricTexture:
+ pattern = "fabric-texture";
+ break;
+
+ case BurlapTexture:
+ pattern = "burlap-texture";
+ break;
+
+ case BricksTexture:
+ pattern = "bricks-texture";
+ break;
+
+ case Bricks2Texture:
+ pattern = "bricks2-texture";
+ break;
+
+ case CanvasTexture:
+ pattern = "canvas-texture";
+ break;
+
+ case MarbleTexture:
+ pattern = "marble-texture";
+ break;
+
+ case Marble2Texture:
+ pattern = "marble2-texture";
+ break;
+
+ case BlueJeanTexture:
+ pattern = "bluejean-texture";
+ break;
+
+ case CellWoodTexture:
+ pattern = "cellwood-texture";
+ break;
+
+ case MetalWireTexture:
+ pattern = "metalwire-texture";
+ break;
+
+ case ModernTexture:
+ pattern = "modern-texture";
+ break;
+
+ case WallTexture:
+ pattern = "wall-texture";
+ break;
+
+ case MossTexture:
+ pattern = "moss-texture";
+ break;
+
+ case StoneTexture:
+ pattern = "stone-texture";
+ break;
+ }
+
+ TDEGlobal::dirs()->addResourceType(pattern.ascii(), TDEGlobal::dirs()->kde_default("data") +
+ "digikam/data");
+ return (TDEGlobal::dirs()->findResourceDir(pattern.ascii(), pattern + ".png") + pattern + ".png" );
+}
+
+} // NameSpace DigikamTextureImagesPlugin
+
diff --git a/src/imageplugins/texture/imageeffect_texture.h b/src/imageplugins/texture/imageeffect_texture.h
new file mode 100644
index 00000000..d37068b6
--- /dev/null
+++ b/src/imageplugins/texture/imageeffect_texture.h
@@ -0,0 +1,100 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-10
+ * Description : a plugin to apply texture over an image
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_TEXTURE_H
+#define IMAGEEFFECT_TEXTURE_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "ctrlpaneldlg.h"
+
+class TQComboBox;
+
+class KIntNumInput;
+
+namespace DigikamTextureImagesPlugin
+{
+
+class ImageEffect_Texture : public Digikam::CtrlPanelDlg
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_Texture(TQWidget* parent);
+ ~ImageEffect_Texture();
+
+private:
+
+ TQString getTexturePath(int texture);
+
+private slots:
+
+ void readUserSettings();
+
+private:
+
+ void writeUserSettings();
+ void resetValues();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ enum TextureTypes
+ {
+ PaperTexture=0,
+ Paper2Texture,
+ FabricTexture,
+ BurlapTexture,
+ BricksTexture,
+ Bricks2Texture,
+ CanvasTexture,
+ MarbleTexture,
+ Marble2Texture,
+ BlueJeanTexture,
+ CellWoodTexture,
+ MetalWireTexture,
+ ModernTexture,
+ WallTexture,
+ MossTexture,
+ StoneTexture
+ };
+
+ TQComboBox *m_textureType;
+
+ KIntNumInput *m_blendGain;
+};
+
+} // NameSpace DigikamTextureImagesPlugin
+
+#endif /* IMAGEEFFECT_TEXTURE_H */
diff --git a/src/imageplugins/texture/imageplugin_texture.cpp b/src/imageplugins/texture/imageplugin_texture.cpp
new file mode 100644
index 00000000..ec0e3ba8
--- /dev/null
+++ b/src/imageplugins/texture/imageplugin_texture.cpp
@@ -0,0 +1,70 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-10
+ * Description : a plugin to apply texture over an image
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+#include <tdeapplication.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "texturetool.h"
+#include "imageplugin_texture.h"
+#include "imageplugin_texture.moc"
+
+using namespace DigikamTextureImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_texture,
+ KGenericFactory<ImagePlugin_Texture>("digikamimageplugin_texture"));
+
+ImagePlugin_Texture::ImagePlugin_Texture(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_Texture")
+{
+ m_textureAction = new TDEAction(i18n("Apply Texture..."), "texture", 0,
+ this, TQ_SLOT(slotTexture()),
+ actionCollection(), "imageplugin_texture");
+
+ setXMLFile( "digikamimageplugin_texture_ui.rc" );
+
+ DDebug() << "ImagePlugin_Texture plugin loaded" << endl;
+}
+
+ImagePlugin_Texture::~ImagePlugin_Texture()
+{
+}
+
+void ImagePlugin_Texture::setEnabledActions(bool enable)
+{
+ m_textureAction->setEnabled(enable);
+}
+
+void ImagePlugin_Texture::slotTexture()
+{
+ TextureTool *tool = new TextureTool(this);
+ loadTool(tool);
+}
diff --git a/src/imageplugins/texture/imageplugin_texture.h b/src/imageplugins/texture/imageplugin_texture.h
new file mode 100644
index 00000000..bae2ba5e
--- /dev/null
+++ b/src/imageplugins/texture/imageplugin_texture.h
@@ -0,0 +1,56 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-10
+ * Description : a plugin to apply texture over an image
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_TEXTURE_H
+#define IMAGEPLUGIN_TEXTURE_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_Texture : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_Texture(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_Texture();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotTexture();
+
+private:
+
+ TDEAction *m_textureAction;
+};
+
+#endif /* IMAGEPLUGIN_TEXTURE_H */
diff --git a/src/imageplugins/texture/patterns/Makefile.am b/src/imageplugins/texture/patterns/Makefile.am
new file mode 100644
index 00000000..414c7f20
--- /dev/null
+++ b/src/imageplugins/texture/patterns/Makefile.am
@@ -0,0 +1,5 @@
+borderpicsdir = $(kde_datadir)/digikam/data
+borderpics_DATA = bricks2-texture.png bricks-texture.png burlap-texture.png canvas-texture.png \
+ marble2-texture.png marble-texture.png paper-texture.png stone-texture.png \
+ fabric-texture.png paper2-texture.png bluejean-texture.png cellwood-texture.png \
+ metalwire-texture.png modern-texture.png wall-texture.png moss-texture.png \ No newline at end of file
diff --git a/src/imageplugins/texture/patterns/bluejean-texture.png b/src/imageplugins/texture/patterns/bluejean-texture.png
new file mode 100644
index 00000000..3885d60b
--- /dev/null
+++ b/src/imageplugins/texture/patterns/bluejean-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/bricks-texture.png b/src/imageplugins/texture/patterns/bricks-texture.png
new file mode 100644
index 00000000..0ebfa881
--- /dev/null
+++ b/src/imageplugins/texture/patterns/bricks-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/bricks2-texture.png b/src/imageplugins/texture/patterns/bricks2-texture.png
new file mode 100644
index 00000000..985c5e84
--- /dev/null
+++ b/src/imageplugins/texture/patterns/bricks2-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/burlap-texture.png b/src/imageplugins/texture/patterns/burlap-texture.png
new file mode 100644
index 00000000..04494770
--- /dev/null
+++ b/src/imageplugins/texture/patterns/burlap-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/canvas-texture.png b/src/imageplugins/texture/patterns/canvas-texture.png
new file mode 100644
index 00000000..6aa3df8e
--- /dev/null
+++ b/src/imageplugins/texture/patterns/canvas-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/cellwood-texture.png b/src/imageplugins/texture/patterns/cellwood-texture.png
new file mode 100644
index 00000000..b94f618c
--- /dev/null
+++ b/src/imageplugins/texture/patterns/cellwood-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/fabric-texture.png b/src/imageplugins/texture/patterns/fabric-texture.png
new file mode 100644
index 00000000..ac88eb74
--- /dev/null
+++ b/src/imageplugins/texture/patterns/fabric-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/marble-texture.png b/src/imageplugins/texture/patterns/marble-texture.png
new file mode 100644
index 00000000..c22ab4ed
--- /dev/null
+++ b/src/imageplugins/texture/patterns/marble-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/marble2-texture.png b/src/imageplugins/texture/patterns/marble2-texture.png
new file mode 100644
index 00000000..45b77f05
--- /dev/null
+++ b/src/imageplugins/texture/patterns/marble2-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/metalwire-texture.png b/src/imageplugins/texture/patterns/metalwire-texture.png
new file mode 100644
index 00000000..cf0b402c
--- /dev/null
+++ b/src/imageplugins/texture/patterns/metalwire-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/modern-texture.png b/src/imageplugins/texture/patterns/modern-texture.png
new file mode 100644
index 00000000..45ed8b7a
--- /dev/null
+++ b/src/imageplugins/texture/patterns/modern-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/moss-texture.png b/src/imageplugins/texture/patterns/moss-texture.png
new file mode 100644
index 00000000..9403189f
--- /dev/null
+++ b/src/imageplugins/texture/patterns/moss-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/paper-texture.png b/src/imageplugins/texture/patterns/paper-texture.png
new file mode 100644
index 00000000..c9c90205
--- /dev/null
+++ b/src/imageplugins/texture/patterns/paper-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/paper2-texture.png b/src/imageplugins/texture/patterns/paper2-texture.png
new file mode 100644
index 00000000..36817ffd
--- /dev/null
+++ b/src/imageplugins/texture/patterns/paper2-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/stone-texture.png b/src/imageplugins/texture/patterns/stone-texture.png
new file mode 100644
index 00000000..6f26b474
--- /dev/null
+++ b/src/imageplugins/texture/patterns/stone-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/patterns/wall-texture.png b/src/imageplugins/texture/patterns/wall-texture.png
new file mode 100644
index 00000000..d7322500
--- /dev/null
+++ b/src/imageplugins/texture/patterns/wall-texture.png
Binary files differ
diff --git a/src/imageplugins/texture/texture.cpp b/src/imageplugins/texture/texture.cpp
new file mode 100644
index 00000000..42477d5d
--- /dev/null
+++ b/src/imageplugins/texture/texture.cpp
@@ -0,0 +1,181 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Texture threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// Local includes.
+
+#include "dimg.h"
+#include "ddebug.h"
+#include "texture.h"
+
+namespace DigikamTextureImagesPlugin
+{
+
+Texture::Texture(Digikam::DImg *orgImage, TQObject *parent, int blendGain, TQString texturePath)
+ : Digikam::DImgThreadedFilter(orgImage, parent, "Texture")
+{
+ m_blendGain = blendGain;
+ m_texturePath = texturePath;
+
+ initFilter();
+}
+
+// This method is based on the Simulate Texture Film tutorial from GimpGuru.org web site
+// available at this url : http://www.gimpguru.org/Tutorials/SimulatedTexture/
+
+//#define INT_MULT(a,b,t) ((t) = (a) * (b) + 0x80, ( ( (t >> 8) + t ) >> 8))
+
+inline static int intMult8(uint a, uint b)
+{
+ uint t = a * b + 0x80;
+ return ((t >> 8) + t) >> 8;
+}
+
+inline static int intMult16(uint a, uint b)
+{
+ uint t = a * b + 0x8000;
+ return ((t >> 16) + t) >> 16;
+}
+
+void Texture::filterImage(void)
+{
+ // Texture tile.
+
+ int w = m_orgImage.width();
+ int h = m_orgImage.height();
+ int bytesDepth = m_orgImage.bytesDepth();
+ bool sixteenBit = m_orgImage.sixteenBit();
+
+ DDebug() << "Texture File: " << m_texturePath << endl;
+ Digikam::DImg texture(m_texturePath);
+ if ( texture.isNull() ) return;
+
+ Digikam::DImg textureImg(w, h, m_orgImage.sixteenBit(), m_orgImage.hasAlpha());
+
+ texture.convertToDepthOfImage(&textureImg);
+
+ for (int x = 0 ; x < w ; x+=texture.width())
+ for (int y = 0 ; y < h ; y+=texture.height())
+ textureImg.bitBltImage(&texture, x, y);
+
+ // Apply texture.
+
+ uchar* data = m_orgImage.bits();
+ uchar* pTeData = textureImg.bits();
+ uchar* pOutBits = m_destImage.bits();
+ uint offset;
+
+ Digikam::DColor teData, transData, inData, outData;
+ uchar *ptr, *dptr, *tptr;
+ int progress;
+
+ int blendGain;
+ if (sixteenBit)
+ blendGain = (m_blendGain + 1) * 256 - 1;
+ else
+ blendGain = m_blendGain;
+
+ // Make textured transparent layout.
+
+ for (int x = 0; !m_cancel && x < w; x++)
+ {
+ for (int y = 0; !m_cancel && y < h; y++)
+ {
+ offset = x*bytesDepth + (y*w*bytesDepth);
+ ptr = data + offset;
+ tptr = pTeData + offset;
+
+ // Read color
+ teData.setColor(tptr, sixteenBit);
+
+ // in the old algorithm, this was
+ //teData.channel.red = (teData.channel.red * (255 - m_blendGain) +
+ // transData.channel.red * m_blendGain) >> 8;
+ // but transdata was uninitialized, its components were apparently 0,
+ // so I removed the part after the "+".
+
+ if (sixteenBit)
+ {
+ teData.blendInvAlpha16(blendGain);
+ }
+ else
+ {
+ teData.blendInvAlpha8(blendGain);
+ }
+
+ // Overwrite RGB.
+ teData.setPixel(tptr);
+ }
+
+ // Update progress bar in dialog.
+ progress = (int) (((double)x * 50.0) / w);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+
+ // Merge layout and image using overlay method.
+
+ for (int x = 0; !m_cancel && x < w; x++)
+ {
+ for (int y = 0; !m_cancel && y < h; y++)
+ {
+ offset = x*bytesDepth + (y*w*bytesDepth);
+ ptr = data + offset;
+ dptr = pOutBits + offset;
+ tptr = pTeData + offset;
+
+ inData.setColor (ptr, sixteenBit);
+ outData.setColor(dptr, sixteenBit);
+ teData.setColor (tptr, sixteenBit);
+
+ if (sixteenBit)
+ {
+ outData.setRed ( intMult16 (inData.red(), inData.red() + intMult16(2 * teData.red(), 65535 - inData.red()) ) );
+ outData.setGreen( intMult16 (inData.green(), inData.green() + intMult16(2 * teData.green(), 65535 - inData.green()) ) );
+ outData.setBlue ( intMult16 (inData.blue(), inData.blue() + intMult16(2 * teData.blue(), 65535 - inData.blue()) ) );
+ }
+ else
+ {
+ outData.setRed ( intMult8 (inData.red(), inData.red() + intMult8(2 * teData.red(), 255 - inData.red()) ) );
+ outData.setGreen( intMult8 (inData.green(), inData.green() + intMult8(2 * teData.green(), 255 - inData.green()) ) );
+ outData.setBlue ( intMult8 (inData.blue(), inData.blue() + intMult8(2 * teData.blue(), 255 - inData.blue()) ) );
+ }
+ outData.setAlpha( inData.alpha() );
+ outData.setPixel( dptr );
+ }
+
+ // Update progress bar in dialog.
+ progress = (int) (50.0 + ((double)x * 50.0) / w);
+
+ if (progress%5 == 0)
+ postProgress(progress);
+ }
+}
+
+} // NameSpace DigikamTextureImagesPlugin
diff --git a/src/imageplugins/texture/texture.h b/src/imageplugins/texture/texture.h
new file mode 100644
index 00000000..1bcda2ff
--- /dev/null
+++ b/src/imageplugins/texture/texture.h
@@ -0,0 +1,62 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-05-25
+ * Description : Texture threaded image filter.
+ *
+ * Copyright (C) 2005-2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2007 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef TEXTURE_H
+#define TEXTURE_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "dimgthreadedfilter.h"
+
+namespace DigikamTextureImagesPlugin
+{
+
+class Texture : public Digikam::DImgThreadedFilter
+{
+
+public:
+
+ Texture(Digikam::DImg *orgImage, TQObject *parent=0, int blendGain=200,
+ TQString texturePath=TQString());
+
+ ~Texture(){};
+
+private:
+
+ virtual void filterImage(void);
+
+private:
+
+ int m_blendGain;
+
+ TQString m_texturePath;
+};
+
+} // NameSpace DigikamTextureImagesPlugin
+
+#endif /* TEXTURE_H */
diff --git a/src/imageplugins/texture/texturetool.cpp b/src/imageplugins/texture/texturetool.cpp
new file mode 100644
index 00000000..71e29aea
--- /dev/null
+++ b/src/imageplugins/texture/texturetool.cpp
@@ -0,0 +1,294 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-10
+ * Description : a plugin to apply texture over an image
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Local includes.
+
+#include "daboutdata.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "imageiface.h"
+#include "imagepanelwidget.h"
+#include "editortoolsettings.h"
+#include "texture.h"
+#include "texturetool.h"
+#include "texturetool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamTextureImagesPlugin
+{
+
+TextureTool::TextureTool(TQObject* parent)
+ : EditorToolThreaded(parent)
+{
+ setName("texture");
+ setToolName(i18n("Texture"));
+ setToolIcon(SmallIcon("texture"));
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel|
+ EditorToolSettings::PanIcon);
+ TQGridLayout* grid = new TQGridLayout( m_gboxSettings->plainPage(), 3, 1);
+ TQLabel *label1 = new TQLabel(i18n("Type:"), m_gboxSettings->plainPage());
+
+ m_textureType = new RComboBox(m_gboxSettings->plainPage());
+ m_textureType->insertItem(i18n("Paper"));
+ m_textureType->insertItem(i18n("Paper 2"));
+ m_textureType->insertItem(i18n("Fabric"));
+ m_textureType->insertItem(i18n("Burlap"));
+ m_textureType->insertItem(i18n("Bricks"));
+ m_textureType->insertItem(i18n("Bricks 2"));
+ m_textureType->insertItem(i18n("Canvas"));
+ m_textureType->insertItem(i18n("Marble"));
+ m_textureType->insertItem(i18n("Marble 2"));
+ m_textureType->insertItem(i18n("Blue Jean"));
+ m_textureType->insertItem(i18n("Cell Wood"));
+ m_textureType->insertItem(i18n("Metal Wire"));
+ m_textureType->insertItem(i18n("Modern"));
+ m_textureType->insertItem(i18n("Wall"));
+ m_textureType->insertItem(i18n("Moss"));
+ m_textureType->insertItem(i18n("Stone"));
+ m_textureType->setDefaultItem(PaperTexture);
+ TQWhatsThis::add( m_textureType, i18n("<p>Set here the texture type to apply to the image."));
+
+ // -------------------------------------------------------------
+
+ TQLabel *label2 = new TQLabel(i18n("Relief:"), m_gboxSettings->plainPage());
+
+ m_blendGain = new RIntNumInput(m_gboxSettings->plainPage());
+ m_blendGain->setRange(1, 255, 1);
+ m_blendGain->setDefaultValue(200);
+ TQWhatsThis::add( m_blendGain, i18n("<p>Set here the relief gain used to merge texture and image."));
+
+ grid->addMultiCellWidget(label1, 0, 0, 0, 0);
+ grid->addMultiCellWidget(m_textureType, 0, 0, 1, 1);
+ grid->addMultiCellWidget(label2, 1, 1, 0, 1);
+ grid->addMultiCellWidget(m_blendGain, 2, 2, 0, 1);
+ grid->setRowStretch(3, 10);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImagePanelWidget(470, 350, "texture Tool", m_gboxSettings->panIconView());
+
+ setToolView(m_previewWidget);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_textureType, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotEffect()));
+
+ connect(m_blendGain, TQ_SIGNAL(valueChanged(int)),
+ this, TQ_SLOT(slotTimer()));
+}
+
+TextureTool::~TextureTool()
+{
+}
+
+void TextureTool::renderingFinished()
+{
+ m_textureType->setEnabled(true);
+ m_blendGain->setEnabled(true);
+}
+
+void TextureTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("texture Tool");
+
+ m_textureType->blockSignals(true);
+ m_blendGain->blockSignals(true);
+
+ m_textureType->setCurrentItem(config->readNumEntry("TextureType", m_textureType->defaultItem()));
+ m_blendGain->setValue(config->readNumEntry("BlendGain", m_blendGain->defaultValue()));
+
+ m_textureType->blockSignals(false);
+ m_blendGain->blockSignals(false);
+}
+
+void TextureTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("texture Tool");
+ config->writeEntry("TextureType", m_textureType->currentItem());
+ config->writeEntry("BlendGain", m_blendGain->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void TextureTool::slotResetSettings()
+{
+ m_textureType->blockSignals(true);
+ m_blendGain->blockSignals(true);
+
+ m_textureType->slotReset();
+ m_blendGain->slotReset();
+
+ m_textureType->blockSignals(false);
+ m_blendGain->blockSignals(false);
+}
+
+void TextureTool::prepareEffect()
+{
+ m_textureType->setEnabled(false);
+ m_blendGain->setEnabled(false);
+
+ DImg image = m_previewWidget->getOriginalRegionImage();
+ TQString texture = getTexturePath( m_textureType->currentItem() );
+
+ int b = 255 - m_blendGain->value();
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Texture(&image, this, b, texture)));
+}
+
+void TextureTool::prepareFinal()
+{
+ m_textureType->setEnabled(false);
+ m_blendGain->setEnabled(false);
+
+ int b = 255 - m_blendGain->value();
+
+ ImageIface iface(0, 0);
+ TQString texture = getTexturePath( m_textureType->currentItem() );
+
+ setFilter(dynamic_cast<DImgThreadedFilter*>(new Texture(iface.getOriginalImg(), this, b, texture)));
+}
+
+void TextureTool::putPreviewData()
+{
+ m_previewWidget->setPreviewImage(filter()->getTargetImage());
+}
+
+void TextureTool::putFinalData()
+{
+ ImageIface iface(0, 0);
+ iface.putOriginalImage(i18n("Texture"), filter()->getTargetImage().bits());
+}
+
+TQString TextureTool::getTexturePath(int texture)
+{
+ TQString pattern;
+
+ switch (texture)
+ {
+ case PaperTexture:
+ pattern = "paper-texture";
+ break;
+
+ case Paper2Texture:
+ pattern = "paper2-texture";
+ break;
+
+ case FabricTexture:
+ pattern = "fabric-texture";
+ break;
+
+ case BurlapTexture:
+ pattern = "burlap-texture";
+ break;
+
+ case BricksTexture:
+ pattern = "bricks-texture";
+ break;
+
+ case Bricks2Texture:
+ pattern = "bricks2-texture";
+ break;
+
+ case CanvasTexture:
+ pattern = "canvas-texture";
+ break;
+
+ case MarbleTexture:
+ pattern = "marble-texture";
+ break;
+
+ case Marble2Texture:
+ pattern = "marble2-texture";
+ break;
+
+ case BlueJeanTexture:
+ pattern = "bluejean-texture";
+ break;
+
+ case CellWoodTexture:
+ pattern = "cellwood-texture";
+ break;
+
+ case MetalWireTexture:
+ pattern = "metalwire-texture";
+ break;
+
+ case ModernTexture:
+ pattern = "modern-texture";
+ break;
+
+ case WallTexture:
+ pattern = "wall-texture";
+ break;
+
+ case MossTexture:
+ pattern = "moss-texture";
+ break;
+
+ case StoneTexture:
+ pattern = "stone-texture";
+ break;
+ }
+
+ TDEGlobal::dirs()->addResourceType(pattern.ascii(), TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ return (TDEGlobal::dirs()->findResourceDir(pattern.ascii(), pattern + ".png") + pattern + ".png" );
+}
+
+} // NameSpace DigikamTextureImagesPlugin
diff --git a/src/imageplugins/texture/texturetool.h b/src/imageplugins/texture/texturetool.h
new file mode 100644
index 00000000..1287bb3e
--- /dev/null
+++ b/src/imageplugins/texture/texturetool.h
@@ -0,0 +1,112 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-10
+ * Description : a plugin to apply texture over an image
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2006-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef TEXTURETOOL_H
+#define TEXTURETOOL_H
+
+// TQt includes.
+
+#include <tqstring.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+namespace KDcrawIface
+{
+class RIntNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class EditorToolSettings;
+class ImagePanelWidget;
+}
+
+namespace DigikamTextureImagesPlugin
+{
+
+class TextureTool : public Digikam::EditorToolThreaded
+{
+ TQ_OBJECT
+
+
+public:
+
+ TextureTool(TQObject* parent);
+ ~TextureTool();
+
+private:
+
+ TQString getTexturePath(int texture);
+
+private slots:
+
+ void slotResetSettings();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void prepareEffect();
+ void prepareFinal();
+ void putPreviewData();
+ void putFinalData();
+ void renderingFinished();
+
+private:
+
+ enum TextureTypes
+ {
+ PaperTexture=0,
+ Paper2Texture,
+ FabricTexture,
+ BurlapTexture,
+ BricksTexture,
+ Bricks2Texture,
+ CanvasTexture,
+ MarbleTexture,
+ Marble2Texture,
+ BlueJeanTexture,
+ CellWoodTexture,
+ MetalWireTexture,
+ ModernTexture,
+ WallTexture,
+ MossTexture,
+ StoneTexture
+ };
+
+ KDcrawIface::RComboBox *m_textureType;
+
+ KDcrawIface::RIntNumInput *m_blendGain;
+
+ Digikam::ImagePanelWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamTextureImagesPlugin
+
+#endif /* TEXTURETOOL_H */
diff --git a/src/imageplugins/whitebalance/Makefile.am b/src/imageplugins/whitebalance/Makefile.am
new file mode 100644
index 00000000..b53cf65a
--- /dev/null
+++ b/src/imageplugins/whitebalance/Makefile.am
@@ -0,0 +1,33 @@
+METASOURCES = AUTO
+
+INCLUDES = -I$(top_srcdir)/src/utilities/imageeditor/editor \
+ -I$(top_srcdir)/src/utilities/imageeditor/canvas \
+ -I$(top_srcdir)/src/libs/histogram \
+ -I$(top_srcdir)/src/libs/levels \
+ -I$(top_srcdir)/src/libs/curves \
+ -I$(top_srcdir)/src/libs/whitebalance \
+ -I$(top_srcdir)/src/libs/widgets/common \
+ -I$(top_srcdir)/src/libs/widgets/iccprofiles \
+ -I$(top_srcdir)/src/libs/widgets/imageplugins \
+ -I$(top_srcdir)/src/libs/dialogs \
+ -I$(top_srcdir)/src/libs/dimg \
+ -I$(top_srcdir)/src/libs/dmetadata \
+ -I$(top_srcdir)/src/libs/dimg/filters \
+ -I$(top_srcdir)/src/digikam \
+ $(LIBKDCRAW_CFLAGS) \
+ $(all_includes)
+
+digikamimageplugin_whitebalance_la_SOURCES = imageplugin_whitebalance.cpp \
+ whitebalancetool.cpp
+
+digikamimageplugin_whitebalance_la_LIBADD = $(LIB_TDEPARTS) \
+ $(top_builddir)/src/digikam/libdigikam.la
+
+digikamimageplugin_whitebalance_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -ltdecore -ltdeui $(LIB_TQT) -ltdefx -lkdcraw -ltdeio
+
+kde_services_DATA = digikamimageplugin_whitebalance.desktop
+
+kde_module_LTLIBRARIES = digikamimageplugin_whitebalance.la
+
+rcdir = $(kde_datadir)/digikam
+rc_DATA = digikamimageplugin_whitebalance_ui.rc
diff --git a/src/imageplugins/whitebalance/digikamimageplugin_whitebalance.desktop b/src/imageplugins/whitebalance/digikamimageplugin_whitebalance.desktop
new file mode 100644
index 00000000..df425c58
--- /dev/null
+++ b/src/imageplugins/whitebalance/digikamimageplugin_whitebalance.desktop
@@ -0,0 +1,53 @@
+[Desktop Entry]
+Name=ImagePlugin_WhiteBalance
+Name[bg]=Приставка за снимки - Баланс на бялото
+Name[el]=ΠρόσθετοΕικόνας_ΙσορροπίαΛευκού
+Name[fi]=Valkotasapaino
+Name[hr]=Bijeli balans
+Name[it]=PluginImmagini_BilanciamentoDelBianco
+Name[ms]=ImagePlugin_ImbanganPutih
+Name[nl]=Afbeeldingsplugin_Witbalans
+Name[sr]=Баланс белог
+Name[sr@Latn]=Balans belog
+Name[sv]=Insticksprogram för vitbalans
+Name[tr]=ResimEklentisi_BeyazDengesi
+Name[xx]=xxImagePlugin_WhiteBalancexx
+
+Type=Service
+X-TDE-ServiceTypes=Digikam/ImagePlugin
+Encoding=UTF-8
+Comment=White balance correction plugin for digiKam
+Comment[bg]=Приставка на digiKam за промяна баланса на бялото
+Comment[ca]=Connector pel digiKam per corregir el balanç de blancs
+Comment[da]=Hvid balance rettelsesplugin for digiKam
+Comment[de]=digiKam-Modul zur Korrektur des Weißabgleiches
+Comment[el]=Πρόσθετο διόρθωσης ισορροπίας λευκού για το digiKam
+Comment[es]=Plugin de digiKam para la corrección del equilibrio de blancos
+Comment[et]=DigiKami valge tasakaalu korrigeerimise plugin
+Comment[fa]=وصلۀ اصلاح تعادل سفید برای digiKam
+Comment[fi]=Korjaa kuvan valkotasapainon
+Comment[fr]=Module externe pour corriger la balance des blancs dans digiKam
+Comment[gl]=Un plugin de digiKam para corrixir o balance do branco
+Comment[hr]=digiKam dodatak za ispravljanje bijelog balansa
+Comment[is]=Íforrit fyrir digiKam sem breytir hvítvægi mynda
+Comment[it]=Plugin di correzione del bilanciamento del bianco per digiKam
+Comment[ja]=digiKam ホワイトバランス補正プラグイン
+Comment[ms]=Plugin pembetulan imbangan putih untuk digiKam
+Comment[nds]=digiKam-Korrektuurmoduul för de Wittbalangs
+Comment[nl]=Digikam-plugin voor het corrigeren van de witbalans
+Comment[pa]=ਡਿਜ਼ੀਕੈਮ ਲਈ ਚਿੱਟਾ ਸਾਵਾਂ ਸੋਧ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka do programu digiKam korygująca balans bieli
+Comment[pt]=Um 'plugin' do digiKam para corrigir o balanceamento de branco
+Comment[pt_BR]=Plugin para Correção de iluminação
+Comment[ru]=Модуль коррекции баланса белого для digiKam
+Comment[sk]=digiKam plugin na korekciu vyváženia bielej
+Comment[sr]=digiKam-ов прикључак исправку баланса белог
+Comment[sr@Latn]=digiKam-ov priključak ispravku balansa belog
+Comment[sv]=Digikam insticksprogram för korrigering av vitbalans
+Comment[tr]=digiKam için beyaz dengesi düzeltme eklentisi
+Comment[uk]=Втулок виправлення балансу білого для digiKam
+Comment[vi]=Phần bổ sung sửa cân bằng trắng cho digiKam
+Comment[xx]=xxWhite balance correction plugin for digiKamxx
+
+X-TDE-Library=digikamimageplugin_whitebalance
+author=Gilles Caulier, caulier dot gilles at gmail dot com
diff --git a/src/imageplugins/whitebalance/digikamimageplugin_whitebalance_ui.rc b/src/imageplugins/whitebalance/digikamimageplugin_whitebalance_ui.rc
new file mode 100644
index 00000000..9bdf8247
--- /dev/null
+++ b/src/imageplugins/whitebalance/digikamimageplugin_whitebalance_ui.rc
@@ -0,0 +1,20 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui version="5" name="digikamimageplugin_whitebalance" >
+
+ <MenuBar>
+
+ <Menu name="Color"><text>&amp;Color</text>
+ <Action name="imageplugin_whitebalance" />
+ </Menu>
+
+ </MenuBar>
+
+ <ToolBar name="ToolBar" >
+ <text>Main Toolbar</text>
+ </ToolBar>
+
+ <ActionProperties>
+ <Action name="imageplugin_whitebalance" />
+ </ActionProperties>
+
+</kpartgui>
diff --git a/src/imageplugins/whitebalance/imageeffect_whitebalance.cpp b/src/imageplugins/whitebalance/imageeffect_whitebalance.cpp
new file mode 100644
index 00000000..f72609dd
--- /dev/null
+++ b/src/imageplugins/whitebalance/imageeffect_whitebalance.cpp
@@ -0,0 +1,842 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-11
+ * Description : a digiKam image editor plugin to correct
+ * image white balance
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2008 by Guillaume Castagnino <casta at xwing dot info>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqhgroupbox.h>
+#include <tqvgroupbox.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqhbuttongroup.h>
+#include <tqwhatsthis.h>
+#include <tqlayout.h>
+#include <tqframe.h>
+#include <tqcombobox.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqpixmap.h>
+#include <tqfile.h>
+#include <tqtextstream.h>
+#include <tqvbox.h>
+
+// KDE includes.
+
+#include <kcursor.h>
+#include <tdelocale.h>
+#include <tdeaboutdata.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdeapplication.h>
+#include <tdepopupmenu.h>
+#include <kstandarddirs.h>
+#include <kprogress.h>
+#include <tdemessagebox.h>
+#include <knuminput.h>
+#include <tdeglobalsettings.h>
+#include <tdefiledialog.h>
+#include <kseparator.h>
+#include <tdeconfig.h>
+#include <kactivelabel.h>
+
+// Local includes.
+
+#include "version.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "dcolor.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "imagehistogram.h"
+#include "whitebalance.h"
+#include "colorgradientwidget.h"
+#include "histogramwidget.h"
+#include "dimgimagefilters.h"
+#include "imageeffect_whitebalance.h"
+#include "imageeffect_whitebalance.moc"
+
+namespace DigikamWhiteBalanceImagesPlugin
+{
+
+ImageEffect_WhiteBalance::ImageEffect_WhiteBalance(TQWidget* parent)
+ : Digikam::ImageDlgBase(parent, i18n("White Color Balance Correction"),
+ "whitebalance", true, false)
+{
+ TQString whatsThis;
+
+ Digikam::ImageIface iface(0, 0);
+
+ m_destinationPreviewData = 0L;
+
+ // About data and help button.
+
+ TDEAboutData* about = new TDEAboutData("digikam",
+ I18N_NOOP("White Color Balance Correction"),
+ digikam_version,
+ I18N_NOOP("A digiKam image plugin to correct white color balance."),
+ TDEAboutData::License_GPL,
+ "(c) 2005-2008, Gilles Caulier",
+ 0,
+ "http://wwww.digikam.org");
+
+ about->addAuthor("Gilles Caulier", I18N_NOOP("Author and maintainer"),
+ "caulier dot gilles at gmail dot com");
+
+ about->addAuthor("Pawel T. Jochym", I18N_NOOP("White color balance correction algorithm"),
+ "jochym at ifj edu pl");
+
+ setAboutData(about);
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new Digikam::ImageWidget("whitebalance Tool Dialog", plainPage(),
+ i18n("<p>You can see here the image's white-balance "
+ "adjustments preview. You can pick color on image to "
+ "see the color level corresponding on histogram."));
+ setPreviewAreaWidget(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ TQWidget *gboxSettings = new TQWidget(plainPage());
+ TQVBoxLayout* layout2 = new TQVBoxLayout( gboxSettings, spacingHint() );
+ TQGridLayout *grid = new TQGridLayout( layout2, 2, 4, spacingHint());
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), gboxSettings);
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, gboxSettings );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(gboxSettings);
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the "
+ "graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, Digikam::HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, Digikam::HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ grid->addMultiCellLayout(l1, 0, 0, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(gboxSettings);
+ m_histogramWidget = new Digikam::HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram "
+ "drawing of the selected image channel. This one is "
+ "re-computed at any filter settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new Digikam::ColorGradientWidget( Digikam::ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ grid->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+
+ // -------------------------------------------------------------
+
+ TQGridLayout *grid2 = new TQGridLayout(layout2, 13, 5, spacingHint());
+
+ m_temperatureLabel = new KActiveLabel(i18n("<qt><a href='http://en.wikipedia.org/wiki/Color_temperature'>Color Temperature</a> "
+ " (K): </qt>"), gboxSettings);
+ m_adjTemperatureLabel = new TQLabel(i18n("Adjustment:"), gboxSettings);
+ m_temperatureInput = new KDoubleNumInput(gboxSettings);
+ m_temperatureInput->setPrecision(1);
+ m_temperatureInput->setRange(2000.0, 12000.0, 10.0, true);
+ TQWhatsThis::add( m_temperatureInput, i18n("<p>Set here the white balance color temperature in Kelvin."));
+
+ m_temperaturePresetLabel = new TQLabel(i18n("Preset:"), gboxSettings);
+ m_temperaturePresetCB = new TQComboBox( false, gboxSettings );
+ m_temperaturePresetCB->insertItem( i18n("Candle") );
+ m_temperaturePresetCB->insertItem( i18n("40W Lamp") );
+ m_temperaturePresetCB->insertItem( i18n("100W Lamp") );
+ m_temperaturePresetCB->insertItem( i18n("200W Lamp") );
+ m_temperaturePresetCB->insertItem( i18n("Sunrise") );
+ m_temperaturePresetCB->insertItem( i18n("Studio Lamp") );
+ m_temperaturePresetCB->insertItem( i18n("Moonlight") );
+ m_temperaturePresetCB->insertItem( i18n("Neutral") );
+ m_temperaturePresetCB->insertItem( i18n("Daylight D50") );
+ m_temperaturePresetCB->insertItem( i18n("Photo Flash") );
+ m_temperaturePresetCB->insertItem( i18n("Sun") );
+ m_temperaturePresetCB->insertItem( i18n("Xenon Lamp") );
+ m_temperaturePresetCB->insertItem( i18n("Daylight D65") );
+ m_temperaturePresetCB->insertItem( i18n("None") );
+ TQWhatsThis::add( m_temperaturePresetCB, i18n("<p>Select the white balance color temperature "
+ "preset to use here:<p>"
+ "<b>Candle</b>: candle light (1850K).<p>"
+ "<b>40W Lamp</b>: 40 Watt incandescent lamp (2680K).<p>"
+ "<b>100W Lamp</b>: 100 Watt incandescent lamp (2800K).<p>"
+ "<b>200W Lamp</b>: 200 Watt incandescent lamp (3000K).<p>"
+ "<b>Sunrise</b>: sunrise or sunset light (3200K).<p>"
+ "<b>Studio Lamp</b>: tungsten lamp used in photo studio "
+ "or light at 1 hour from dusk/dawn (3400K).<p>"
+ "<b>Moonlight</b>: moon light (4100K).<p>"
+ "<b>Neutral</b>: neutral color temperature (4750K).<p>"
+ "<b>Daylight D50</b>: sunny daylight around noon (5000K).<p>"
+ "<b>Photo Flash</b>: electronic photo flash (5500K).<p>"
+ "<b>Sun</b>: effective sun temperature (5770K).<p>"
+ "<b>Xenon Lamp</b>: xenon lamp or light arc (6420K).<p>"
+ "<b>Daylight D65</b>: overcast sky light (6500K).<p>"
+ "<b>None</b>: no preset value."));
+ m_pickTemperature = new TQPushButton(gboxSettings);
+ TDEGlobal::dirs()->addResourceType("color-picker-grey", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-grey", "color-picker-grey.png");
+ m_pickTemperature->setPixmap( TQPixmap( directory + "color-picker-grey.png" ) );
+ m_pickTemperature->setToggleButton(true);
+ TQToolTip::add( m_pickTemperature, i18n( "Temperature tone color picker." ) );
+ TQWhatsThis::add( m_pickTemperature, i18n("<p>With this button, you can pick the color from original "
+ "image used to set white color balance temperature and "
+ "green component."));
+
+ KSeparator *line = new KSeparator(Horizontal, gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_blackLabel = new TQLabel(i18n("Black point:"), gboxSettings);
+ m_blackInput = new KDoubleNumInput(gboxSettings);
+ m_blackInput->setPrecision(2);
+ m_blackInput->setRange(0.0, 0.05, 0.01, true);
+ TQWhatsThis::add( m_blackInput, i18n("<p>Set here the black level value."));
+
+ m_darkLabel = new TQLabel(i18n("Shadows:"), gboxSettings);
+ m_darkInput = new KDoubleNumInput(gboxSettings);
+ m_darkInput->setPrecision(2);
+ m_darkInput->setRange(0.0, 1.0, 0.01, true);
+ TQWhatsThis::add( m_darkInput, i18n("<p>Set here the shadows noise suppresion level."));
+
+ m_saturationLabel = new TQLabel(i18n("Saturation:"), gboxSettings);
+ m_saturationInput = new KDoubleNumInput(gboxSettings);
+ m_saturationInput->setPrecision(2);
+ m_saturationInput->setRange(0.0, 2.0, 0.01, true);
+ TQWhatsThis::add( m_saturationInput, i18n("<p>Set here the saturation value."));
+
+ m_gammaLabel = new TQLabel(i18n("Gamma:"), gboxSettings);
+ m_gammaInput = new KDoubleNumInput(gboxSettings);
+ m_gammaInput->setPrecision(2);
+ m_gammaInput->setRange(0.1, 3.0, 0.01, true);
+ TQWhatsThis::add( m_gammaInput, i18n("<p>Set here the gamma correction value."));
+
+ m_greenLabel = new TQLabel(i18n("Green:"), gboxSettings);
+ m_greenInput = new KDoubleNumInput(gboxSettings);
+ m_greenInput->setPrecision(2);
+ m_greenInput->setRange(0.2, 2.5, 0.01, true);
+ TQWhatsThis::add(m_greenInput, i18n("<p>Set here the green component to set magenta color "
+ "cast removal level."));
+
+ KSeparator *line2 = new KSeparator(Horizontal, gboxSettings);
+
+ // -------------------------------------------------------------
+
+ m_exposureLabel = new KActiveLabel(i18n("<qt><a href='http://en.wikipedia.org/wiki/Exposure_value'>Exposure Compensation</a> "
+ " (E.V): </qt>"), gboxSettings);
+ m_mainExposureLabel = new TQLabel(i18n("Main:"), gboxSettings);
+ m_autoAdjustExposure = new TQPushButton(gboxSettings);
+ m_autoAdjustExposure->setPixmap(kapp->iconLoader()->loadIcon("system-run", (TDEIcon::Group)TDEIcon::Toolbar));
+ TQToolTip::add( m_autoAdjustExposure, i18n( "Auto exposure adjustments" ) );
+ TQWhatsThis::add( m_autoAdjustExposure, i18n("<p>With this button, you can automatically adjust Exposure "
+ "and Black Point values."));
+ m_mainExposureInput = new KDoubleNumInput(gboxSettings);
+ m_mainExposureInput->setPrecision(2);
+ m_mainExposureInput->setRange(-6.0, 8.0, 0.1, true);
+ TQWhatsThis::add( m_mainExposureInput, i18n("<p>Set here the main exposure compensation value in E.V."));
+
+ m_fineExposureLabel = new TQLabel(i18n("Fine:"), gboxSettings);
+ m_fineExposureInput = new KDoubleNumInput(gboxSettings);
+ m_fineExposureInput->setPrecision(2);
+ m_fineExposureInput->setRange(-0.5, 0.5, 0.01, true);
+ TQWhatsThis::add( m_fineExposureInput, i18n("<p>This value in E.V will be added to main exposure "
+ "compensation value to set fine exposure adjustment."));
+
+ // -------------------------------------------------------------
+
+ grid2->addMultiCellWidget(m_temperatureLabel, 0, 0, 0, 5);
+ grid2->addMultiCellWidget(m_adjTemperatureLabel, 1, 1, 0, 0);
+ grid2->addMultiCellWidget(m_pickTemperature, 1, 1, 1, 1);
+ grid2->addMultiCellWidget(m_temperatureInput, 1, 1, 2, 5);
+ grid2->addMultiCellWidget(m_temperaturePresetLabel, 2, 2, 0, 0);
+ grid2->addMultiCellWidget(m_temperaturePresetCB, 2, 2, 2, 5);
+
+ grid2->addMultiCellWidget(line, 3, 3, 0, 5);
+
+ grid2->addMultiCellWidget(m_blackLabel, 4, 4, 0, 0);
+ grid2->addMultiCellWidget(m_blackInput, 4, 4, 1, 5);
+ grid2->addMultiCellWidget(m_darkLabel, 5, 5, 0, 0);
+ grid2->addMultiCellWidget(m_darkInput, 5, 5, 1, 5);
+ grid2->addMultiCellWidget(m_saturationLabel, 6, 6, 0, 0);
+ grid2->addMultiCellWidget(m_saturationInput, 6, 6, 1, 5);
+ grid2->addMultiCellWidget(m_gammaLabel, 7, 7, 0, 0);
+ grid2->addMultiCellWidget(m_gammaInput, 7, 7, 1, 5);
+ grid2->addMultiCellWidget(m_greenLabel, 8, 8, 0, 0);
+ grid2->addMultiCellWidget(m_greenInput, 8, 8, 1, 5);
+
+ grid2->addMultiCellWidget(line2, 9, 9, 0, 5);
+
+ grid2->addMultiCellWidget(m_exposureLabel, 10, 10, 0, 5);
+ grid2->addMultiCellWidget(m_mainExposureLabel, 11, 11, 0, 0);
+ grid2->addMultiCellWidget(m_autoAdjustExposure, 11, 11, 1, 1);
+ grid2->addMultiCellWidget(m_mainExposureInput, 11, 11, 2, 5);
+ grid2->addMultiCellWidget(m_fineExposureLabel, 12, 12, 0, 1);
+ grid2->addMultiCellWidget(m_fineExposureInput, 12, 12, 2, 5);
+ grid2->setRowStretch(13, 10);
+
+ setUserAreaWidget(gboxSettings);
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromOriginal( const Digikam::DColor & )));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget( const Digikam::DColor &, const TQPoint & )),
+ this, TQ_SLOT(slotColorSelectedFromTarget( const Digikam::DColor & )));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+ // Correction Filter Slider controls.
+
+ connect(m_temperaturePresetCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotTemperaturePresetChanged(int)));
+
+ connect(m_temperatureInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTemperatureChanged(double)));
+
+ connect(m_darkInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_blackInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_mainExposureInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_fineExposureInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gammaInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_saturationInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_greenInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ // -------------------------------------------------------------
+ // Bouttons slots.
+
+ connect(m_autoAdjustExposure, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotAutoAdjustExposure()));
+
+ connect(m_pickTemperature, TQ_SIGNAL(released()),
+ this, TQ_SLOT(slotPickerColorButtonActived()));
+}
+
+ImageEffect_WhiteBalance::~ImageEffect_WhiteBalance()
+{
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ delete m_histogramWidget;
+}
+
+void ImageEffect_WhiteBalance::slotTemperatureChanged(double temperature)
+{
+ switch((uint)temperature)
+ {
+ case 1850:
+ m_temperaturePresetCB->setCurrentItem(Candle);
+ break;
+
+ case 2680:
+ m_temperaturePresetCB->setCurrentItem(Lamp40W);
+ break;
+
+ case 2800:
+ m_temperaturePresetCB->setCurrentItem(Lamp100W);
+ break;
+
+ case 3000:
+ m_temperaturePresetCB->setCurrentItem(Lamp200W);
+ break;
+
+ case 3200:
+ m_temperaturePresetCB->setCurrentItem(Sunrise);
+ break;
+
+ case 3400:
+ m_temperaturePresetCB->setCurrentItem(StudioLamp);
+ break;
+
+ case 4100:
+ m_temperaturePresetCB->setCurrentItem(MoonLight);
+ break;
+
+ case 4750:
+ m_temperaturePresetCB->setCurrentItem(Neutral);
+ break;
+
+ case 5000:
+ m_temperaturePresetCB->setCurrentItem(DaylightD50);
+ break;
+
+ case 5500:
+ m_temperaturePresetCB->setCurrentItem(Flash);
+ break;
+
+ case 5770:
+ m_temperaturePresetCB->setCurrentItem(Sun);
+ break;
+
+ case 6420:
+ m_temperaturePresetCB->setCurrentItem(XeonLamp);
+ break;
+
+ case 6500:
+ m_temperaturePresetCB->setCurrentItem(DaylightD65);
+ break;
+
+ default:
+ m_temperaturePresetCB->setCurrentItem(None);
+ break;
+ }
+
+ slotTimer();
+}
+
+void ImageEffect_WhiteBalance::slotTemperaturePresetChanged(int tempPreset)
+{
+ switch(tempPreset)
+ {
+ case Candle:
+ m_temperatureInput->setValue(1850.0);
+ break;
+
+ case Lamp40W:
+ m_temperatureInput->setValue(2680.0);
+ break;
+
+ case Lamp100W:
+ m_temperatureInput->setValue(2800.0);
+ break;
+
+ case Lamp200W:
+ m_temperatureInput->setValue(3000.0);
+ break;
+
+ case Sunrise:
+ m_temperatureInput->setValue(3200.0);
+ break;
+
+ case StudioLamp:
+ m_temperatureInput->setValue(3400.0);
+ break;
+
+ case MoonLight:
+ m_temperatureInput->setValue(4100.0);
+ break;
+
+ case Neutral:
+ m_temperatureInput->setValue(4750.0);
+ break;
+
+ case DaylightD50:
+ m_temperatureInput->setValue(5000.0);
+ break;
+
+ case Flash:
+ m_temperatureInput->setValue(5500.0);
+ break;
+
+ case Sun:
+ m_temperatureInput->setValue(5770.0);
+ break;
+
+ case XeonLamp:
+ m_temperatureInput->setValue(6420.0);
+ break;
+
+ case DaylightD65:
+ m_temperatureInput->setValue(6500.0);
+ break;
+
+ default: // None.
+ break;
+ }
+
+ slotEffect();
+}
+
+void ImageEffect_WhiteBalance::slotPickerColorButtonActived()
+{
+ // Save previous rendering mode and toggle to original image.
+ m_currentPreviewMode = m_previewWidget->getRenderingPreviewMode();
+ m_previewWidget->setRenderingPreviewMode(Digikam::ImageGuideWidget::PreviewOriginalImage);
+}
+
+void ImageEffect_WhiteBalance::slotColorSelectedFromOriginal(const Digikam::DColor &color)
+{
+ if ( m_pickTemperature->isOn() )
+ {
+ Digikam::DColor dc = color;
+ TQColor tc = dc.getTQColor();
+ double temperatureLevel, greenLevel;
+
+ Digikam::WhiteBalance::autoWBAdjustementFromColor(tc, temperatureLevel, greenLevel);
+
+ m_temperatureInput->setValue(temperatureLevel);
+ m_greenInput->setValue(greenLevel);
+ m_pickTemperature->setOn(false);
+ }
+ else
+ return;
+
+ // restore previous rendering mode.
+ m_previewWidget->setRenderingPreviewMode(m_currentPreviewMode);
+
+ slotEffect();
+}
+
+void ImageEffect_WhiteBalance::slotColorSelectedFromTarget( const Digikam::DColor &color )
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void ImageEffect_WhiteBalance::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_WhiteBalance::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = Digikam::HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void ImageEffect_WhiteBalance::slotAutoAdjustExposure()
+{
+ parentWidget()->setCursor( KCursor::waitCursor() );
+
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int width = iface->originalWidth();
+ int height = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ double blackLevel;
+ double exposureLevel;
+
+ Digikam::WhiteBalance::autoExposureAdjustement(data, width, height, sb, blackLevel, exposureLevel);
+ delete [] data;
+
+ m_blackInput->setValue(blackLevel);
+ m_mainExposureInput->setValue(exposureLevel);
+ m_fineExposureInput->setValue(0.0);
+
+ parentWidget()->unsetCursor();
+ slotEffect();
+}
+
+void ImageEffect_WhiteBalance::slotEffect()
+{
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ // Create the new empty destination image data space.
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ m_destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)];
+
+ double temperature = m_temperatureInput->value();
+ double dark = m_darkInput->value();
+ double black = m_blackInput->value();
+ double mainExposure = m_mainExposureInput->value();
+ double fineExposure = m_fineExposureInput->value();
+ double gamma = m_gammaInput->value();
+ double saturation = m_saturationInput->value();
+ double green = m_greenInput->value();
+
+ Digikam::WhiteBalance wbFilter(sb);
+ wbFilter.whiteBalance(data, w, h, sb,
+ black, mainExposure + fineExposure,
+ temperature, green, dark,
+ gamma, saturation);
+
+ iface->putPreviewImage(data);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+ memcpy (m_destinationPreviewData, data, w*h*(sb ? 8 : 4));
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ delete [] data;
+}
+
+void ImageEffect_WhiteBalance::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ Digikam::ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ double temperature = m_temperatureInput->value();
+ double dark = m_darkInput->value();
+ double black = m_blackInput->value();
+ double mainExposure = m_mainExposureInput->value();
+ double fineExposure = m_fineExposureInput->value();
+ double gamma = m_gammaInput->value();
+ double saturation = m_saturationInput->value();
+ double green = m_greenInput->value();
+
+ Digikam::WhiteBalance wbFilter(sb);
+ wbFilter.whiteBalance(data, w, h, sb,
+ black, mainExposure + fineExposure,
+ temperature, green, dark,
+ gamma, saturation);
+
+ iface->putOriginalImage(i18n("White Balance"), data);
+ delete [] data;
+ kapp->restoreOverrideCursor();
+ accept();
+}
+
+void ImageEffect_WhiteBalance::resetValues()
+{
+ m_darkInput->blockSignals(true);
+ m_blackInput->blockSignals(true);
+ m_mainExposureInput->blockSignals(true);
+ m_fineExposureInput->blockSignals(true);
+ m_gammaInput->blockSignals(true);
+ m_saturationInput->blockSignals(true);
+ m_greenInput->blockSignals(true);
+ m_temperaturePresetCB->blockSignals(true);
+
+ // Neutral color temperature settings is D65
+ m_darkInput->setValue(0.5);
+ m_blackInput->setValue(0.0);
+ m_mainExposureInput->setValue(0.0);
+ m_fineExposureInput->setValue(0.0);
+ m_gammaInput->setValue(1.0);
+ m_saturationInput->setValue(1.0);
+ m_greenInput->setValue(1.0);
+ m_temperaturePresetCB->setCurrentItem(DaylightD65);
+ slotTemperaturePresetChanged(DaylightD65);
+
+ m_previewWidget->resetSpotPosition();
+ m_channelCB->setCurrentItem(LuminosityChannel);
+ slotChannelChanged(LuminosityChannel);
+
+ m_histogramWidget->reset();
+
+ m_darkInput->blockSignals(false);
+ m_blackInput->blockSignals(false);
+ m_mainExposureInput->blockSignals(false);
+ m_fineExposureInput->blockSignals(false);
+ m_gammaInput->blockSignals(false);
+ m_saturationInput->blockSignals(false);
+ m_greenInput->blockSignals(false);
+ m_temperaturePresetCB->blockSignals(false);
+ slotEffect();
+}
+
+void ImageEffect_WhiteBalance::readUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("whitebalance Tool Dialog");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", Digikam::HistogramWidget::LogScaleHistogram));
+
+ m_darkInput->setValue(config->readDoubleNumEntry("Dark", 0.5));
+ m_blackInput->setValue(config->readDoubleNumEntry("Black", 0.0));
+ m_mainExposureInput->setValue(config->readDoubleNumEntry("MainExposure", 0.0));
+ m_fineExposureInput->setValue(config->readDoubleNumEntry("FineExposure", 0.0));
+ m_gammaInput->setValue(config->readDoubleNumEntry("Gamma", 1.0));
+ m_saturationInput->setValue(config->readDoubleNumEntry("Saturation", 1.0));
+ m_greenInput->setValue(config->readDoubleNumEntry("Green", 1.0));
+ m_temperatureInput->setValue(config->readDoubleNumEntry("Temperature", 6500.0));
+ slotTemperatureChanged(m_temperatureInput->value());
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void ImageEffect_WhiteBalance::writeUserSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("whitebalance Tool Dialog");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+
+ config->writeEntry("Dark", m_darkInput->value());
+ config->writeEntry("Black", m_blackInput->value());
+ config->writeEntry("MainExposure", m_mainExposureInput->value());
+ config->writeEntry("FineExposure", m_fineExposureInput->value());
+ config->writeEntry("Gamma", m_gammaInput->value());
+ config->writeEntry("Saturation", m_saturationInput->value());
+ config->writeEntry("Green", m_greenInput->value());
+ config->writeEntry("Temperature", m_temperatureInput->value());
+ config->sync();
+}
+
+// Load all settings.
+void ImageEffect_WhiteBalance::slotUser3()
+{
+ KURL loadWhiteBalanceFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("White Color Balance Settings File to Load")) );
+ if( loadWhiteBalanceFile.isEmpty() )
+ return;
+
+ TQFile file(loadWhiteBalanceFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+
+ if ( stream.readLine() != "# White Color Balance Configuration File V2" )
+ {
+ KMessageBox::error(this,
+ i18n("\"%1\" is not a White Color Balance settings text file.")
+ .arg(loadWhiteBalanceFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+ m_temperatureInput->setValue( stream.readLine().toDouble() );
+ m_darkInput->setValue( stream.readLine().toDouble() );
+ m_blackInput->setValue( stream.readLine().toDouble() );
+ m_mainExposureInput->setValue( stream.readLine().toDouble() );
+ m_fineExposureInput->setValue( stream.readLine().toDouble() );
+ m_gammaInput->setValue( stream.readLine().toDouble() );
+ m_saturationInput->setValue( stream.readLine().toDouble() );
+ m_greenInput->setValue( stream.readLine().toDouble() );
+ m_histogramWidget->reset();
+ blockSignals(false);
+ slotEffect();
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot load settings from the White Color Balance text file."));
+
+ file.close();
+}
+
+// Save all settings.
+void ImageEffect_WhiteBalance::slotUser2()
+{
+ KURL saveWhiteBalanceFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), this,
+ TQString( i18n("White Color Balance Settings File to Save")) );
+ if( saveWhiteBalanceFile.isEmpty() )
+ return;
+
+ TQFile file(saveWhiteBalanceFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# White Color Balance Configuration File V2\n";
+ stream << m_temperatureInput->value() << "\n";
+ stream << m_darkInput->value() << "\n";
+ stream << m_blackInput->value() << "\n";
+ stream << m_mainExposureInput->value() << "\n";
+ stream << m_fineExposureInput->value() << "\n";
+ stream << m_gammaInput->value() << "\n";
+ stream << m_saturationInput->value() << "\n";
+ stream << m_greenInput->value() << "\n";
+ }
+ else
+ KMessageBox::error(this, i18n("Cannot save settings to the White Color Balance text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamWhiteBalanceImagesPlugin
+
diff --git a/src/imageplugins/whitebalance/imageeffect_whitebalance.h b/src/imageplugins/whitebalance/imageeffect_whitebalance.h
new file mode 100644
index 00000000..6bef5607
--- /dev/null
+++ b/src/imageplugins/whitebalance/imageeffect_whitebalance.h
@@ -0,0 +1,168 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-11
+ * Description : a digiKam image editor plugin to correct
+ * image white balance
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2008 by Guillaume Castagnino <casta at xwing dot info>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEEFFECT_WHITEBALANCE_H
+#define IMAGEEFFECT_WHITEBALANCE_H
+
+// TQt include.
+
+#include <tqcolor.h>
+
+// Digikam includes.
+
+#include "imagedlgbase.h"
+
+class TQPushButton;
+class TQLabel;
+class TQComboBox;
+class TQPushButton;
+class TQHButtonGroup;
+
+class KDoubleNumInput;
+class KActiveLabel;
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+}
+
+namespace DigikamWhiteBalanceImagesPlugin
+{
+
+class ImageEffect_WhiteBalance : public Digikam::ImageDlgBase
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImageEffect_WhiteBalance(TQWidget* parent);
+ ~ImageEffect_WhiteBalance();
+
+protected:
+
+ void finalRendering();
+
+private slots:
+
+ void slotUser2();
+ void slotUser3();
+ void slotEffect();
+ void slotColorSelectedFromOriginal(const Digikam::DColor &color);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+ void slotScaleChanged(int scale);
+ void slotChannelChanged(int channel);
+ void slotTemperatureChanged(double temperature);
+ void slotTemperaturePresetChanged(int tempPreset);
+ void slotAutoAdjustExposure(void);
+ void slotPickerColorButtonActived();
+
+private:
+
+ void readUserSettings();
+ void writeUserSettings();
+ void resetValues();
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum TemperaturePreset
+ {
+ Candle=0,
+ Lamp40W,
+ Lamp100W,
+ Lamp200W,
+ Sunrise,
+ StudioLamp,
+ MoonLight,
+ Neutral,
+ DaylightD50,
+ Flash,
+ Sun,
+ XeonLamp,
+ DaylightD65,
+ None
+ };
+
+ uchar *m_destinationPreviewData;
+
+ int m_currentPreviewMode;
+
+ TQPushButton *m_pickTemperature;
+ TQPushButton *m_autoAdjustExposure;
+
+ TQComboBox *m_temperaturePresetCB;
+ TQComboBox *m_channelCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ TQLabel *m_adjTemperatureLabel;
+ TQLabel *m_temperaturePresetLabel;
+ TQLabel *m_darkLabel;
+ TQLabel *m_blackLabel;
+ TQLabel *m_mainExposureLabel;
+ TQLabel *m_fineExposureLabel;
+ TQLabel *m_gammaLabel;
+ TQLabel *m_saturationLabel;
+ TQLabel *m_greenLabel;
+
+ KActiveLabel *m_exposureLabel;
+ KActiveLabel *m_temperatureLabel;
+
+ KDoubleNumInput *m_temperatureInput;
+ KDoubleNumInput *m_darkInput;
+ KDoubleNumInput *m_blackInput;
+ KDoubleNumInput *m_mainExposureInput;
+ KDoubleNumInput *m_fineExposureInput;
+ KDoubleNumInput *m_gammaInput;
+ KDoubleNumInput *m_saturationInput;
+ KDoubleNumInput *m_greenInput;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::ImageWidget *m_previewWidget;
+};
+
+} // NameSpace DigikamWhiteBalanceImagesPlugin
+
+#endif /* IMAGEEFFECT_WHITEBALANCE_H */
diff --git a/src/imageplugins/whitebalance/imageplugin_whitebalance.cpp b/src/imageplugins/whitebalance/imageplugin_whitebalance.cpp
new file mode 100644
index 00000000..071097fe
--- /dev/null
+++ b/src/imageplugins/whitebalance/imageplugin_whitebalance.cpp
@@ -0,0 +1,71 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-11
+ * Description : a digiKam image editor plugin to correct
+ * image white balance
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// KDE includes.
+
+#include <tdelocale.h>
+#include <kgenericfactory.h>
+#include <klibloader.h>
+#include <tdeaction.h>
+#include <kcursor.h>
+
+// Local includes.
+
+#include "ddebug.h"
+#include "whitebalancetool.h"
+#include "imageplugin_whitebalance.h"
+#include "imageplugin_whitebalance.moc"
+
+using namespace DigikamWhiteBalanceImagesPlugin;
+
+K_EXPORT_COMPONENT_FACTORY(digikamimageplugin_whitebalance,
+ KGenericFactory<ImagePlugin_WhiteBalance>("digikamimageplugin_whitebalance"));
+
+ImagePlugin_WhiteBalance::ImagePlugin_WhiteBalance(TQObject *parent, const char*, const TQStringList &)
+ : Digikam::ImagePlugin(parent, "ImagePlugin_WhiteBalance")
+{
+ m_whitebalanceAction = new TDEAction(i18n("White Balance..."), "whitebalance",
+ CTRL+SHIFT+Key_W,
+ this, TQ_SLOT(slotWhiteBalance()),
+ actionCollection(), "imageplugin_whitebalance");
+
+ setXMLFile("digikamimageplugin_whitebalance_ui.rc");
+
+ DDebug() << "ImagePlugin_WhiteBalance plugin loaded" << endl;
+}
+
+ImagePlugin_WhiteBalance::~ImagePlugin_WhiteBalance()
+{
+}
+
+void ImagePlugin_WhiteBalance::setEnabledActions(bool enable)
+{
+ m_whitebalanceAction->setEnabled(enable);
+}
+
+void ImagePlugin_WhiteBalance::slotWhiteBalance()
+{
+ WhiteBalanceTool *wb = new WhiteBalanceTool(this);
+ loadTool(wb);
+}
diff --git a/src/imageplugins/whitebalance/imageplugin_whitebalance.h b/src/imageplugins/whitebalance/imageplugin_whitebalance.h
new file mode 100644
index 00000000..afc870c1
--- /dev/null
+++ b/src/imageplugins/whitebalance/imageplugin_whitebalance.h
@@ -0,0 +1,57 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-11
+ * Description : a digiKam image editor plugin to correct
+ * image white balance
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef IMAGEPLUGIN_WHITEBALANCE_H
+#define IMAGEPLUGIN_WHITEBALANCE_H
+
+// Digikam includes.
+
+#include "imageplugin.h"
+#include "digikam_export.h"
+
+class TDEAction;
+
+class DIGIKAMIMAGEPLUGINS_EXPORT ImagePlugin_WhiteBalance : public Digikam::ImagePlugin
+{
+ TQ_OBJECT
+
+
+public:
+
+ ImagePlugin_WhiteBalance(TQObject *parent, const char* name,
+ const TQStringList &args);
+ ~ImagePlugin_WhiteBalance();
+
+ void setEnabledActions(bool enable);
+
+private slots:
+
+ void slotWhiteBalance();
+
+private:
+
+ TDEAction *m_whitebalanceAction;
+};
+
+#endif /* IMAGEPLUGIN_WHITEBALANCE_H */
diff --git a/src/imageplugins/whitebalance/whitebalancetool.cpp b/src/imageplugins/whitebalance/whitebalancetool.cpp
new file mode 100644
index 00000000..fdbe723a
--- /dev/null
+++ b/src/imageplugins/whitebalance/whitebalancetool.cpp
@@ -0,0 +1,850 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-11
+ * Description : a digiKam image editor plugin to correct
+ * image white balance
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2008 by Guillaume Castagnino <casta at xwing dot info>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+// TQt includes.
+
+#include <tqcombobox.h>
+#include <tqfile.h>
+#include <tqframe.h>
+#include <tqhbuttongroup.h>
+#include <tqhgroupbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpixmap.h>
+#include <tqpushbutton.h>
+#include <tqtextstream.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqvbox.h>
+#include <tqvgroupbox.h>
+#include <tqwhatsthis.h>
+
+// KDE includes.
+
+#include <tdeaboutdata.h>
+#include <kactivelabel.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kcursor.h>
+#include <tdefiledialog.h>
+#include <tdeglobalsettings.h>
+#include <khelpmenu.h>
+#include <kiconloader.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <tdepopupmenu.h>
+#include <kprogress.h>
+#include <kseparator.h>
+#include <kstandarddirs.h>
+
+// LibKDcraw includes.
+
+#include <libkdcraw/rnuminput.h>
+#include <libkdcraw/rcombobox.h>
+
+// Digikam includes.
+
+#include "colorgradientwidget.h"
+#include "daboutdata.h"
+#include "dcolor.h"
+#include "ddebug.h"
+#include "dimg.h"
+#include "dimgimagefilters.h"
+#include "editortoolsettings.h"
+#include "histogramwidget.h"
+#include "imagehistogram.h"
+#include "imageiface.h"
+#include "imagewidget.h"
+#include "whitebalance.h"
+
+// Local includes.
+
+#include "whitebalancetool.h"
+#include "whitebalancetool.moc"
+
+using namespace KDcrawIface;
+using namespace Digikam;
+
+namespace DigikamWhiteBalanceImagesPlugin
+{
+
+WhiteBalanceTool::WhiteBalanceTool(TQObject* parent)
+ : EditorTool(parent)
+{
+ setName("whitebalance");
+ setToolName(i18n("White Balance"));
+ setToolIcon(SmallIcon("whitebalance"));
+
+ m_destinationPreviewData = 0;
+
+ // -------------------------------------------------------------
+
+ m_previewWidget = new ImageWidget("whitebalance Tool", 0,
+ i18n("<p>You can see here the image's white-balance "
+ "adjustments preview. You can pick color on image to "
+ "see the color level corresponding on histogram."));
+ setToolView(m_previewWidget);
+
+ // -------------------------------------------------------------
+
+ m_gboxSettings = new EditorToolSettings(EditorToolSettings::Default|
+ EditorToolSettings::Load|
+ EditorToolSettings::SaveAs|
+ EditorToolSettings::Ok|
+ EditorToolSettings::Cancel);
+
+ TQVBoxLayout* layout2 = new TQVBoxLayout(m_gboxSettings->plainPage(), m_gboxSettings->spacingHint());
+ TQGridLayout *grid = new TQGridLayout(layout2, 2, 4);
+
+ TQLabel *label1 = new TQLabel(i18n("Channel:"), m_gboxSettings->plainPage());
+ label1->setAlignment ( TQt::AlignRight | TQt::AlignVCenter );
+ m_channelCB = new TQComboBox( false, m_gboxSettings->plainPage() );
+ m_channelCB->insertItem( i18n("Luminosity") );
+ m_channelCB->insertItem( i18n("Red") );
+ m_channelCB->insertItem( i18n("Green") );
+ m_channelCB->insertItem( i18n("Blue") );
+ TQWhatsThis::add( m_channelCB, i18n("<p>Select the histogram channel to display here:<p>"
+ "<b>Luminosity</b>: display the image's luminosity values.<p>"
+ "<b>Red</b>: display the red image-channel values.<p>"
+ "<b>Green</b>: display the green image-channel values.<p>"
+ "<b>Blue</b>: display the blue image-channel values.<p>"));
+
+ m_scaleBG = new TQHButtonGroup(m_gboxSettings->plainPage());
+ m_scaleBG->setExclusive(true);
+ m_scaleBG->setFrameShape(TQFrame::NoFrame);
+ m_scaleBG->setInsideMargin( 0 );
+ TQWhatsThis::add( m_scaleBG, i18n("<p>Select the histogram scale here.<p>"
+ "If the image's maximal counts are small, you can use the linear scale.<p>"
+ "Logarithmic scale can be used when the maximal counts are big; "
+ "if it is used, all values (small and large) will be visible on the "
+ "graph."));
+
+ TQPushButton *linHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( linHistoButton, i18n( "<p>Linear" ) );
+ m_scaleBG->insert(linHistoButton, HistogramWidget::LinScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-lin", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ TQString directory = TDEGlobal::dirs()->findResourceDir("histogram-lin", "histogram-lin.png");
+ linHistoButton->setPixmap( TQPixmap( directory + "histogram-lin.png" ) );
+ linHistoButton->setToggleButton(true);
+
+ TQPushButton *logHistoButton = new TQPushButton( m_scaleBG );
+ TQToolTip::add( logHistoButton, i18n( "<p>Logarithmic" ) );
+ m_scaleBG->insert(logHistoButton, HistogramWidget::LogScaleHistogram);
+ TDEGlobal::dirs()->addResourceType("histogram-log", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("histogram-log", "histogram-log.png");
+ logHistoButton->setPixmap( TQPixmap( directory + "histogram-log.png" ) );
+ logHistoButton->setToggleButton(true);
+
+ TQHBoxLayout* l1 = new TQHBoxLayout();
+ l1->addWidget(label1);
+ l1->addWidget(m_channelCB);
+ l1->addStretch(10);
+ l1->addWidget(m_scaleBG);
+
+ // -------------------------------------------------------------
+
+ TQVBox *histoBox = new TQVBox(m_gboxSettings->plainPage());
+ m_histogramWidget = new HistogramWidget(256, 140, histoBox, false, true, true);
+ TQWhatsThis::add( m_histogramWidget, i18n("<p>Here you can see the target preview image histogram "
+ "drawing of the selected image channel. This one is "
+ "re-computed at any filter settings changes."));
+ TQLabel *space = new TQLabel(histoBox);
+ space->setFixedHeight(1);
+ m_hGradient = new ColorGradientWidget( ColorGradientWidget::Horizontal, 10, histoBox );
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+
+ grid->addMultiCellLayout(l1, 0, 0, 0, 4);
+ grid->addMultiCellWidget(histoBox, 1, 2, 0, 4);
+ grid->setMargin(m_gboxSettings->spacingHint());
+ grid->setSpacing(m_gboxSettings->spacingHint());
+
+ // -------------------------------------------------------------
+
+ TQGridLayout *grid2 = new TQGridLayout(layout2, 13, 5);
+
+ m_temperatureLabel = new KActiveLabel(i18n("<qt><a href='http://en.wikipedia.org/wiki/Color_temperature'>Color Temperature</a> "
+ " (K): </qt>"), m_gboxSettings->plainPage());
+ m_adjTemperatureLabel = new TQLabel(i18n("Adjustment:"), m_gboxSettings->plainPage());
+ m_temperatureInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_temperatureInput->setPrecision(1);
+ m_temperatureInput->setRange(1750.0, 12000.0, 10.0);
+ m_temperatureInput->setDefaultValue(6500.0);
+ TQWhatsThis::add( m_temperatureInput, i18n("<p>Set here the white balance color temperature in Kelvin."));
+
+ m_temperaturePresetLabel = new TQLabel(i18n("Preset:"), m_gboxSettings->plainPage());
+ m_temperaturePresetCB = new RComboBox(m_gboxSettings->plainPage());
+ m_temperaturePresetCB->insertItem(i18n("Candle"));
+ m_temperaturePresetCB->insertItem(i18n("40W Lamp"));
+ m_temperaturePresetCB->insertItem(i18n("100W Lamp"));
+ m_temperaturePresetCB->insertItem(i18n("200W Lamp"));
+ m_temperaturePresetCB->insertItem(i18n("Sunrise"));
+ m_temperaturePresetCB->insertItem(i18n("Studio Lamp"));
+ m_temperaturePresetCB->insertItem(i18n("Moonlight"));
+ m_temperaturePresetCB->insertItem(i18n("Neutral"));
+ m_temperaturePresetCB->insertItem(i18n("Daylight D50"));
+ m_temperaturePresetCB->insertItem(i18n("Photo Flash"));
+ m_temperaturePresetCB->insertItem(i18n("Sun"));
+ m_temperaturePresetCB->insertItem(i18n("Xenon Lamp"));
+ m_temperaturePresetCB->insertItem(i18n("Daylight D65"));
+ m_temperaturePresetCB->insertItem(i18n("None"));
+ m_temperaturePresetCB->setDefaultItem(DaylightD65);
+ TQWhatsThis::add( m_temperaturePresetCB, i18n("<p>Select the white balance color temperature "
+ "preset to use here:<p>"
+ "<b>Candle</b>: candle light (1850K).<p>"
+ "<b>40W Lamp</b>: 40 Watt incandescent lamp (2680K).<p>"
+ "<b>100W Lamp</b>: 100 Watt incandescent lamp (2800K).<p>"
+ "<b>200W Lamp</b>: 200 Watt incandescent lamp (3000K).<p>"
+ "<b>Sunrise</b>: sunrise or sunset light (3200K).<p>"
+ "<b>Studio Lamp</b>: tungsten lamp used in photo studio "
+ "or light at 1 hour from dusk/dawn (3400K).<p>"
+ "<b>Moonlight</b>: moon light (4100K).<p>"
+ "<b>Neutral</b>: neutral color temperature (4750K).<p>"
+ "<b>Daylight D50</b>: sunny daylight around noon (5000K).<p>"
+ "<b>Photo Flash</b>: electronic photo flash (5500K).<p>"
+ "<b>Sun</b>: effective sun temperature (5770K).<p>"
+ "<b>Xenon Lamp</b>: xenon lamp or light arc (6420K).<p>"
+ "<b>Daylight D65</b>: overcast sky light (6500K).<p>"
+ "<b>None</b>: no preset value."));
+ m_pickTemperature = new TQPushButton(m_gboxSettings->plainPage());
+ TDEGlobal::dirs()->addResourceType("color-picker-grey", TDEGlobal::dirs()->kde_default("data") + "digikam/data");
+ directory = TDEGlobal::dirs()->findResourceDir("color-picker-grey", "color-picker-grey.png");
+ m_pickTemperature->setPixmap( TQPixmap( directory + "color-picker-grey.png" ) );
+ m_pickTemperature->setToggleButton(true);
+ TQToolTip::add( m_pickTemperature, i18n( "Temperature tone color picker." ) );
+ TQWhatsThis::add( m_pickTemperature, i18n("<p>With this button, you can pick the color from original "
+ "image used to set white color balance temperature and "
+ "green component."));
+
+ KSeparator *line = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ // -------------------------------------------------------------
+
+ m_blackLabel = new TQLabel(i18n("Black point:"), m_gboxSettings->plainPage());
+ m_blackInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_blackInput->setPrecision(2);
+ m_blackInput->setRange(0.0, 0.05, 0.01);
+ m_blackInput->setDefaultValue(0.0);
+ TQWhatsThis::add( m_blackInput, i18n("<p>Set here the black level value."));
+
+ m_darkLabel = new TQLabel(i18n("Shadows:"), m_gboxSettings->plainPage());
+ m_darkInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_darkInput->setPrecision(2);
+ m_darkInput->setRange(0.0, 1.0, 0.01);
+ m_darkInput->setDefaultValue(0.5);
+ TQWhatsThis::add( m_darkInput, i18n("<p>Set here the shadows noise suppresion level."));
+
+ m_saturationLabel = new TQLabel(i18n("Saturation:"), m_gboxSettings->plainPage());
+ m_saturationInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_saturationInput->setPrecision(2);
+ m_saturationInput->setRange(0.0, 2.0, 0.01);
+ m_saturationInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_saturationInput, i18n("<p>Set here the saturation value."));
+
+ m_gammaLabel = new TQLabel(i18n("Gamma:"), m_gboxSettings->plainPage());
+ m_gammaInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_gammaInput->setPrecision(2);
+ m_gammaInput->setRange(0.1, 3.0, 0.01);
+ m_gammaInput->setDefaultValue(1.0);
+ TQWhatsThis::add( m_gammaInput, i18n("<p>Set here the gamma correction value."));
+
+ m_greenLabel = new TQLabel(i18n("Green:"), m_gboxSettings->plainPage());
+ m_greenInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_greenInput->setPrecision(2);
+ m_greenInput->setRange(0.2, 2.5, 0.01);
+ m_greenInput->setDefaultValue(1.0);
+ TQWhatsThis::add(m_greenInput, i18n("<p>Set here the green component to set magenta color "
+ "cast removal level."));
+
+ KSeparator *line2 = new KSeparator(Horizontal, m_gboxSettings->plainPage());
+
+ // -------------------------------------------------------------
+
+ m_exposureLabel = new KActiveLabel(i18n("<qt><a href='http://en.wikipedia.org/wiki/Exposure_value'>Exposure Compensation</a> "
+ " (E.V): </qt>"), m_gboxSettings->plainPage());
+ m_mainExposureLabel = new TQLabel(i18n("Main:"), m_gboxSettings->plainPage());
+ m_autoAdjustExposure = new TQPushButton(m_gboxSettings->plainPage());
+ m_autoAdjustExposure->setPixmap(kapp->iconLoader()->loadIcon("system-run", (TDEIcon::Group)TDEIcon::Toolbar));
+ TQToolTip::add( m_autoAdjustExposure, i18n( "Auto exposure adjustments" ) );
+ TQWhatsThis::add( m_autoAdjustExposure, i18n("<p>With this button, you can automatically adjust Exposure "
+ "and Black Point values."));
+ m_mainExposureInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_mainExposureInput->setPrecision(2);
+ m_mainExposureInput->setRange(-6.0, 8.0, 0.1);
+ m_mainExposureInput->setDefaultValue(0.0);
+ TQWhatsThis::add( m_mainExposureInput, i18n("<p>Set here the main exposure compensation value in E.V."));
+
+ m_fineExposureLabel = new TQLabel(i18n("Fine:"), m_gboxSettings->plainPage());
+ m_fineExposureInput = new RDoubleNumInput(m_gboxSettings->plainPage());
+ m_fineExposureInput->setPrecision(2);
+ m_fineExposureInput->setRange(-0.5, 0.5, 0.01);
+ m_fineExposureInput->setDefaultValue(0.0);
+ TQWhatsThis::add( m_fineExposureInput, i18n("<p>This value in E.V will be added to main exposure "
+ "compensation value to set fine exposure adjustment."));
+
+ // -------------------------------------------------------------
+
+ grid2->addMultiCellWidget(m_temperatureLabel, 0, 0, 0, 5);
+ grid2->addMultiCellWidget(m_adjTemperatureLabel, 1, 1, 0, 0);
+ grid2->addMultiCellWidget(m_pickTemperature, 1, 1, 1, 1);
+ grid2->addMultiCellWidget(m_temperatureInput, 1, 1, 2, 5);
+ grid2->addMultiCellWidget(m_temperaturePresetLabel, 2, 2, 0, 0);
+ grid2->addMultiCellWidget(m_temperaturePresetCB, 2, 2, 2, 5);
+
+ grid2->addMultiCellWidget(line, 3, 3, 0, 5);
+
+ grid2->addMultiCellWidget(m_blackLabel, 4, 4, 0, 0);
+ grid2->addMultiCellWidget(m_blackInput, 4, 4, 1, 5);
+ grid2->addMultiCellWidget(m_darkLabel, 5, 5, 0, 0);
+ grid2->addMultiCellWidget(m_darkInput, 5, 5, 1, 5);
+ grid2->addMultiCellWidget(m_saturationLabel, 6, 6, 0, 0);
+ grid2->addMultiCellWidget(m_saturationInput, 6, 6, 1, 5);
+ grid2->addMultiCellWidget(m_gammaLabel, 7, 7, 0, 0);
+ grid2->addMultiCellWidget(m_gammaInput, 7, 7, 1, 5);
+ grid2->addMultiCellWidget(m_greenLabel, 8, 8, 0, 0);
+ grid2->addMultiCellWidget(m_greenInput, 8, 8, 1, 5);
+
+ grid2->addMultiCellWidget(line2, 9, 9, 0, 5);
+
+ grid2->addMultiCellWidget(m_exposureLabel, 10, 10, 0, 5);
+ grid2->addMultiCellWidget(m_mainExposureLabel, 11, 11, 0, 0);
+ grid2->addMultiCellWidget(m_autoAdjustExposure, 11, 11, 1, 1);
+ grid2->addMultiCellWidget(m_mainExposureInput, 11, 11, 2, 5);
+ grid2->addMultiCellWidget(m_fineExposureLabel, 12, 12, 0, 1);
+ grid2->addMultiCellWidget(m_fineExposureInput, 12, 12, 2, 5);
+ grid2->setRowStretch(13, 10);
+ grid2->setMargin(m_gboxSettings->spacingHint());
+ grid2->setSpacing(m_gboxSettings->spacingHint());
+
+ setToolSettings(m_gboxSettings);
+ init();
+
+ // -------------------------------------------------------------
+
+ connect(m_channelCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotChannelChanged(int)));
+
+ connect(m_scaleBG, TQ_SIGNAL(released(int)),
+ this, TQ_SLOT(slotScaleChanged(int)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromOriginal(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotColorSelectedFromOriginal(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(spotPositionChangedFromTarget(const Digikam::DColor&, const TQPoint&)),
+ this, TQ_SLOT(slotColorSelectedFromTarget(const Digikam::DColor&)));
+
+ connect(m_previewWidget, TQ_SIGNAL(signalResized()),
+ this, TQ_SLOT(slotEffect()));
+
+ // -------------------------------------------------------------
+ // Correction Filter Slider controls.
+
+ connect(m_temperaturePresetCB, TQ_SIGNAL(activated(int)),
+ this, TQ_SLOT(slotTemperaturePresetChanged(int)));
+
+ connect(m_temperatureInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTemperatureChanged(double)));
+
+ connect(m_darkInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_blackInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_mainExposureInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_fineExposureInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_gammaInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_saturationInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ connect(m_greenInput, TQ_SIGNAL(valueChanged (double)),
+ this, TQ_SLOT(slotTimer()));
+
+ // -------------------------------------------------------------
+ // Bouttons slots.
+
+ connect(m_autoAdjustExposure, TQ_SIGNAL(clicked()),
+ this, TQ_SLOT(slotAutoAdjustExposure()));
+
+ connect(m_pickTemperature, TQ_SIGNAL(released()),
+ this, TQ_SLOT(slotPickerColorButtonActived()));
+}
+
+WhiteBalanceTool::~WhiteBalanceTool()
+{
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+}
+
+void WhiteBalanceTool::slotTemperatureChanged(double temperature)
+{
+ switch((uint)temperature)
+ {
+ case 1850:
+ m_temperaturePresetCB->setCurrentItem(Candle);
+ break;
+
+ case 2680:
+ m_temperaturePresetCB->setCurrentItem(Lamp40W);
+ break;
+
+ case 2800:
+ m_temperaturePresetCB->setCurrentItem(Lamp100W);
+ break;
+
+ case 3000:
+ m_temperaturePresetCB->setCurrentItem(Lamp200W);
+ break;
+
+ case 3200:
+ m_temperaturePresetCB->setCurrentItem(Sunrise);
+ break;
+
+ case 3400:
+ m_temperaturePresetCB->setCurrentItem(StudioLamp);
+ break;
+
+ case 4100:
+ m_temperaturePresetCB->setCurrentItem(MoonLight);
+ break;
+
+ case 4750:
+ m_temperaturePresetCB->setCurrentItem(Neutral);
+ break;
+
+ case 5000:
+ m_temperaturePresetCB->setCurrentItem(DaylightD50);
+ break;
+
+ case 5500:
+ m_temperaturePresetCB->setCurrentItem(Flash);
+ break;
+
+ case 5770:
+ m_temperaturePresetCB->setCurrentItem(Sun);
+ break;
+
+ case 6420:
+ m_temperaturePresetCB->setCurrentItem(XeonLamp);
+ break;
+
+ case 6500:
+ m_temperaturePresetCB->setCurrentItem(DaylightD65);
+ break;
+
+ default:
+ m_temperaturePresetCB->setCurrentItem(None);
+ break;
+ }
+
+ slotTimer();
+}
+
+void WhiteBalanceTool::slotTemperaturePresetChanged(int tempPreset)
+{
+ switch(tempPreset)
+ {
+ case Candle:
+ m_temperatureInput->setValue(1850.0);
+ break;
+
+ case Lamp40W:
+ m_temperatureInput->setValue(2680.0);
+ break;
+
+ case Lamp100W:
+ m_temperatureInput->setValue(2800.0);
+ break;
+
+ case Lamp200W:
+ m_temperatureInput->setValue(3000.0);
+ break;
+
+ case Sunrise:
+ m_temperatureInput->setValue(3200.0);
+ break;
+
+ case StudioLamp:
+ m_temperatureInput->setValue(3400.0);
+ break;
+
+ case MoonLight:
+ m_temperatureInput->setValue(4100.0);
+ break;
+
+ case Neutral:
+ m_temperatureInput->setValue(4750.0);
+ break;
+
+ case DaylightD50:
+ m_temperatureInput->setValue(5000.0);
+ break;
+
+ case Flash:
+ m_temperatureInput->setValue(5500.0);
+ break;
+
+ case Sun:
+ m_temperatureInput->setValue(5770.0);
+ break;
+
+ case XeonLamp:
+ m_temperatureInput->setValue(6420.0);
+ break;
+
+ case DaylightD65:
+ m_temperatureInput->setValue(6500.0);
+ break;
+
+ default: // None.
+ break;
+ }
+
+ slotEffect();
+}
+
+void WhiteBalanceTool::slotPickerColorButtonActived()
+{
+ // Save previous rendering mode and toggle to original image.
+ m_currentPreviewMode = m_previewWidget->getRenderingPreviewMode();
+ m_previewWidget->setRenderingPreviewMode(ImageGuideWidget::PreviewOriginalImage);
+}
+
+void WhiteBalanceTool::slotColorSelectedFromOriginal(const DColor &color)
+{
+ if ( m_pickTemperature->isOn() )
+ {
+ DColor dc = color;
+ TQColor tc = dc.getTQColor();
+ double temperatureLevel, greenLevel;
+
+ WhiteBalance::autoWBAdjustementFromColor(tc, temperatureLevel, greenLevel);
+
+ m_temperatureInput->setValue(temperatureLevel);
+ m_greenInput->setValue(greenLevel);
+ m_pickTemperature->setOn(false);
+ }
+ else
+ return;
+
+ // restore previous rendering mode.
+ m_previewWidget->setRenderingPreviewMode(m_currentPreviewMode);
+
+ slotEffect();
+}
+
+void WhiteBalanceTool::slotColorSelectedFromTarget(const DColor& color)
+{
+ m_histogramWidget->setHistogramGuideByColor(color);
+}
+
+void WhiteBalanceTool::slotScaleChanged(int scale)
+{
+ m_histogramWidget->m_scaleType = scale;
+ m_histogramWidget->repaint(false);
+}
+
+void WhiteBalanceTool::slotChannelChanged(int channel)
+{
+ switch(channel)
+ {
+ case LuminosityChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::ValueHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "white" ) );
+ break;
+
+ case RedChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::RedChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "red" ) );
+ break;
+
+ case GreenChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::GreenChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "green" ) );
+ break;
+
+ case BlueChannel:
+ m_histogramWidget->m_channelType = HistogramWidget::BlueChannelHistogram;
+ m_hGradient->setColors( TQColor( "black" ), TQColor( "blue" ) );
+ break;
+ }
+
+ m_histogramWidget->repaint(false);
+}
+
+void WhiteBalanceTool::slotAutoAdjustExposure()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int width = iface->originalWidth();
+ int height = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ double blackLevel;
+ double exposureLevel;
+
+ WhiteBalance::autoExposureAdjustement(data, width, height, sb, blackLevel, exposureLevel);
+ delete [] data;
+
+ m_blackInput->setValue(blackLevel);
+ m_mainExposureInput->setValue(exposureLevel);
+ m_fineExposureInput->setValue(0.0);
+
+ kapp->restoreOverrideCursor();
+ slotEffect();
+}
+
+void WhiteBalanceTool::slotEffect()
+{
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getPreviewImage();
+ int w = iface->previewWidth();
+ int h = iface->previewHeight();
+ bool sb = iface->previewSixteenBit();
+
+ // Create the new empty destination image data space.
+ m_histogramWidget->stopHistogramComputation();
+
+ if (m_destinationPreviewData)
+ delete [] m_destinationPreviewData;
+
+ m_destinationPreviewData = new uchar[w*h*(sb ? 8 : 4)];
+
+ double temperature = m_temperatureInput->value();
+ double dark = m_darkInput->value();
+ double black = m_blackInput->value();
+ double mainExposure = m_mainExposureInput->value();
+ double fineExposure = m_fineExposureInput->value();
+ double gamma = m_gammaInput->value();
+ double saturation = m_saturationInput->value();
+ double green = m_greenInput->value();
+
+ WhiteBalance wbFilter(sb);
+ wbFilter.whiteBalance(data, w, h, sb,
+ black, mainExposure + fineExposure,
+ temperature, green, dark,
+ gamma, saturation);
+
+ iface->putPreviewImage(data);
+ m_previewWidget->updatePreview();
+
+ // Update histogram.
+ memcpy (m_destinationPreviewData, data, w*h*(sb ? 8 : 4));
+ m_histogramWidget->updateData(m_destinationPreviewData, w, h, sb, 0, 0, 0, false);
+ delete [] data;
+}
+
+void WhiteBalanceTool::finalRendering()
+{
+ kapp->setOverrideCursor( KCursor::waitCursor() );
+ ImageIface* iface = m_previewWidget->imageIface();
+ uchar *data = iface->getOriginalImage();
+ int w = iface->originalWidth();
+ int h = iface->originalHeight();
+ bool sb = iface->originalSixteenBit();
+
+ double temperature = m_temperatureInput->value();
+ double dark = m_darkInput->value();
+ double black = m_blackInput->value();
+ double mainExposure = m_mainExposureInput->value();
+ double fineExposure = m_fineExposureInput->value();
+ double gamma = m_gammaInput->value();
+ double saturation = m_saturationInput->value();
+ double green = m_greenInput->value();
+
+ WhiteBalance wbFilter(sb);
+ wbFilter.whiteBalance(data, w, h, sb,
+ black, mainExposure + fineExposure,
+ temperature, green, dark,
+ gamma, saturation);
+
+ iface->putOriginalImage(i18n("White Balance"), data);
+ delete [] data;
+ kapp->restoreOverrideCursor();
+}
+
+void WhiteBalanceTool::slotResetSettings()
+{
+ m_blackInput->blockSignals(true);
+ m_darkInput->blockSignals(true);
+ m_fineExposureInput->blockSignals(true);
+ m_gammaInput->blockSignals(true);
+ m_greenInput->blockSignals(true);
+ m_mainExposureInput->blockSignals(true);
+ m_saturationInput->blockSignals(true);
+ m_temperatureInput->blockSignals(true);
+ m_temperaturePresetCB->blockSignals(true);
+
+ // Neutral color temperature settings is D65
+ m_blackInput->slotReset();
+ m_darkInput->slotReset();
+ m_fineExposureInput->slotReset();
+ m_gammaInput->slotReset();
+ m_greenInput->slotReset();
+ m_mainExposureInput->slotReset();
+ m_saturationInput->slotReset();
+ m_temperaturePresetCB->slotReset();
+ slotTemperaturePresetChanged(m_temperaturePresetCB->defaultItem());
+ m_temperatureInput->slotReset();
+
+ m_previewWidget->resetSpotPosition();
+ m_channelCB->setCurrentItem(LuminosityChannel);
+ slotChannelChanged(LuminosityChannel);
+
+ m_histogramWidget->reset();
+
+ m_blackInput->blockSignals(false);
+ m_darkInput->blockSignals(false);
+ m_fineExposureInput->blockSignals(false);
+ m_gammaInput->blockSignals(false);
+ m_greenInput->blockSignals(false);
+ m_mainExposureInput->blockSignals(false);
+ m_saturationInput->blockSignals(false);
+ m_temperatureInput->blockSignals(false);
+ m_temperaturePresetCB->blockSignals(false);
+
+ slotEffect();
+}
+
+void WhiteBalanceTool::readSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("whitebalance Tool");
+ m_channelCB->setCurrentItem(config->readNumEntry("Histogram Channel", 0)); // Luminosity.
+ m_scaleBG->setButton(config->readNumEntry("Histogram Scale", HistogramWidget::LogScaleHistogram));
+
+ m_darkInput->setValue(config->readDoubleNumEntry("Dark",m_darkInput->defaultValue()));
+ m_blackInput->setValue(config->readDoubleNumEntry("Black", m_blackInput->defaultValue()));
+ m_mainExposureInput->setValue(config->readDoubleNumEntry("MainExposure", m_mainExposureInput->defaultValue()));
+ m_fineExposureInput->setValue(config->readDoubleNumEntry("FineExposure", m_fineExposureInput->defaultValue()));
+ m_gammaInput->setValue(config->readDoubleNumEntry("Gamma", m_gammaInput->defaultValue()));
+ m_saturationInput->setValue(config->readDoubleNumEntry("Saturation", m_saturationInput->defaultValue()));
+ m_greenInput->setValue(config->readDoubleNumEntry("Green", m_greenInput->defaultValue()));
+ m_temperatureInput->setValue(config->readDoubleNumEntry("Temperature", m_temperatureInput->defaultValue()));
+
+ slotTemperatureChanged(m_temperatureInput->value());
+ m_histogramWidget->reset();
+ slotChannelChanged(m_channelCB->currentItem());
+ slotScaleChanged(m_scaleBG->selectedId());
+}
+
+void WhiteBalanceTool::writeSettings()
+{
+ TDEConfig* config = kapp->config();
+ config->setGroup("whitebalance Tool");
+ config->writeEntry("Histogram Channel", m_channelCB->currentItem());
+ config->writeEntry("Histogram Scale", m_scaleBG->selectedId());
+
+ config->writeEntry("Dark", m_darkInput->value());
+ config->writeEntry("Black", m_blackInput->value());
+ config->writeEntry("MainExposure", m_mainExposureInput->value());
+ config->writeEntry("FineExposure", m_fineExposureInput->value());
+ config->writeEntry("Gamma", m_gammaInput->value());
+ config->writeEntry("Saturation", m_saturationInput->value());
+ config->writeEntry("Green", m_greenInput->value());
+ config->writeEntry("Temperature", m_temperatureInput->value());
+ m_previewWidget->writeSettings();
+ config->sync();
+}
+
+void WhiteBalanceTool::slotLoadSettings()
+{
+ KURL loadWhiteBalanceFile = KFileDialog::getOpenURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("White Color Balance Settings File to Load")) );
+ if( loadWhiteBalanceFile.isEmpty() )
+ return;
+
+ TQFile file(loadWhiteBalanceFile.path());
+
+ if ( file.open(IO_ReadOnly) )
+ {
+ TQTextStream stream( &file );
+
+ if ( stream.readLine() != "# White Color Balance Configuration File V2" )
+ {
+ KMessageBox::error(kapp->activeWindow(),
+ i18n("\"%1\" is not a White Color Balance settings text file.")
+ .arg(loadWhiteBalanceFile.fileName()));
+ file.close();
+ return;
+ }
+
+ blockSignals(true);
+ m_temperatureInput->setValue( stream.readLine().toDouble() );
+ m_darkInput->setValue( stream.readLine().toDouble() );
+ m_blackInput->setValue( stream.readLine().toDouble() );
+ m_mainExposureInput->setValue( stream.readLine().toDouble() );
+ m_fineExposureInput->setValue( stream.readLine().toDouble() );
+ m_gammaInput->setValue( stream.readLine().toDouble() );
+ m_saturationInput->setValue( stream.readLine().toDouble() );
+ m_greenInput->setValue( stream.readLine().toDouble() );
+ m_histogramWidget->reset();
+ blockSignals(false);
+ slotEffect();
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot load settings from the White Color Balance text file."));
+
+ file.close();
+}
+
+void WhiteBalanceTool::slotSaveAsSettings()
+{
+ KURL saveWhiteBalanceFile = KFileDialog::getSaveURL(TDEGlobalSettings::documentPath(),
+ TQString( "*" ), kapp->activeWindow(),
+ TQString( i18n("White Color Balance Settings File to Save")) );
+ if( saveWhiteBalanceFile.isEmpty() )
+ return;
+
+ TQFile file(saveWhiteBalanceFile.path());
+
+ if ( file.open(IO_WriteOnly) )
+ {
+ TQTextStream stream( &file );
+ stream << "# White Color Balance Configuration File V2\n";
+ stream << m_temperatureInput->value() << "\n";
+ stream << m_darkInput->value() << "\n";
+ stream << m_blackInput->value() << "\n";
+ stream << m_mainExposureInput->value() << "\n";
+ stream << m_fineExposureInput->value() << "\n";
+ stream << m_gammaInput->value() << "\n";
+ stream << m_saturationInput->value() << "\n";
+ stream << m_greenInput->value() << "\n";
+ }
+ else
+ KMessageBox::error(kapp->activeWindow(), i18n("Cannot save settings to the White Color Balance text file."));
+
+ file.close();
+}
+
+} // NameSpace DigikamWhiteBalanceImagesPlugin
diff --git a/src/imageplugins/whitebalance/whitebalancetool.h b/src/imageplugins/whitebalance/whitebalancetool.h
new file mode 100644
index 00000000..2df2877e
--- /dev/null
+++ b/src/imageplugins/whitebalance/whitebalancetool.h
@@ -0,0 +1,174 @@
+/* ============================================================
+ *
+ * This file is a part of digiKam project
+ * http://www.digikam.org
+ *
+ * Date : 2005-03-11
+ * Description : a digiKam image editor plugin to correct
+ * image white balance
+ *
+ * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
+ * Copyright (C) 2008 by Guillaume Castagnino <casta at xwing dot info>
+ *
+ * This program is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation;
+ * either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ============================================================ */
+
+#ifndef WHITEBALANCETOOL_H
+#define WHITEBALANCETOOL_H
+
+// TQt includes.
+
+#include <tqcolor.h>
+
+// Digikam includes.
+
+#include "editortool.h"
+
+class TQComboBox;
+class TQPushButton;
+class TQLabel;
+class TQPushButton;
+class TQHButtonGroup;
+
+class KActiveLabel;
+
+namespace KDcrawIface
+{
+class RDoubleNumInput;
+class RComboBox;
+}
+
+namespace Digikam
+{
+class HistogramWidget;
+class ColorGradientWidget;
+class ImageWidget;
+class DColor;
+class EditorToolSettings;
+}
+
+namespace DigikamWhiteBalanceImagesPlugin
+{
+
+class WhiteBalanceTool : public Digikam::EditorTool
+{
+ TQ_OBJECT
+
+
+public:
+
+ WhiteBalanceTool(TQObject* parent);
+ ~WhiteBalanceTool();
+
+private:
+
+ void readSettings();
+ void writeSettings();
+ void finalRendering();
+
+private slots:
+
+ void slotSaveAsSettings();
+ void slotLoadSettings();
+ void slotEffect();
+ void slotResetSettings();
+ void slotColorSelectedFromOriginal(const Digikam::DColor &color);
+ void slotColorSelectedFromTarget(const Digikam::DColor &color);
+ void slotScaleChanged(int scale);
+ void slotChannelChanged(int channel);
+ void slotTemperatureChanged(double temperature);
+ void slotTemperaturePresetChanged(int tempPreset);
+ void slotAutoAdjustExposure(void);
+ void slotPickerColorButtonActived();
+
+private:
+
+ enum HistogramScale
+ {
+ Linear=0,
+ Logarithmic
+ };
+
+ enum ColorChannel
+ {
+ LuminosityChannel=0,
+ RedChannel,
+ GreenChannel,
+ BlueChannel
+ };
+
+ enum TemperaturePreset
+ {
+ Candle=0,
+ Lamp40W,
+ Lamp100W,
+ Lamp200W,
+ Sunrise,
+ StudioLamp,
+ MoonLight,
+ Neutral,
+ DaylightD50,
+ Flash,
+ Sun,
+ XeonLamp,
+ DaylightD65,
+ None
+ };
+
+ uchar *m_destinationPreviewData;
+
+ int m_currentPreviewMode;
+
+ TQComboBox *m_channelCB;
+
+ TQPushButton *m_pickTemperature;
+ TQPushButton *m_autoAdjustExposure;
+
+ KDcrawIface::RComboBox *m_temperaturePresetCB;
+
+ TQHButtonGroup *m_scaleBG;
+
+ TQLabel *m_adjTemperatureLabel;
+ TQLabel *m_temperaturePresetLabel;
+ TQLabel *m_darkLabel;
+ TQLabel *m_blackLabel;
+ TQLabel *m_mainExposureLabel;
+ TQLabel *m_fineExposureLabel;
+ TQLabel *m_gammaLabel;
+ TQLabel *m_saturationLabel;
+ TQLabel *m_greenLabel;
+
+ KActiveLabel *m_exposureLabel;
+ KActiveLabel *m_temperatureLabel;
+
+ KDcrawIface::RDoubleNumInput *m_temperatureInput;
+ KDcrawIface::RDoubleNumInput *m_darkInput;
+ KDcrawIface::RDoubleNumInput *m_blackInput;
+ KDcrawIface::RDoubleNumInput *m_mainExposureInput;
+ KDcrawIface::RDoubleNumInput *m_fineExposureInput;
+ KDcrawIface::RDoubleNumInput *m_gammaInput;
+ KDcrawIface::RDoubleNumInput *m_saturationInput;
+ KDcrawIface::RDoubleNumInput *m_greenInput;
+
+ Digikam::HistogramWidget *m_histogramWidget;
+
+ Digikam::ColorGradientWidget *m_hGradient;
+
+ Digikam::ImageWidget *m_previewWidget;
+
+ Digikam::EditorToolSettings *m_gboxSettings;
+};
+
+} // NameSpace DigikamWhiteBalanceImagesPlugin
+
+#endif /* WHITEBALANCETOOL_H */