2859 |
2860 |
2860 ^ |
2861 ^ |
2861 #(Menu |
2862 #(Menu |
2862 ( |
2863 ( |
2863 (MenuItem |
2864 (MenuItem |
2864 "/ enabled: imageIsLoadedAndAllowedToChangeImageDimensionAndDepth |
|
2865 enabled: imageIsLoaded |
2865 enabled: imageIsLoaded |
2866 label: 'Depth' |
2866 label: 'Depth' |
2867 translateLabel: true |
|
2868 submenu: |
2867 submenu: |
2869 (Menu |
2868 (Menu |
2870 ( |
2869 ( |
2871 (MenuItem |
2870 (MenuItem |
2872 activeHelpKey: colorMap1 |
2871 activeHelpKey: colorMap1 |
|
2872 enabled: imageIsLoadedAndNotReadonlyHolder |
2873 label: '1-Plane' |
2873 label: '1-Plane' |
2874 itemValue: colorMapMode: |
2874 itemValue: colorMapMode: |
2875 translateLabel: true |
|
2876 argument: depth1 |
2875 argument: depth1 |
2877 choice: colorMapMode |
2876 choice: colorMapMode |
2878 choiceValue: depth1 |
2877 choiceValue: depth1 |
2879 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2880 ) |
2878 ) |
2881 (MenuItem |
2879 (MenuItem |
2882 activeHelpKey: colorMap1M |
2880 activeHelpKey: colorMap1M |
|
2881 enabled: imageIsLoadedAndNotReadonlyHolder |
2883 label: '1-Plane + Mask' |
2882 label: '1-Plane + Mask' |
2884 itemValue: colorMapMode: |
2883 itemValue: colorMapMode: |
2885 translateLabel: true |
|
2886 argument: masked1 |
2884 argument: masked1 |
2887 choice: colorMapMode |
2885 choice: colorMapMode |
2888 choiceValue: masked1 |
2886 choiceValue: masked1 |
2889 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2890 ) |
2887 ) |
2891 (MenuItem |
2888 (MenuItem |
2892 label: '-' |
2889 label: '-' |
2893 ) |
2890 ) |
2894 (MenuItem |
2891 (MenuItem |
2895 activeHelpKey: colorMap2 |
2892 activeHelpKey: colorMap2 |
|
2893 enabled: imageIsLoadedAndNotReadonlyHolder |
2896 label: '2-Plane' |
2894 label: '2-Plane' |
2897 itemValue: colorMapMode: |
2895 itemValue: colorMapMode: |
2898 translateLabel: true |
|
2899 argument: depth2 |
2896 argument: depth2 |
2900 choice: colorMapMode |
2897 choice: colorMapMode |
2901 choiceValue: depth2 |
2898 choiceValue: depth2 |
2902 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2903 ) |
2899 ) |
2904 (MenuItem |
2900 (MenuItem |
2905 activeHelpKey: colorMap2M |
2901 activeHelpKey: colorMap2M |
|
2902 enabled: imageIsLoadedAndNotReadonlyHolder |
2906 label: '2-Plane + Mask' |
2903 label: '2-Plane + Mask' |
2907 itemValue: colorMapMode: |
2904 itemValue: colorMapMode: |
2908 translateLabel: true |
|
2909 argument: masked2 |
2905 argument: masked2 |
2910 choice: colorMapMode |
2906 choice: colorMapMode |
2911 choiceValue: masked2 |
2907 choiceValue: masked2 |
2912 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2913 ) |
2908 ) |
2914 (MenuItem |
2909 (MenuItem |
2915 label: '-' |
2910 label: '-' |
2916 ) |
2911 ) |
2917 (MenuItem |
2912 (MenuItem |
2918 activeHelpKey: colorMap4 |
2913 activeHelpKey: colorMap4 |
|
2914 enabled: imageIsLoadedAndNotReadonlyHolder |
2919 label: '4-Plane' |
2915 label: '4-Plane' |
2920 itemValue: colorMapMode: |
2916 itemValue: colorMapMode: |
2921 translateLabel: true |
|
2922 argument: depth4 |
2917 argument: depth4 |
2923 choice: colorMapMode |
2918 choice: colorMapMode |
2924 choiceValue: depth4 |
2919 choiceValue: depth4 |
2925 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2926 ) |
2920 ) |
2927 (MenuItem |
2921 (MenuItem |
2928 activeHelpKey: colorMap4M |
2922 activeHelpKey: colorMap4M |
|
2923 enabled: imageIsLoadedAndNotReadonlyHolder |
2929 label: '4-Plane + Mask' |
2924 label: '4-Plane + Mask' |
2930 itemValue: colorMapMode: |
2925 itemValue: colorMapMode: |
2931 translateLabel: true |
|
2932 argument: masked4 |
2926 argument: masked4 |
2933 choice: colorMapMode |
2927 choice: colorMapMode |
2934 choiceValue: masked4 |
2928 choiceValue: masked4 |
2935 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2936 ) |
2929 ) |
2937 (MenuItem |
2930 (MenuItem |
2938 label: '-' |
2931 label: '-' |
2939 ) |
2932 ) |
2940 (MenuItem |
2933 (MenuItem |
2941 activeHelpKey: colorMap8 |
2934 activeHelpKey: colorMap8 |
|
2935 enabled: imageIsLoadedAndNotReadonlyHolder |
2942 label: '8-Plane' |
2936 label: '8-Plane' |
2943 itemValue: colorMapMode: |
2937 itemValue: colorMapMode: |
2944 translateLabel: true |
|
2945 argument: depth8 |
2938 argument: depth8 |
2946 choice: colorMapMode |
2939 choice: colorMapMode |
2947 choiceValue: depth8 |
2940 choiceValue: depth8 |
2948 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2949 ) |
2941 ) |
2950 (MenuItem |
2942 (MenuItem |
2951 activeHelpKey: colorMap8M |
2943 activeHelpKey: colorMap8M |
|
2944 enabled: imageIsLoadedAndNotReadonlyHolder |
2952 label: '8-Plane + Mask' |
2945 label: '8-Plane + Mask' |
2953 itemValue: colorMapMode: |
2946 itemValue: colorMapMode: |
2954 translateLabel: true |
|
2955 argument: masked8 |
2947 argument: masked8 |
2956 choice: colorMapMode |
2948 choice: colorMapMode |
2957 choiceValue: masked8 |
2949 choiceValue: masked8 |
2958 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2959 ) |
2950 ) |
2960 (MenuItem |
2951 (MenuItem |
2961 label: '-' |
2952 label: '-' |
2962 ) |
2953 ) |
2963 (MenuItem |
2954 (MenuItem |
2964 activeHelpKey: colorMap16 |
2955 activeHelpKey: colorMap16 |
|
2956 enabled: imageIsLoadedAndNotReadonlyHolder |
2965 label: '16-Plane' |
2957 label: '16-Plane' |
2966 itemValue: colorMapMode: |
2958 itemValue: colorMapMode: |
2967 translateLabel: true |
|
2968 argument: depth16 |
2959 argument: depth16 |
2969 choice: colorMapMode |
2960 choice: colorMapMode |
2970 choiceValue: depth16 |
2961 choiceValue: depth16 |
2971 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2972 ) |
2962 ) |
2973 (MenuItem |
2963 (MenuItem |
2974 activeHelpKey: colorMap16M |
2964 activeHelpKey: colorMap16M |
|
2965 enabled: imageIsLoadedAndNotReadonlyHolder |
2975 label: '16-Plane + Mask' |
2966 label: '16-Plane + Mask' |
2976 itemValue: colorMapMode: |
2967 itemValue: colorMapMode: |
2977 translateLabel: true |
|
2978 argument: masked16 |
2968 argument: masked16 |
2979 choice: colorMapMode |
2969 choice: colorMapMode |
2980 choiceValue: masked16 |
2970 choiceValue: masked16 |
2981 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2982 ) |
2971 ) |
2983 (MenuItem |
2972 (MenuItem |
2984 label: '-' |
2973 label: '-' |
2985 ) |
2974 ) |
2986 (MenuItem |
2975 (MenuItem |
2987 activeHelpKey: colorMap24 |
2976 activeHelpKey: colorMap24 |
|
2977 enabled: imageIsLoadedAndNotReadonlyHolder |
2988 label: '24-Plane' |
2978 label: '24-Plane' |
2989 itemValue: colorMapMode: |
2979 itemValue: colorMapMode: |
2990 translateLabel: true |
|
2991 argument: depth24 |
2980 argument: depth24 |
2992 choice: colorMapMode |
2981 choice: colorMapMode |
2993 choiceValue: depth24 |
2982 choiceValue: depth24 |
2994 enabled: imageIsLoadedAndNotReadonlyHolder |
|
2995 ) |
2983 ) |
2996 (MenuItem |
2984 (MenuItem |
2997 activeHelpKey: colorMap24M |
2985 activeHelpKey: colorMap24M |
|
2986 enabled: imageIsLoadedAndNotReadonlyHolder |
2998 label: '24-Plane + Mask' |
2987 label: '24-Plane + Mask' |
2999 itemValue: colorMapMode: |
2988 itemValue: colorMapMode: |
3000 translateLabel: true |
|
3001 argument: masked24 |
2989 argument: masked24 |
3002 choice: colorMapMode |
2990 choice: colorMapMode |
3003 choiceValue: masked24 |
2991 choiceValue: masked24 |
3004 enabled: imageIsLoadedAndNotReadonlyHolder |
|
3005 ) |
2992 ) |
3006 (MenuItem |
2993 (MenuItem |
3007 label: '-' |
2994 label: '-' |
3008 ) |
2995 ) |
3009 (MenuItem |
2996 (MenuItem |
3010 activeHelpKey: colorMap32 |
2997 activeHelpKey: colorMap32 |
|
2998 enabled: imageIsLoadedAndNotReadonlyHolder |
3011 label: '32-Plane (rgba)' |
2999 label: '32-Plane (rgba)' |
3012 itemValue: colorMapMode: |
3000 itemValue: colorMapMode: |
3013 translateLabel: true |
|
3014 argument: depth32 |
3001 argument: depth32 |
3015 choice: colorMapMode |
3002 choice: colorMapMode |
3016 choiceValue: depth32 |
3003 choiceValue: depth32 |
3017 enabled: imageIsLoadedAndNotReadonlyHolder |
|
3018 ) |
3004 ) |
3019 ) |
3005 ) |
3020 nil |
3006 nil |
3021 nil |
3007 nil |
3022 ) |
3008 ) |
3023 ) |
3009 ) |
3024 (MenuItem |
3010 (MenuItem |
3025 enabled: imageIsLoadedAndNotReadonlyHolder |
3011 enabled: imageIsLoadedAndNotReadonlyHolder |
3026 label: 'ColorMap' |
3012 label: 'ColorMap' |
3027 translateLabel: true |
|
3028 submenu: |
3013 submenu: |
3029 (Menu |
3014 (Menu |
3030 ( |
3015 ( |
3031 (MenuItem |
3016 (MenuItem |
3032 activeHelpKey: compressColormap |
3017 activeHelpKey: compressColormap |
3033 enabled: hasColormapHolder |
3018 enabled: hasColormapHolder |
3034 label: 'Compress Colormap' |
3019 label: 'Compress Colormap' |
3035 itemValue: #'menu_compressColorMap' |
3020 itemValue: #'menu_compressColorMap' |
3036 translateLabel: true |
|
3037 ) |
3021 ) |
3038 (MenuItem |
3022 (MenuItem |
3039 enabled: hasColormapHolder |
3023 enabled: hasColormapHolder |
3040 label: 'Sort Colormap' |
3024 label: 'Sort Colormap' |
3041 itemValue: #'menu_sortColorMap' |
3025 itemValue: #'menu_sortColorMap' |
3042 translateLabel: true |
|
3043 ) |
3026 ) |
3044 (MenuItem |
3027 (MenuItem |
3045 label: 'Reduce Number of Colors by Rounding...' |
3028 label: 'Reduce Number of Colors by Rounding...' |
3046 itemValue: reduceNumberOfColors2 |
3029 itemValue: reduceNumberOfColors2 |
3047 translateLabel: true |
|
3048 ) |
3030 ) |
3049 (MenuItem |
3031 (MenuItem |
3050 label: 'Reduce Number of Colors by Masking Bits...' |
3032 label: 'Reduce Number of Colors by Masking Bits...' |
3051 itemValue: reduceNumberOfColors |
3033 itemValue: reduceNumberOfColors |
3052 translateLabel: true |
|
3053 ) |
|
3054 (MenuItem |
|
3055 label: '-' |
|
3056 ) |
|
3057 (MenuItem |
|
3058 enabled: imageIsLoadedHolder |
|
3059 label: 'Brighten' |
|
3060 itemValue: doBrightenImage |
|
3061 translateLabel: true |
|
3062 ) |
|
3063 (MenuItem |
|
3064 enabled: imageIsLoadedHolder |
|
3065 label: 'Darken' |
|
3066 itemValue: doDarkenImage |
|
3067 translateLabel: true |
|
3068 ) |
|
3069 (MenuItem |
|
3070 enabled: imageIsLoadedHolder |
|
3071 label: 'Invert' |
|
3072 itemValue: doNegativeImage |
|
3073 translateLabel: true |
|
3074 ) |
3034 ) |
3075 ) |
3035 ) |
3076 nil |
3036 nil |
3077 nil |
3037 nil |
3078 ) |
3038 ) |
3079 ) |
3039 ) |
3080 (MenuItem |
3040 (MenuItem |
3081 enabled: imageIsLoadedAndNotReadonlyHolder |
3041 enabled: imageIsLoadedAndNotReadonlyHolder |
3082 label: 'Process' |
3042 label: 'Process' |
3083 translateLabel: true |
|
3084 submenu: |
3043 submenu: |
3085 (Menu |
3044 (Menu |
3086 ( |
3045 ( |
3087 (MenuItem |
3046 (MenuItem |
3088 label: 'Make GrayScale' |
3047 label: 'Negative' |
3089 itemValue: makeGrayScaleImage |
3048 itemValue: makeNegative |
3090 translateLabel: true |
|
3091 ) |
3049 ) |
3092 (MenuItem |
3050 (MenuItem |
3093 label: 'Make Monochrome...' |
3051 label: 'Invert Pixel Bits' |
3094 itemValue: makeMonochromeImage |
3052 itemValue: makeInvertedBits |
3095 translateLabel: true |
3053 isVisible: hasColormap |
3096 ) |
|
3097 (MenuItem |
|
3098 label: 'Make Inverse' |
|
3099 itemValue: makeInverse |
|
3100 translateLabel: true |
|
3101 ) |
3054 ) |
3102 (MenuItem |
3055 (MenuItem |
3103 label: '-' |
3056 label: '-' |
3104 ) |
3057 ) |
3105 (MenuItem |
3058 (MenuItem |
3106 enabled: allowedToChangeImageDimensionAndDepth |
3059 enabled: allowedToChangeImageDimensionAndDepth |
3107 label: 'Make dithered 8Bit Palette' |
3060 label: 'Make dithered 8Bit Palette' |
3108 itemValue: makeDitheredPaletteImage |
3061 itemValue: makeDitheredPaletteImage |
3109 translateLabel: true |
|
3110 isVisible: false |
3062 isVisible: false |
3111 ) |
3063 ) |
3112 (MenuItem |
3064 (MenuItem |
3113 label: 'Dither to Depth...' |
3065 label: 'Dither to Depth...' |
3114 itemValue: ditherToDepth |
3066 itemValue: ditherToDepth |
3115 translateLabel: true |
|
3116 ) |
3067 ) |
3117 (MenuItem |
3068 (MenuItem |
3118 label: 'Threshold to Depth...' |
3069 label: 'Threshold to Depth...' |
3119 itemValue: thresholdToDepth |
3070 itemValue: thresholdToDepth |
3120 translateLabel: true |
3071 ) |
|
3072 (MenuItem |
|
3073 label: '-' |
|
3074 ) |
|
3075 (MenuItem |
|
3076 label: 'Make Monochrome...' |
|
3077 itemValue: makeMonochromeImage |
|
3078 ) |
|
3079 (MenuItem |
|
3080 label: 'Make GrayScale (same Depth)' |
|
3081 itemValue: makeGrayScaleImage |
3121 ) |
3082 ) |
3122 (MenuItem |
3083 (MenuItem |
3123 label: 'Make GrayScale with Depth (Dither)...' |
3084 label: 'Make GrayScale with Depth (Dither)...' |
3124 itemValue: ditherGrayToDepth |
3085 itemValue: ditherGrayToDepth |
3125 translateLabel: true |
|
3126 ) |
3086 ) |
3127 (MenuItem |
3087 (MenuItem |
3128 label: 'Make GrayScale with Depth (Threshold)...' |
3088 label: 'Make GrayScale with Depth (Threshold)...' |
3129 itemValue: thresholdGrayToDepth |
3089 itemValue: thresholdGrayToDepth |
3130 translateLabel: true |
|
3131 ) |
3090 ) |
3132 (MenuItem |
3091 (MenuItem |
3133 label: '-' |
3092 label: '-' |
3134 ) |
3093 ) |
3135 (MenuItem |
3094 (MenuItem |
3136 label: 'Make Slightly Brighter' |
3095 label: 'Make Slightly Brighter' |
3137 itemValue: makeSlightlyBrighter |
3096 itemValue: makeSlightlyBrighter |
3138 translateLabel: true |
3097 ) |
|
3098 (MenuItem |
|
3099 label: 'Make Brighter' |
|
3100 itemValue: makeBrighter |
3139 ) |
3101 ) |
3140 (MenuItem |
3102 (MenuItem |
3141 label: 'Make Slightly Darker' |
3103 label: 'Make Slightly Darker' |
3142 itemValue: makeSlightlyDarker |
3104 itemValue: makeSlightlyDarker |
3143 translateLabel: true |
|
3144 ) |
|
3145 (MenuItem |
|
3146 label: '-' |
|
3147 ) |
|
3148 (MenuItem |
|
3149 label: 'Make Brighter' |
|
3150 itemValue: makeBrighter |
|
3151 translateLabel: true |
|
3152 ) |
3105 ) |
3153 (MenuItem |
3106 (MenuItem |
3154 label: 'Make Darker' |
3107 label: 'Make Darker' |
3155 itemValue: makeDarker |
3108 itemValue: makeDarker |
3156 translateLabel: true |
|
3157 ) |
3109 ) |
3158 (MenuItem |
3110 (MenuItem |
3159 label: '-' |
3111 label: '-' |
3160 ) |
3112 ) |
3161 (MenuItem |
3113 (MenuItem |
3162 label: 'Change HLS...' |
3114 label: 'Change HLS...' |
3163 itemValue: changeHLS |
3115 itemValue: changeHLS |
3164 translateLabel: true |
|
3165 ) |
3116 ) |
3166 (MenuItem |
3117 (MenuItem |
3167 label: 'Colorize...' |
3118 label: 'Colorize...' |
3168 itemValue: colorize |
3119 itemValue: colorize |
3169 translateLabel: true |
3120 ) |
|
3121 (MenuItem |
|
3122 enabled: imageIsLoadedHolder |
|
3123 label: 'Brighten' |
|
3124 itemValue: doBrightenImage |
|
3125 ) |
|
3126 (MenuItem |
|
3127 enabled: imageIsLoadedHolder |
|
3128 label: 'Darken' |
|
3129 itemValue: doDarkenImage |
3170 ) |
3130 ) |
3171 ) |
3131 ) |
3172 nil |
3132 nil |
3173 nil |
3133 nil |
3174 ) |
3134 ) |
3175 ) |
3135 ) |
3176 (MenuItem |
3136 (MenuItem |
3177 enabled: imageIsLoadedAndNotReadonlyHolder |
3137 enabled: imageIsLoadedAndNotReadonlyHolder |
3178 label: 'Mask' |
3138 label: 'Mask' |
3179 translateLabel: true |
|
3180 submenu: |
3139 submenu: |
3181 (Menu |
3140 (Menu |
3182 ( |
3141 ( |
3183 (MenuItem |
3142 (MenuItem |
3184 activeHelpKey: copyMask |
3143 activeHelpKey: copyMask |
3185 enabled: hasMask |
3144 enabled: hasMask |
3186 label: 'Copy Mask' |
3145 label: 'Copy Mask' |
3187 itemValue: #'menu_copyMask' |
3146 itemValue: #'menu_copyMask' |
3188 translateLabel: true |
|
3189 ) |
3147 ) |
3190 (MenuItem |
3148 (MenuItem |
3191 activeHelpKey: pasteMask |
3149 activeHelpKey: pasteMask |
3192 enabled: hasMask |
3150 enabled: hasMask |
3193 label: 'Paste Mask' |
3151 label: 'Paste Mask' |
3194 itemValue: #'menu_pasteMask' |
3152 itemValue: #'menu_pasteMask' |
3195 translateLabel: true |
|
3196 ) |
3153 ) |
3197 (MenuItem |
3154 (MenuItem |
3198 enabled: hasMask |
3155 enabled: hasMask |
3199 label: 'Clear Masked Pixels' |
3156 label: 'Clear Masked Pixels' |
3200 itemValue: #'menu_clearMaskedPixels' |
3157 itemValue: #'menu_clearMaskedPixels' |
3201 translateLabel: true |
|
3202 ) |
3158 ) |
3203 (MenuItem |
3159 (MenuItem |
3204 enabled: hasMask |
3160 enabled: hasMask |
3205 label: 'Clear Colormap Entry for Masked Pixels' |
3161 label: 'Clear Colormap Entry for Masked Pixels' |
3206 itemValue: #'menu_clearColormapEntry0AndMaskedPixels' |
3162 itemValue: #'menu_clearColormapEntry0AndMaskedPixels' |
3207 translateLabel: true |
|
3208 ) |
3163 ) |
3209 ) |
3164 ) |
3210 nil |
3165 nil |
3211 nil |
3166 nil |
3212 ) |
3167 ) |
7371 |
7375 |
7372 (imageEditView image:newImage) notNil ifTrue:[ |
7376 (imageEditView image:newImage) notNil ifTrue:[ |
7373 self fetchImageData. |
7377 self fetchImageData. |
7374 ] |
7378 ] |
7375 |
7379 |
7376 "Modified: / 15.9.1998 / 17:53:32 / cg" |
7380 "Modified: / 15-09-1998 / 17:53:32 / cg" |
7377 "Created: / 30.9.1998 / 23:51:23 / cg" |
7381 "Created: / 30-09-1998 / 23:51:23 / cg" |
|
7382 "Modified (comment): / 31-08-2017 / 14:19:21 / cg" |
|
7383 ! |
|
7384 |
|
7385 updateImageAfterDoing:aBlockOrSelector |
|
7386 self withExecuteCursorDo:[ |
|
7387 aBlockOrSelector value:imageEditView. |
|
7388 self updateImage. |
|
7389 ]. |
|
7390 |
|
7391 "Created: / 31-08-2017 / 12:14:39 / cg" |
|
7392 ! ! |
|
7393 |
|
7394 !ImageEditor methodsFor:'user actions-colormap-basic'! |
|
7395 |
|
7396 nonUndoableClearColormapEntry0AndMaskedPixels |
|
7397 "ensure that there is a colorMap entry with 0/0/0 at position |
|
7398 0 and then clear all masked pixels (to pixelValue 0). |
|
7399 This is required for windows icons to be really transparent" |
|
7400 |
|
7401 |index colorMap| |
|
7402 |
|
7403 self nonUndoableCompressColorMap. |
|
7404 |
|
7405 colorMap := self image colorMap. |
|
7406 (colorMap includes:(Color black)) ifFalse:[ |
|
7407 self addColorToColormap:(Color black) undoable:false. |
|
7408 colorMap := self image colorMap. |
|
7409 ]. |
|
7410 index := colorMap indexOf:(Color black). |
|
7411 index == 1 ifFalse:[ |
|
7412 self nonUndoableSortColorMapWith:self sortBlockForColorsByRGB. |
|
7413 colorMap := self image colorMap. |
|
7414 ]. |
|
7415 self nonUndoableClearMaskedPixels |
|
7416 |
|
7417 "Created: / 31-08-2017 / 14:31:09 / cg" |
|
7418 ! |
|
7419 |
|
7420 nonUndoableClearMaskedPixels |
|
7421 "clear all masked pixels (to pixelValue 0)" |
|
7422 |
|
7423 |newImage| |
|
7424 |
|
7425 newImage := self image clearMaskedPixels. |
|
7426 0 to:newImage height - 1 do:[:y | |
|
7427 0 to:newImage width - 1 do:[:x | |
|
7428 (newImage maskAtX:x y:y) == 0 ifTrue:[ |
|
7429 newImage pixelAtX:x y:y put:0 |
|
7430 ] |
|
7431 ] |
|
7432 ]. |
|
7433 |
|
7434 (imageEditView image:newImage) notNil ifTrue:[ |
|
7435 self fetchImageData. |
|
7436 ] |
|
7437 |
|
7438 "Created: / 31-08-2017 / 14:22:58 / cg" |
|
7439 ! |
|
7440 |
|
7441 nonUndoableCompressColorMap |
|
7442 "not undoable |
|
7443 calculates a new color map for the image, using only used colors" |
|
7444 |
|
7445 |newImage| |
|
7446 |
|
7447 newImage := self image. |
|
7448 newImage compressColorMap. |
|
7449 |
|
7450 (imageEditView image:newImage) notNil ifTrue:[ |
|
7451 self fetchImageData. |
|
7452 ] |
|
7453 |
|
7454 "Created: / 31-08-2017 / 14:21:51 / cg" |
|
7455 ! |
|
7456 |
|
7457 nonUndoableSortColorMapWith:sortBlock |
|
7458 "not undoable |
|
7459 calculates a new color map for the image, sorting colors" |
|
7460 |
|
7461 |depth newColorMap newImage oldImage usedColors oldToNew oldBits newBits tmpBits |
|
7462 expectedSize w h| |
|
7463 |
|
7464 oldImage := self image. |
|
7465 depth := oldImage depth. |
|
7466 w := oldImage width. |
|
7467 h := oldImage height. |
|
7468 |
|
7469 usedColors := oldImage realColorMap. |
|
7470 |
|
7471 "/ translation table |
|
7472 oldToNew := ByteArray new:(1 bitShift:depth). |
|
7473 newColorMap := usedColors asArray. |
|
7474 newColorMap sort:sortBlock. |
|
7475 |
|
7476 oldImage colorMap asArray keysAndValuesDo:[:oldIdx :clr | |
|
7477 |newPixel| |
|
7478 |
|
7479 (usedColors includes:clr) ifTrue:[ |
|
7480 newPixel := newColorMap indexOf:clr. |
|
7481 oldToNew at:oldIdx put:newPixel-1. |
|
7482 ] |
|
7483 ]. |
|
7484 |
|
7485 oldBits := oldImage bits. |
|
7486 "/ sanity check... |
|
7487 expectedSize := ((w * h * depth + 7) // 8). |
|
7488 (oldBits size < expectedSize) ifTrue:[ |
|
7489 self halt:'incorrect pixeldata size'. |
|
7490 oldBits := (ByteArray new:expectedSize) replaceFrom:1 with:oldBits; yourself. |
|
7491 ]. |
|
7492 newBits := ByteArray new:(oldBits size). |
|
7493 depth ~~ 8 ifTrue:[ |
|
7494 |
|
7495 "/ expand/compress can only handle 8bits |
|
7496 tmpBits := ByteArray uninitializedNew:(w*h). |
|
7497 oldBits |
|
7498 expandPixels:depth |
|
7499 width:w height:h |
|
7500 into:tmpBits |
|
7501 mapping:oldToNew. |
|
7502 tmpBits |
|
7503 compressPixels:depth |
|
7504 width:w height:h |
|
7505 into:newBits |
|
7506 mapping:nil |
|
7507 ] ifFalse:[ |
|
7508 oldBits |
|
7509 expandPixels:depth |
|
7510 width:w height:h |
|
7511 into:newBits |
|
7512 mapping:oldToNew. |
|
7513 ]. |
|
7514 |
|
7515 newImage := oldImage species new |
|
7516 width:w height:h depth:depth |
|
7517 fromArray:newBits. |
|
7518 |
|
7519 newImage colorMap:newColorMap. |
|
7520 newImage fileName:oldImage fileName. |
|
7521 newImage mask:(oldImage mask copy). |
|
7522 |
|
7523 (imageEditView image:newImage) notNil ifTrue:[ |
|
7524 self fetchImageData. |
|
7525 ] |
|
7526 |
|
7527 "Created: / 31-08-2017 / 14:19:42 / cg" |
7378 ! ! |
7528 ! ! |
7379 |
7529 |
7380 !ImageEditor methodsFor:'user actions-editing'! |
7530 !ImageEditor methodsFor:'user actions-editing'! |
7381 |
7531 |
7382 autoCropAll |
7532 autoCropAll |
7421 imageEditView autoCropLeft:false right:false top:true bottom:false. |
7571 imageEditView autoCropLeft:false right:false top:true bottom:false. |
7422 self updateInfoLabel |
7572 self updateInfoLabel |
7423 |
7573 |
7424 "Created: / 20-02-2017 / 18:06:03 / cg" |
7574 "Created: / 20-02-2017 / 18:06:03 / cg" |
7425 ! |
7575 ! |
|
7576 |
|
7577 ditherGrayToDepth |
|
7578 self askForDepthThenDo:[:depth | |
|
7579 self ditherGrayToDepth:depth |
|
7580 ]. |
|
7581 |
|
7582 "Created: / 24-08-2017 / 17:49:42 / cg" |
|
7583 ! |
|
7584 |
|
7585 ditherGrayToDepth:depth |
|
7586 self withExecuteCursorDo:[ |
|
7587 |newImage| |
|
7588 |
|
7589 depth == 1 ifTrue:[ |
|
7590 newImage := self image asErrorDitheredMonochromeImage |
|
7591 ] ifFalse:[ |
|
7592 newImage := self image asGrayImageDepth:depth dither:#floydSteinberg. |
|
7593 ]. |
|
7594 imageEditView newImageWithUndo:newImage. |
|
7595 ]. |
|
7596 |
|
7597 "Created: / 24-08-2017 / 17:51:07 / cg" |
|
7598 "Modified: / 30-08-2017 / 01:18:43 / cg" |
|
7599 ! |
|
7600 |
|
7601 ditherToDepth |
|
7602 self askForDepthThenDo:[:depth | |
|
7603 self convertToDepth:depth dither:true |
|
7604 ]. |
|
7605 |
|
7606 "Created: / 07-07-2006 / 13:22:10 / cg" |
|
7607 "Modified: / 30-08-2017 / 00:34:42 / cg" |
|
7608 ! |
|
7609 |
|
7610 do3DProjection |
|
7611 "make a naive 3D projection; |
|
7612 can be used to create those typical marketing images as seen in web pages" |
|
7613 |
|
7614 |box dx1 dx2 image| |
|
7615 |
|
7616 image := imageEditView image. |
|
7617 |
|
7618 box := EnterBox new. |
|
7619 box title:(resources string:'dX1 (0 < dx < 0.5):'). |
|
7620 box okText:(resources string:'OK'). |
|
7621 box abortText:(resources string:'Cancel'). |
|
7622 box initialText:'0.1'. |
|
7623 box showAtPointer. |
|
7624 |
|
7625 (box accepted |
|
7626 and: [(dx1 := Number readFrom:(box contents) onError:nil) notNil]) |
|
7627 ifTrue:[ |
|
7628 box title:(resources string:'dX2 (0 < dx < 0.5):'). |
|
7629 box initialText:(dx1 printString). |
|
7630 box showAtPointer. |
|
7631 (box accepted |
|
7632 and: [(dx2 := Number readFrom:(box contents) onError:nil) notNil]) |
|
7633 ifTrue:[ |
|
7634 imageEditView threeDProjection:dx1 and:dx2. |
|
7635 ] |
|
7636 ]. |
|
7637 |
|
7638 self updateInfoLabel |
|
7639 |
|
7640 "Modified (comment): / 31-08-2017 / 13:58:03 / cg" |
|
7641 ! |
|
7642 |
|
7643 doBrightenImage |
|
7644 imageEditView brightenImage. |
|
7645 self listOfColors removeAll. |
|
7646 self findColorMapMode. |
|
7647 "/ imageEditView removelastUndo |
|
7648 ! |
|
7649 |
|
7650 doBrowseClass |
|
7651 "opens a System Browser on the resourceClass and the resourceSelector" |
|
7652 |
|
7653 |cls| |
|
7654 |
|
7655 cls := imageEditView resourceClass. |
|
7656 cls isNil ifTrue:[^ self warn:'No Class specified']. |
|
7657 |
|
7658 cls browserClass |
|
7659 openInClass:cls class |
|
7660 selector:(imageEditView resourceSelector) |
|
7661 |
|
7662 "Modified: / 31.7.1998 / 02:01:15 / cg" |
|
7663 ! |
|
7664 |
|
7665 doCopyImageToClipboard |
|
7666 imageEditView copyImageToClipboard. |
|
7667 ! |
|
7668 |
|
7669 doCropManual |
|
7670 "let user specify borders and cut them off" |
|
7671 |
|
7672 |bindings left top right bottom img firstChange cropAction acceptChannel| |
|
7673 |
|
7674 acceptChannel := TriggerValue new. |
|
7675 |
|
7676 firstChange := true. |
|
7677 |
|
7678 cropAction := |
|
7679 [:lV :rV :tV :bV | |l r t b| |
|
7680 acceptChannel value:true. |
|
7681 |
|
7682 l := lV value. |
|
7683 r := rV value. |
|
7684 t := tV value. |
|
7685 b := bV value. |
|
7686 (l + r + t + b) == 0 ifTrue:[ |
|
7687 UserPreferences current beepInEditor ifTrue:[ |
|
7688 self window beep |
|
7689 ] |
|
7690 ] ifFalse:[ |
|
7691 img := imageEditView image. |
|
7692 firstChange ifTrue:[ |
|
7693 imageEditView makeUndo. |
|
7694 firstChange := false. |
|
7695 ]. |
|
7696 imageEditView |
|
7697 makeSubImageX:l y:t |
|
7698 width:(img width - l - r) |
|
7699 height:(img height - t - b). |
|
7700 |
|
7701 self updateImagePreView. |
|
7702 self updateInfoLabel |
|
7703 ]. |
|
7704 ]. |
|
7705 |
|
7706 bindings := IdentityDictionary new. |
|
7707 bindings at:#cropLeftAmount put:(left := 1 asValue). |
|
7708 bindings at:#cropRightAmount put:(right := 1 asValue). |
|
7709 bindings at:#cropTopAmount put:(top := 1 asValue). |
|
7710 bindings at:#cropBottomAmount put:(bottom := 1 asValue). |
|
7711 bindings at:#acceptChannel put:acceptChannel. |
|
7712 |
|
7713 bindings at:#cropLeftNow put:[ cropAction value:left value:0 value:0 value:0 ]. |
|
7714 bindings at:#cropRightNow put:[ cropAction value:0 value:right value:0 value:0 ]. |
|
7715 bindings at:#cropTopNow put:[ cropAction value:0 value:0 value:top value:0 ]. |
|
7716 bindings at:#cropBottomNow put:[ cropAction value:0 value:0 value:0 value:bottom ]. |
|
7717 |
|
7718 bindings at:#applyCropAction put:[ cropAction value:left value:right value:top value:bottom ]. |
|
7719 bindings at:#cropBoxIsDialog put:true. |
|
7720 |
|
7721 (self openDialogInterface:#cropSpec withBindings:bindings) |
|
7722 ifFalse:[ |
|
7723 firstChange ~~ true ifTrue:[ |
|
7724 imageEditView undo. |
|
7725 self updateImagePreView. |
|
7726 ] |
|
7727 ]. |
|
7728 |
|
7729 "Created: / 07-09-1998 / 18:16:07 / cg" |
|
7730 "Modified: / 19-02-2017 / 15:43:50 / cg" |
|
7731 ! |
|
7732 |
|
7733 doDarkenImage |
|
7734 imageEditView darkenImage. |
|
7735 self listOfColors removeAll. |
|
7736 self findColorMapMode. |
|
7737 "/ imageEditView removelastUndo |
|
7738 ! |
|
7739 |
|
7740 doEditMask |
|
7741 |mask| |
|
7742 |
|
7743 (mask := self image mask) notNil ifTrue:[ |
|
7744 mask edit |
|
7745 ]. |
|
7746 |
|
7747 "Modified: / 18-02-2017 / 00:38:51 / cg" |
|
7748 ! |
|
7749 |
|
7750 doFlipHorizontal |
|
7751 "flips horizontally current image" |
|
7752 |
|
7753 imageEditView flipHorizontal |
|
7754 ! |
|
7755 |
|
7756 doFlipVertical |
|
7757 "flips vertically current image" |
|
7758 |
|
7759 imageEditView flipVertical |
|
7760 ! |
|
7761 |
|
7762 doInsertTextFromUser |
|
7763 |text tempForm tempImage maskImage font w h paintColor| |
|
7764 |
|
7765 text := Dialog request:'Text to be inserted (placed as bitmap into clipboard for paste):'. |
|
7766 text isEmptyOrNil ifTrue:[^ self ]. |
|
7767 |
|
7768 font := Font family:'arial' size:20. |
|
7769 font := font onDevice:Screen current. |
|
7770 w := font widthOf:text. |
|
7771 h := font heightOf:text. |
|
7772 |
|
7773 tempForm := Form extent:(w@h) depth:1 onDevice:(Screen current). |
|
7774 tempForm clear. |
|
7775 tempForm font:font. |
|
7776 tempForm paint:(Color colorId:1). |
|
7777 tempForm displayString:text at:(0@font ascent). |
|
7778 |
|
7779 tempImage := tempForm asImage. |
|
7780 maskImage := tempForm asImage. |
|
7781 |
|
7782 paintColor := imageEditView selectedColor. |
|
7783 paintColor colorId == 0 ifTrue:[ |
|
7784 paintColor := Color black |
|
7785 ]. |
|
7786 tempImage |
|
7787 photometric:#palette; |
|
7788 colorMap:(Array |
|
7789 with:Color white |
|
7790 with:paintColor); |
|
7791 mask:maskImage. |
|
7792 |
|
7793 ImageEditView copyImageToClipboard:tempImage. |
|
7794 self editMode value:#paste. |
|
7795 |
|
7796 "Modified: / 11-11-2007 / 12:32:55 / cg" |
|
7797 ! |
|
7798 |
|
7799 doInspectImage |
|
7800 "opens a System Browser on the resourceClass and the resourceSelector" |
|
7801 |
|
7802 self image inspect |
|
7803 ! |
|
7804 |
|
7805 doInvertedBitsImage |
|
7806 "inverts the pixels" |
|
7807 |
|
7808 self withExecuteCursorDo:[ |
|
7809 imageEditView makeInvertedBits. |
|
7810 self updateImage. |
|
7811 ]. |
|
7812 "/ |
|
7813 "/ imageEditView negativeImage. |
|
7814 "/ self listOfColors removeAll. |
|
7815 "/ self findColorMapMode. |
|
7816 "/ "/ imageEditView removelastUndo |
|
7817 "/ |
|
7818 "/ |
|
7819 |
|
7820 "Created: / 31-08-2017 / 12:49:13 / cg" |
|
7821 ! |
|
7822 |
|
7823 doMagnifyDown |
|
7824 "magnifies the current image one step down" |
|
7825 |
|
7826 |magHolder mag| |
|
7827 |
|
7828 magHolder := self magnificationHolder. |
|
7829 (mag := magHolder value) > 1 ifTrue: [ |
|
7830 magHolder value: mag - 1 |
|
7831 ] |
|
7832 |
|
7833 "Modified: / 26.7.1998 / 20:24:08 / cg" |
|
7834 ! |
|
7835 |
|
7836 doMagnifyImage |
|
7837 "magnifies the current image to a new size" |
|
7838 |
|
7839 |box newSize image antiAliased| |
|
7840 |
|
7841 antiAliased := false asValue. |
|
7842 image := imageEditView image. |
|
7843 |
|
7844 box := EnterBox new. |
|
7845 box title:(resources string:'Images new size:'). |
|
7846 box okText:(resources string:'OK'). |
|
7847 box abortText:(resources string:'Cancel'). |
|
7848 box initialText:image extent printString. |
|
7849 box verticalPanel add:(CheckBox label:(resources string:'Antialias/Smooth') model:antiAliased). |
|
7850 box showAtPointer. |
|
7851 |
|
7852 (box accepted |
|
7853 and: [(newSize := self pointFromString:(box contents)) notNil]) |
|
7854 ifTrue:[ |
|
7855 newSize isPoint ifFalse:[ |
|
7856 self warn:'Please enter the new size as ''x @ y''.'. |
|
7857 ^ self. |
|
7858 ]. |
|
7859 antiAliased value ifTrue:[ |
|
7860 ((newSize x < image width) or:[(newSize y < image height)]) ifTrue:[ |
|
7861 imageEditView magnifySmoothingTo:newSize. |
|
7862 ] ifFalse:[ |
|
7863 imageEditView magnifyAntiAliasedImageTo:newSize. |
|
7864 ]. |
|
7865 ] ifFalse:[ |
|
7866 imageEditView magnifyImageTo:newSize. |
|
7867 ]. |
|
7868 ]. |
|
7869 |
|
7870 self updateInfoLabel |
|
7871 |
|
7872 "Modified: / 30-08-2017 / 15:46:02 / cg" |
|
7873 ! |
|
7874 |
|
7875 doMagnifyImageBy |
|
7876 "magnifies the current image (by a scale)" |
|
7877 |
|
7878 |oldSize newSize scaleString scale image antiAliased smoothing| |
|
7879 |
|
7880 image := imageEditView image. |
|
7881 oldSize := image extent. |
|
7882 |
|
7883 antiAliased := false asValue. |
|
7884 smoothing := false asValue. |
|
7885 |
|
7886 Dialog modifyingBoxWith:[:box | |
|
7887 box verticalPanel add:(CheckBox label:(resources string:'Antialias/Smooth') model:antiAliased). |
|
7888 "/ box verticalPanel add:(CheckBox label:(resources string:'Smoothing') model:smoothing). |
|
7889 ] do:[ |
|
7890 scaleString := Dialog |
|
7891 request:(resources string:'Scale factor (<1 to shrink; >1 to magnify):') |
|
7892 initialAnswer:'1' |
|
7893 list:#('0.1' '0.25' '0.3' '0.5' '1.5' '2' '3' '4'). |
|
7894 ]. |
|
7895 scaleString isNil ifTrue:[^ self]. |
|
7896 |
|
7897 scale := Object readFromString:scaleString onError:nil. |
|
7898 |
|
7899 scale notNil ifTrue:[ |
|
7900 scale isNumber ifFalse:[ |
|
7901 self warn:'please enter a scale factor (<1 to shrink; >1 to magnify).'. |
|
7902 ^ self. |
|
7903 ]. |
|
7904 newSize := oldSize * scale. |
|
7905 antiAliased value ifTrue:[ |
|
7906 scale < 1 ifTrue:[ |
|
7907 imageEditView magnifySmoothingBy:scale. |
|
7908 ] ifFalse:[ |
|
7909 imageEditView magnifyAntiAliasedImageTo:newSize. |
|
7910 ]. |
|
7911 ] ifFalse:[ |
|
7912 imageEditView magnifyImageTo:newSize. |
|
7913 ]. |
|
7914 ]. |
|
7915 |
|
7916 self updateInfoLabel |
|
7917 |
|
7918 "Modified: / 30-08-2017 / 15:34:56 / cg" |
|
7919 ! |
|
7920 |
|
7921 doMagnifyUp |
|
7922 "magnifies the current image one step up" |
|
7923 |
|
7924 |magHolder mag| |
|
7925 |
|
7926 magHolder := self magnificationHolder. |
|
7927 (mag := magHolder value) < 63 ifTrue: [ |
|
7928 magHolder value: mag + 1 |
|
7929 ] |
|
7930 |
|
7931 "Modified: / 26.7.1998 / 20:23:52 / cg" |
|
7932 ! |
|
7933 |
|
7934 doNegativeImage |
|
7935 "negates current image by negating the color map" |
|
7936 |
|
7937 self withExecuteCursorDo:[ |
|
7938 imageEditView negativeImage. |
|
7939 self updateImage. |
|
7940 ]. |
|
7941 "/ |
|
7942 "/ imageEditView negativeImage. |
|
7943 "/ self listOfColors removeAll. |
|
7944 "/ self findColorMapMode. |
|
7945 "/ "/ imageEditView removelastUndo |
|
7946 "/ |
|
7947 "/ |
|
7948 |
|
7949 "Modified: / 31-08-2017 / 12:44:25 / cg" |
|
7950 ! |
|
7951 |
|
7952 doResizeImage |
|
7953 "resizes the current image" |
|
7954 |
|
7955 |box newSize image| |
|
7956 |
|
7957 image := imageEditView image. |
|
7958 |
|
7959 box := EnterBox new. |
|
7960 box title:(resources string:'Images new size:'). |
|
7961 box okText:(resources string:'OK'). |
|
7962 box abortText:(resources string:'Cancel'). |
|
7963 box initialText:image extent printString. |
|
7964 box showAtPointer. |
|
7965 (box accepted |
|
7966 and: [(newSize := self pointFromString:(box contents)) notNil]) |
|
7967 ifTrue:[ |
|
7968 imageEditView resizeImageTo:newSize. |
|
7969 ]. |
|
7970 ! |
|
7971 |
|
7972 doRotateImage |
|
7973 "rotates current image" |
|
7974 |
|
7975 |rotationString box rotation| |
|
7976 |
|
7977 rotationString := Dialog |
|
7978 request:(resources string:'Rotate by (degrees, clockwise):') |
|
7979 list:#( '-90' '90' '180' '45' '-45' '135' '-135' ) |
|
7980 initialAnswer:90. |
|
7981 rotationString isEmptyOrNil ifTrue:[^ self]. "/ canceled |
|
7982 rotation := Number readFrom:rotationString onError:[nil]. |
|
7983 rotation isNil ifTrue:[^ self]. |
|
7984 |
|
7985 "/ box := EnterBox new. |
|
7986 "/ box title:(resources string:'Rotate by (degrees, clockwise):'). |
|
7987 "/ box okText:(resources string:'OK'). |
|
7988 "/ box abortText:(resources string:'Cancel'). |
|
7989 "/ box initialText: '0'. |
|
7990 "/ box showAtPointer. |
|
7991 "/ (box accepted and: [(rotation := Number readFromString: box contents onError:nil) notNil]) |
|
7992 "/ ifFalse:[ ^ self ]. |
|
7993 |
|
7994 imageEditView rotateImageBy:rotation. |
|
7995 self updateInfoLabel. |
|
7996 |
|
7997 "Modified: / 18-03-2012 / 14:41:14 / cg" |
|
7998 "Modified (comment): / 24-08-2017 / 15:02:57 / cg" |
|
7999 ! |
|
8000 |
|
8001 doShiftManual |
|
8002 "let user specify amount and shift" |
|
8003 |
|
8004 |bindings amount img firstChange shiftAction acceptChannel wrapHolder| |
|
8005 |
|
8006 acceptChannel := TriggerValue new. |
|
8007 wrapHolder := (lastShiftUsedWrap ? true) asValue. |
|
8008 |
|
8009 firstChange := true. |
|
8010 |
|
8011 shiftAction := |
|
8012 [:shiftH :shiftV | |
|
8013 acceptChannel value:true. |
|
8014 |
|
8015 img := imageEditView image. |
|
8016 firstChange ifTrue:[ |
|
8017 imageEditView makeUndo. |
|
8018 firstChange := false. |
|
8019 ]. |
|
8020 imageEditView shiftImageHorizontal:(shiftH value) vertical:(shiftV value) wrap:(wrapHolder value). |
|
8021 self updateInfoLabel |
|
8022 ]. |
|
8023 |
|
8024 bindings := IdentityDictionary new. |
|
8025 bindings at:#shiftAmount put:(amount := 1 asValue). |
|
8026 bindings at:#wrap put:wrapHolder. |
|
8027 bindings at:#acceptChannel put:acceptChannel. |
|
8028 |
|
8029 bindings at:#shiftLeftNow put:[ shiftAction value:(-1*amount value) value:0 ]. |
|
8030 bindings at:#shiftRightNow put:[ shiftAction value:amount value value:0 ]. |
|
8031 bindings at:#shiftUpNow put:[ shiftAction value:0 value:(-1*amount value) ]. |
|
8032 bindings at:#shiftDownNow put:[ shiftAction value:0 value:amount value ]. |
|
8033 |
|
8034 (self openDialogInterface:#shiftDialogSpec withBindings:bindings) |
|
8035 ifFalse:[ |
|
8036 firstChange ~~ true ifTrue:[ |
|
8037 imageEditView undo |
|
8038 ] |
|
8039 ]. |
|
8040 lastShiftUsedWrap := wrapHolder value. |
|
8041 |
|
8042 "Created: / 7.9.1998 / 18:16:07 / cg" |
|
8043 "Modified: / 7.9.1998 / 18:20:42 / cg" |
|
8044 ! |
|
8045 |
|
8046 doUnCropManual |
|
8047 "let user specify borders and add them" |
|
8048 |
|
8049 |bindings leftAmount topAmount rightAmount bottomAmount img| |
|
8050 |
|
8051 bindings := IdentityDictionary new. |
|
8052 bindings at:#cropLeftAmount put:(leftAmount := 1 asValue). |
|
8053 bindings at:#cropRightAmount put:(rightAmount := 1 asValue). |
|
8054 bindings at:#cropTopAmount put:(topAmount := 1 asValue). |
|
8055 bindings at:#cropBottomAmount put:(bottomAmount := 1 asValue). |
|
8056 bindings at:#cropBoxIsDialog put:true. |
|
8057 |
|
8058 (self openDialogInterface:#uncropSpec withBindings:bindings) |
|
8059 ifTrue:[ |
|
8060 leftAmount := leftAmount value. |
|
8061 rightAmount := rightAmount value. |
|
8062 topAmount := topAmount value. |
|
8063 bottomAmount := bottomAmount value. |
|
8064 img := imageEditView image. |
|
8065 |
|
8066 imageEditView |
|
8067 makeBorderedImageX:leftAmount y:topAmount |
|
8068 width:(img width + leftAmount + rightAmount) |
|
8069 height:(img height + topAmount + bottomAmount). |
|
8070 self updateInfoLabel |
|
8071 ]. |
|
8072 |
|
8073 "Created: / 07-09-1998 / 18:16:07 / cg" |
|
8074 "Modified: / 19-02-2017 / 15:31:00 / cg" |
|
8075 ! |
|
8076 |
|
8077 doUndo |
|
8078 "reverses last edit action" |
|
8079 |
|
8080 imageEditView undo. |
|
8081 self updateImagePreView |
|
8082 ! |
|
8083 |
|
8084 makeInverse |
|
8085 "inverts the pixels - for palettes, this leads to funny results" |
|
8086 |
|
8087 self updateImageAfterDoing:#makeInverse. |
|
8088 |
|
8089 "Modified: / 31-08-2017 / 12:16:07 / cg" |
|
8090 "Modified (comment): / 31-08-2017 / 13:51:28 / cg" |
|
8091 ! |
|
8092 |
|
8093 makeMonochromeImage |
|
8094 "let user choose a threshold, then convert to monochrome" |
|
8095 |
|
8096 |image userInput thresholdBrighness| |
|
8097 |
|
8098 image := imageEditView image. |
|
8099 |
|
8100 Dialog modifyingBoxWith:[:box | |
|
8101 |preview slider update thresholdValue| |
|
8102 |
|
8103 thresholdValue := 0.5 asValue. |
|
8104 |
|
8105 box enterField |
|
8106 converter:(PrintConverter new initForNumber); |
|
8107 model:thresholdValue. |
|
8108 |
|
8109 box verticalPanel extent:1.0 @ 300. |
|
8110 |
|
8111 box verticalPanel add:(slider := HorizontalSlider new start:0 stop:1 step:0.05). |
|
8112 slider model:thresholdValue. |
|
8113 slider width:1.0; leftInset:4; rightInset:4. |
|
8114 |
|
8115 box verticalPanel add:(preview := ImageView new). |
|
8116 preview extent:300 @300. |
|
8117 preview level:-1. |
|
8118 box verticalPanel horizontalLayout:#fitSpace. |
|
8119 |
|
8120 update := |
|
8121 [ |
|
8122 |s t| |
|
8123 |
|
8124 t := thresholdValue value clampBetween:0 and:1. |
|
8125 preview image:((image asThresholdMonochromeImage:t) |
|
8126 magnifiedPreservingRatioTo:preview extent). |
|
8127 ]. |
|
8128 update value. |
|
8129 box enterField acceptOnLostFocus:true. |
|
8130 box enterField acceptOnLeave:true. |
|
8131 thresholdValue onChangeEvaluate:update. |
|
8132 |
|
8133 ] do:[ |
|
8134 userInput := Dialog request:'Threshold (0=black; 1=white) ?' initialAnswer:0.5. |
|
8135 ]. |
|
8136 userInput isEmptyOrNil ifTrue:[^ self]. |
|
8137 thresholdBrighness := Number readFrom:userInput onError:nil. |
|
8138 thresholdBrighness isNil ifTrue:[^ self]. |
|
8139 |
|
8140 thresholdBrighness := thresholdBrighness clampBetween:0 and:1. |
|
8141 imageEditView newImageWithUndo:(image asThresholdMonochromeImage:thresholdBrighness) |
|
8142 |
|
8143 "Created: / 24-08-2017 / 15:26:44 / cg" |
|
8144 "Modified: / 24-08-2017 / 17:54:21 / cg" |
|
8145 ! |
|
8146 |
|
8147 makeNegative |
|
8148 "negates current image by negating the color map" |
|
8149 |
|
8150 self withExecuteCursorDo:[ |
|
8151 imageEditView negativeImage. |
|
8152 self updateImage. |
|
8153 ]. |
|
8154 "/ |
|
8155 "/ imageEditView negativeImage. |
|
8156 "/ self listOfColors removeAll. |
|
8157 "/ self findColorMapMode. |
|
8158 "/ "/ imageEditView removelastUndo |
|
8159 "/ |
|
8160 "/ |
|
8161 |
|
8162 "Created: / 31-08-2017 / 13:49:47 / cg" |
|
8163 ! |
|
8164 |
|
8165 thresholdGrayToDepth |
|
8166 self askForDepthThenDo:[:depth | |
|
8167 self thresholdGrayToDepth:depth |
|
8168 ]. |
|
8169 |
|
8170 "Created: / 24-08-2017 / 17:49:23 / cg" |
|
8171 ! |
|
8172 |
|
8173 thresholdGrayToDepth:depth |
|
8174 self withExecuteCursorDo:[ |
|
8175 |newImage| |
|
8176 |
|
8177 newImage := self image asThresholdGrayImageDepth:depth. |
|
8178 imageEditView newImageWithUndo:newImage. |
|
8179 ]. |
|
8180 |
|
8181 "Created: / 24-08-2017 / 17:49:30 / cg" |
|
8182 ! |
|
8183 |
|
8184 thresholdToDepth |
|
8185 self askForDepthThenDo:[:depth | |
|
8186 self convertToDepth:depth dither:false |
|
8187 ]. |
|
8188 |
|
8189 "Created: / 30-08-2017 / 00:31:33 / cg" |
|
8190 ! ! |
|
8191 |
|
8192 !ImageEditor methodsFor:'user actions-editing-colors'! |
7426 |
8193 |
7427 convertToDepth:depth dither:doDither |
8194 convertToDepth:depth dither:doDither |
7428 |answer labels values |
8195 |answer labels values |
7429 ditherColors fixColors |
8196 ditherColors fixColors |
7430 nGrey greyColorsAlready moreColors d| |
8197 nGrey greyColorsAlready moreColors d| |
7586 |
8353 |
7587 "Created: / 30-08-2017 / 00:33:55 / cg" |
8354 "Created: / 30-08-2017 / 00:33:55 / cg" |
7588 "Modified: / 30-08-2017 / 02:13:03 / cg" |
8355 "Modified: / 30-08-2017 / 02:13:03 / cg" |
7589 ! |
8356 ! |
7590 |
8357 |
7591 ditherGrayToDepth |
8358 makeInvertedBits |
7592 self askForDepthThenDo:[:depth | |
8359 "inverts the pixels - for palettes, this leads to funny results. |
7593 self ditherGrayToDepth:depth |
8360 For others, this is the same as negating" |
7594 ]. |
8361 |
7595 |
8362 self updateImageAfterDoing:#makeInvertedBits. |
7596 "Created: / 24-08-2017 / 17:49:42 / cg" |
8363 |
7597 ! |
8364 "Created: / 31-08-2017 / 13:51:10 / cg" |
7598 |
|
7599 ditherGrayToDepth:depth |
|
7600 self withExecuteCursorDo:[ |
|
7601 |newImage| |
|
7602 |
|
7603 depth == 1 ifTrue:[ |
|
7604 newImage := self image asErrorDitheredMonochromeImage |
|
7605 ] ifFalse:[ |
|
7606 newImage := self image asGrayImageDepth:depth dither:#floydSteinberg. |
|
7607 ]. |
|
7608 imageEditView newImageWithUndo:newImage. |
|
7609 ]. |
|
7610 |
|
7611 "Created: / 24-08-2017 / 17:51:07 / cg" |
|
7612 "Modified: / 30-08-2017 / 01:18:43 / cg" |
|
7613 ! |
|
7614 |
|
7615 ditherToDepth |
|
7616 self askForDepthThenDo:[:depth | |
|
7617 self convertToDepth:depth dither:true |
|
7618 ]. |
|
7619 |
|
7620 "Created: / 07-07-2006 / 13:22:10 / cg" |
|
7621 "Modified: / 30-08-2017 / 00:34:42 / cg" |
|
7622 ! |
|
7623 |
|
7624 do3DProjection |
|
7625 |box dx1 dx2 image| |
|
7626 |
|
7627 image := imageEditView image. |
|
7628 |
|
7629 box := EnterBox new. |
|
7630 box title:(resources string:'dX1 (0 < dx < 0.5):'). |
|
7631 box okText:(resources string:'OK'). |
|
7632 box abortText:(resources string:'Cancel'). |
|
7633 box initialText:'0.1'. |
|
7634 box showAtPointer. |
|
7635 |
|
7636 (box accepted |
|
7637 and: [(dx1 := Number readFrom:(box contents) onError:nil) notNil]) |
|
7638 ifTrue:[ |
|
7639 box title:(resources string:'dX2 (0 < dx < 0.5):'). |
|
7640 box initialText:(dx1 printString). |
|
7641 box showAtPointer. |
|
7642 (box accepted |
|
7643 and: [(dx2 := Number readFrom:(box contents) onError:nil) notNil]) |
|
7644 ifTrue:[ |
|
7645 imageEditView threeDProjection:dx1 and:dx2. |
|
7646 ] |
|
7647 ]. |
|
7648 |
|
7649 self updateInfoLabel |
|
7650 ! |
|
7651 |
|
7652 doBrightenImage |
|
7653 imageEditView brightenImage. |
|
7654 self listOfColors removeAll. |
|
7655 self findColorMapMode. |
|
7656 "/ imageEditView removelastUndo |
|
7657 ! |
|
7658 |
|
7659 doBrowseClass |
|
7660 "opens a System Browser on the resourceClass and the resourceSelector" |
|
7661 |
|
7662 |cls| |
|
7663 |
|
7664 cls := imageEditView resourceClass. |
|
7665 cls isNil ifTrue:[^ self warn:'No Class specified']. |
|
7666 |
|
7667 cls browserClass |
|
7668 openInClass:cls class |
|
7669 selector:(imageEditView resourceSelector) |
|
7670 |
|
7671 "Modified: / 31.7.1998 / 02:01:15 / cg" |
|
7672 ! |
|
7673 |
|
7674 doCopyImageToClipboard |
|
7675 imageEditView copyImageToClipboard. |
|
7676 ! |
|
7677 |
|
7678 doCropManual |
|
7679 "let user specify borders and cut them off" |
|
7680 |
|
7681 |bindings left top right bottom img firstChange cropAction acceptChannel| |
|
7682 |
|
7683 acceptChannel := TriggerValue new. |
|
7684 |
|
7685 firstChange := true. |
|
7686 |
|
7687 cropAction := |
|
7688 [:lV :rV :tV :bV | |l r t b| |
|
7689 acceptChannel value:true. |
|
7690 |
|
7691 l := lV value. |
|
7692 r := rV value. |
|
7693 t := tV value. |
|
7694 b := bV value. |
|
7695 (l + r + t + b) == 0 ifTrue:[ |
|
7696 UserPreferences current beepInEditor ifTrue:[ |
|
7697 self window beep |
|
7698 ] |
|
7699 ] ifFalse:[ |
|
7700 img := imageEditView image. |
|
7701 firstChange ifTrue:[ |
|
7702 imageEditView makeUndo. |
|
7703 firstChange := false. |
|
7704 ]. |
|
7705 imageEditView |
|
7706 makeSubImageX:l y:t |
|
7707 width:(img width - l - r) |
|
7708 height:(img height - t - b). |
|
7709 |
|
7710 self updateImagePreView. |
|
7711 self updateInfoLabel |
|
7712 ]. |
|
7713 ]. |
|
7714 |
|
7715 bindings := IdentityDictionary new. |
|
7716 bindings at:#cropLeftAmount put:(left := 1 asValue). |
|
7717 bindings at:#cropRightAmount put:(right := 1 asValue). |
|
7718 bindings at:#cropTopAmount put:(top := 1 asValue). |
|
7719 bindings at:#cropBottomAmount put:(bottom := 1 asValue). |
|
7720 bindings at:#acceptChannel put:acceptChannel. |
|
7721 |
|
7722 bindings at:#cropLeftNow put:[ cropAction value:left value:0 value:0 value:0 ]. |
|
7723 bindings at:#cropRightNow put:[ cropAction value:0 value:right value:0 value:0 ]. |
|
7724 bindings at:#cropTopNow put:[ cropAction value:0 value:0 value:top value:0 ]. |
|
7725 bindings at:#cropBottomNow put:[ cropAction value:0 value:0 value:0 value:bottom ]. |
|
7726 |
|
7727 bindings at:#applyCropAction put:[ cropAction value:left value:right value:top value:bottom ]. |
|
7728 bindings at:#cropBoxIsDialog put:true. |
|
7729 |
|
7730 (self openDialogInterface:#cropSpec withBindings:bindings) |
|
7731 ifFalse:[ |
|
7732 firstChange ~~ true ifTrue:[ |
|
7733 imageEditView undo. |
|
7734 self updateImagePreView. |
|
7735 ] |
|
7736 ]. |
|
7737 |
|
7738 "Created: / 07-09-1998 / 18:16:07 / cg" |
|
7739 "Modified: / 19-02-2017 / 15:43:50 / cg" |
|
7740 ! |
|
7741 |
|
7742 doDarkenImage |
|
7743 imageEditView darkenImage. |
|
7744 self listOfColors removeAll. |
|
7745 self findColorMapMode. |
|
7746 "/ imageEditView removelastUndo |
|
7747 ! |
|
7748 |
|
7749 doEditMask |
|
7750 |mask| |
|
7751 |
|
7752 (mask := self image mask) notNil ifTrue:[ |
|
7753 mask edit |
|
7754 ]. |
|
7755 |
|
7756 "Modified: / 18-02-2017 / 00:38:51 / cg" |
|
7757 ! |
|
7758 |
|
7759 doFlipHorizontal |
|
7760 "flips horizontally current image" |
|
7761 |
|
7762 imageEditView flipHorizontal |
|
7763 ! |
|
7764 |
|
7765 doFlipVertical |
|
7766 "flips vertically current image" |
|
7767 |
|
7768 imageEditView flipVertical |
|
7769 ! |
|
7770 |
|
7771 doInsertTextFromUser |
|
7772 |text tempForm tempImage maskImage font w h paintColor| |
|
7773 |
|
7774 text := Dialog request:'Text to be inserted (placed as bitmap into clipboard for paste):'. |
|
7775 text isEmptyOrNil ifTrue:[^ self ]. |
|
7776 |
|
7777 font := Font family:'arial' size:20. |
|
7778 font := font onDevice:Screen current. |
|
7779 w := font widthOf:text. |
|
7780 h := font heightOf:text. |
|
7781 |
|
7782 tempForm := Form extent:(w@h) depth:1 onDevice:(Screen current). |
|
7783 tempForm clear. |
|
7784 tempForm font:font. |
|
7785 tempForm paint:(Color colorId:1). |
|
7786 tempForm displayString:text at:(0@font ascent). |
|
7787 |
|
7788 tempImage := tempForm asImage. |
|
7789 maskImage := tempForm asImage. |
|
7790 |
|
7791 paintColor := imageEditView selectedColor. |
|
7792 paintColor colorId == 0 ifTrue:[ |
|
7793 paintColor := Color black |
|
7794 ]. |
|
7795 tempImage |
|
7796 photometric:#palette; |
|
7797 colorMap:(Array |
|
7798 with:Color white |
|
7799 with:paintColor); |
|
7800 mask:maskImage. |
|
7801 |
|
7802 ImageEditView copyImageToClipboard:tempImage. |
|
7803 self editMode value:#paste. |
|
7804 |
|
7805 "Modified: / 11-11-2007 / 12:32:55 / cg" |
|
7806 ! |
|
7807 |
|
7808 doInspectImage |
|
7809 "opens a System Browser on the resourceClass and the resourceSelector" |
|
7810 |
|
7811 self image inspect |
|
7812 ! |
|
7813 |
|
7814 doMagnifyDown |
|
7815 "magnifies the current image one step down" |
|
7816 |
|
7817 |magHolder mag| |
|
7818 |
|
7819 magHolder := self magnificationHolder. |
|
7820 (mag := magHolder value) > 1 ifTrue: [ |
|
7821 magHolder value: mag - 1 |
|
7822 ] |
|
7823 |
|
7824 "Modified: / 26.7.1998 / 20:24:08 / cg" |
|
7825 ! |
|
7826 |
|
7827 doMagnifyImage |
|
7828 "magnifies the current image to a new size" |
|
7829 |
|
7830 |box newSize image antiAliased| |
|
7831 |
|
7832 antiAliased := false asValue. |
|
7833 image := imageEditView image. |
|
7834 |
|
7835 box := EnterBox new. |
|
7836 box title:(resources string:'Images new size:'). |
|
7837 box okText:(resources string:'OK'). |
|
7838 box abortText:(resources string:'Cancel'). |
|
7839 box initialText:image extent printString. |
|
7840 box verticalPanel add:(CheckBox label:(resources string:'Antialias/Smooth') model:antiAliased). |
|
7841 box showAtPointer. |
|
7842 |
|
7843 (box accepted |
|
7844 and: [(newSize := self pointFromString:(box contents)) notNil]) |
|
7845 ifTrue:[ |
|
7846 newSize isPoint ifFalse:[ |
|
7847 self warn:'Please enter the new size as ''x @ y''.'. |
|
7848 ^ self. |
|
7849 ]. |
|
7850 antiAliased value ifTrue:[ |
|
7851 ((newSize x < image width) or:[(newSize y < image height)]) ifTrue:[ |
|
7852 imageEditView magnifySmoothingTo:newSize. |
|
7853 ] ifFalse:[ |
|
7854 imageEditView magnifyAntiAliasedImageTo:newSize. |
|
7855 ]. |
|
7856 ] ifFalse:[ |
|
7857 imageEditView magnifyImageTo:newSize. |
|
7858 ]. |
|
7859 ]. |
|
7860 |
|
7861 self updateInfoLabel |
|
7862 |
|
7863 "Modified: / 30-08-2017 / 15:46:02 / cg" |
|
7864 ! |
|
7865 |
|
7866 doMagnifyImageBy |
|
7867 "magnifies the current image (by a scale)" |
|
7868 |
|
7869 |oldSize newSize scaleString scale image antiAliased smoothing| |
|
7870 |
|
7871 image := imageEditView image. |
|
7872 oldSize := image extent. |
|
7873 |
|
7874 antiAliased := false asValue. |
|
7875 smoothing := false asValue. |
|
7876 |
|
7877 Dialog modifyingBoxWith:[:box | |
|
7878 box verticalPanel add:(CheckBox label:(resources string:'Antialias/Smooth') model:antiAliased). |
|
7879 "/ box verticalPanel add:(CheckBox label:(resources string:'Smoothing') model:smoothing). |
|
7880 ] do:[ |
|
7881 scaleString := Dialog |
|
7882 request:(resources string:'Scale factor (<1 to shrink; >1 to magnify):') |
|
7883 initialAnswer:'1' |
|
7884 list:#('0.1' '0.25' '0.3' '0.5' '1.5' '2' '3' '4'). |
|
7885 ]. |
|
7886 scaleString isNil ifTrue:[^ self]. |
|
7887 |
|
7888 scale := Object readFromString:scaleString onError:nil. |
|
7889 |
|
7890 scale notNil ifTrue:[ |
|
7891 scale isNumber ifFalse:[ |
|
7892 self warn:'please enter a scale factor (<1 to shrink; >1 to magnify).'. |
|
7893 ^ self. |
|
7894 ]. |
|
7895 newSize := oldSize * scale. |
|
7896 antiAliased value ifTrue:[ |
|
7897 scale < 1 ifTrue:[ |
|
7898 imageEditView magnifySmoothingBy:scale. |
|
7899 ] ifFalse:[ |
|
7900 imageEditView magnifyAntiAliasedImageTo:newSize. |
|
7901 ]. |
|
7902 ] ifFalse:[ |
|
7903 imageEditView magnifyImageTo:newSize. |
|
7904 ]. |
|
7905 ]. |
|
7906 |
|
7907 self updateInfoLabel |
|
7908 |
|
7909 "Modified: / 30-08-2017 / 15:34:56 / cg" |
|
7910 ! |
|
7911 |
|
7912 doMagnifyUp |
|
7913 "magnifies the current image one step up" |
|
7914 |
|
7915 |magHolder mag| |
|
7916 |
|
7917 magHolder := self magnificationHolder. |
|
7918 (mag := magHolder value) < 63 ifTrue: [ |
|
7919 magHolder value: mag + 1 |
|
7920 ] |
|
7921 |
|
7922 "Modified: / 26.7.1998 / 20:23:52 / cg" |
|
7923 ! |
|
7924 |
|
7925 doNegativeImage |
|
7926 "negates current image by negating the color map" |
|
7927 |
|
7928 self image depth ~~ 1 ifTrue:[ |
|
7929 Dialog warn:'Only useful for depth 1 images'. |
|
7930 ^ self |
|
7931 ]. |
|
7932 imageEditView negativeImage. |
|
7933 self listOfColors removeAll. |
|
7934 self findColorMapMode. |
|
7935 "/ imageEditView removelastUndo |
|
7936 ! |
|
7937 |
|
7938 doResizeImage |
|
7939 "resizes the current image" |
|
7940 |
|
7941 |box newSize image| |
|
7942 |
|
7943 image := imageEditView image. |
|
7944 |
|
7945 box := EnterBox new. |
|
7946 box title:(resources string:'Images new size:'). |
|
7947 box okText:(resources string:'OK'). |
|
7948 box abortText:(resources string:'Cancel'). |
|
7949 box initialText:image extent printString. |
|
7950 box showAtPointer. |
|
7951 (box accepted |
|
7952 and: [(newSize := self pointFromString:(box contents)) notNil]) |
|
7953 ifTrue:[ |
|
7954 imageEditView resizeImageTo:newSize. |
|
7955 ]. |
|
7956 ! |
|
7957 |
|
7958 doRotateImage |
|
7959 "rotates current image" |
|
7960 |
|
7961 |rotationString box rotation| |
|
7962 |
|
7963 rotationString := Dialog |
|
7964 request:(resources string:'Rotate by (degrees, clockwise):') |
|
7965 list:#( '-90' '90' '180' '45' '-45' '135' '-135' ) |
|
7966 initialAnswer:90. |
|
7967 rotationString isEmptyOrNil ifTrue:[^ self]. "/ canceled |
|
7968 rotation := Number readFrom:rotationString onError:[nil]. |
|
7969 rotation isNil ifTrue:[^ self]. |
|
7970 |
|
7971 "/ box := EnterBox new. |
|
7972 "/ box title:(resources string:'Rotate by (degrees, clockwise):'). |
|
7973 "/ box okText:(resources string:'OK'). |
|
7974 "/ box abortText:(resources string:'Cancel'). |
|
7975 "/ box initialText: '0'. |
|
7976 "/ box showAtPointer. |
|
7977 "/ (box accepted and: [(rotation := Number readFromString: box contents onError:nil) notNil]) |
|
7978 "/ ifFalse:[ ^ self ]. |
|
7979 |
|
7980 imageEditView rotateImageBy:rotation. |
|
7981 self updateInfoLabel. |
|
7982 |
|
7983 "Modified: / 18-03-2012 / 14:41:14 / cg" |
|
7984 "Modified (comment): / 24-08-2017 / 15:02:57 / cg" |
|
7985 ! |
|
7986 |
|
7987 doShiftManual |
|
7988 "let user specify amount and shift" |
|
7989 |
|
7990 |bindings amount img firstChange shiftAction acceptChannel wrapHolder| |
|
7991 |
|
7992 acceptChannel := TriggerValue new. |
|
7993 wrapHolder := (lastShiftUsedWrap ? true) asValue. |
|
7994 |
|
7995 firstChange := true. |
|
7996 |
|
7997 shiftAction := |
|
7998 [:shiftH :shiftV | |
|
7999 acceptChannel value:true. |
|
8000 |
|
8001 img := imageEditView image. |
|
8002 firstChange ifTrue:[ |
|
8003 imageEditView makeUndo. |
|
8004 firstChange := false. |
|
8005 ]. |
|
8006 imageEditView shiftImageHorizontal:(shiftH value) vertical:(shiftV value) wrap:(wrapHolder value). |
|
8007 self updateInfoLabel |
|
8008 ]. |
|
8009 |
|
8010 bindings := IdentityDictionary new. |
|
8011 bindings at:#shiftAmount put:(amount := 1 asValue). |
|
8012 bindings at:#wrap put:wrapHolder. |
|
8013 bindings at:#acceptChannel put:acceptChannel. |
|
8014 |
|
8015 bindings at:#shiftLeftNow put:[ shiftAction value:(-1*amount value) value:0 ]. |
|
8016 bindings at:#shiftRightNow put:[ shiftAction value:amount value value:0 ]. |
|
8017 bindings at:#shiftUpNow put:[ shiftAction value:0 value:(-1*amount value) ]. |
|
8018 bindings at:#shiftDownNow put:[ shiftAction value:0 value:amount value ]. |
|
8019 |
|
8020 (self openDialogInterface:#shiftDialogSpec withBindings:bindings) |
|
8021 ifFalse:[ |
|
8022 firstChange ~~ true ifTrue:[ |
|
8023 imageEditView undo |
|
8024 ] |
|
8025 ]. |
|
8026 lastShiftUsedWrap := wrapHolder value. |
|
8027 |
|
8028 "Created: / 7.9.1998 / 18:16:07 / cg" |
|
8029 "Modified: / 7.9.1998 / 18:20:42 / cg" |
|
8030 ! |
|
8031 |
|
8032 doUnCropManual |
|
8033 "let user specify borders and add them" |
|
8034 |
|
8035 |bindings leftAmount topAmount rightAmount bottomAmount img| |
|
8036 |
|
8037 bindings := IdentityDictionary new. |
|
8038 bindings at:#cropLeftAmount put:(leftAmount := 1 asValue). |
|
8039 bindings at:#cropRightAmount put:(rightAmount := 1 asValue). |
|
8040 bindings at:#cropTopAmount put:(topAmount := 1 asValue). |
|
8041 bindings at:#cropBottomAmount put:(bottomAmount := 1 asValue). |
|
8042 bindings at:#cropBoxIsDialog put:true. |
|
8043 |
|
8044 (self openDialogInterface:#uncropSpec withBindings:bindings) |
|
8045 ifTrue:[ |
|
8046 leftAmount := leftAmount value. |
|
8047 rightAmount := rightAmount value. |
|
8048 topAmount := topAmount value. |
|
8049 bottomAmount := bottomAmount value. |
|
8050 img := imageEditView image. |
|
8051 |
|
8052 imageEditView |
|
8053 makeBorderedImageX:leftAmount y:topAmount |
|
8054 width:(img width + leftAmount + rightAmount) |
|
8055 height:(img height + topAmount + bottomAmount). |
|
8056 self updateInfoLabel |
|
8057 ]. |
|
8058 |
|
8059 "Created: / 07-09-1998 / 18:16:07 / cg" |
|
8060 "Modified: / 19-02-2017 / 15:31:00 / cg" |
|
8061 ! |
|
8062 |
|
8063 doUndo |
|
8064 "reverses last edit action" |
|
8065 |
|
8066 imageEditView undo. |
|
8067 self updateImagePreView |
|
8068 ! |
|
8069 |
|
8070 makeMonochromeImage |
|
8071 "let user choose a threshold, then convert to monochrome" |
|
8072 |
|
8073 |image userInput thresholdBrighness| |
|
8074 |
|
8075 image := imageEditView image. |
|
8076 |
|
8077 Dialog modifyingBoxWith:[:box | |
|
8078 |preview slider update thresholdValue| |
|
8079 |
|
8080 thresholdValue := 0.5 asValue. |
|
8081 |
|
8082 box enterField |
|
8083 converter:(PrintConverter new initForNumber); |
|
8084 model:thresholdValue. |
|
8085 |
|
8086 box verticalPanel extent:1.0 @ 300. |
|
8087 |
|
8088 box verticalPanel add:(slider := HorizontalSlider new start:0 stop:1 step:0.05). |
|
8089 slider model:thresholdValue. |
|
8090 slider width:1.0; leftInset:4; rightInset:4. |
|
8091 |
|
8092 box verticalPanel add:(preview := ImageView new). |
|
8093 preview extent:300 @300. |
|
8094 preview level:-1. |
|
8095 box verticalPanel horizontalLayout:#fitSpace. |
|
8096 |
|
8097 update := |
|
8098 [ |
|
8099 |s t| |
|
8100 |
|
8101 t := thresholdValue value clampBetween:0 and:1. |
|
8102 preview image:((image asThresholdMonochromeImage:t) |
|
8103 magnifiedPreservingRatioTo:preview extent). |
|
8104 ]. |
|
8105 update value. |
|
8106 box enterField acceptOnLostFocus:true. |
|
8107 box enterField acceptOnLeave:true. |
|
8108 thresholdValue onChangeEvaluate:update. |
|
8109 |
|
8110 ] do:[ |
|
8111 userInput := Dialog request:'Threshold (0=black; 1=white) ?' initialAnswer:0.5. |
|
8112 ]. |
|
8113 userInput isEmptyOrNil ifTrue:[^ self]. |
|
8114 thresholdBrighness := Number readFrom:userInput onError:nil. |
|
8115 thresholdBrighness isNil ifTrue:[^ self]. |
|
8116 |
|
8117 thresholdBrighness := thresholdBrighness clampBetween:0 and:1. |
|
8118 imageEditView newImageWithUndo:(image asThresholdMonochromeImage:thresholdBrighness) |
|
8119 |
|
8120 "Created: / 24-08-2017 / 15:26:44 / cg" |
|
8121 "Modified: / 24-08-2017 / 17:54:21 / cg" |
|
8122 ! |
|
8123 |
|
8124 thresholdGrayToDepth |
|
8125 self askForDepthThenDo:[:depth | |
|
8126 self thresholdGrayToDepth:depth |
|
8127 ]. |
|
8128 |
|
8129 "Created: / 24-08-2017 / 17:49:23 / cg" |
|
8130 ! |
|
8131 |
|
8132 thresholdGrayToDepth:depth |
|
8133 self withExecuteCursorDo:[ |
|
8134 |newImage| |
|
8135 |
|
8136 newImage := self image asThresholdGrayImageDepth:depth. |
|
8137 imageEditView newImageWithUndo:newImage. |
|
8138 ]. |
|
8139 |
|
8140 "Created: / 24-08-2017 / 17:49:30 / cg" |
|
8141 ! |
|
8142 |
|
8143 thresholdToDepth |
|
8144 self askForDepthThenDo:[:depth | |
|
8145 self convertToDepth:depth dither:false |
|
8146 ]. |
|
8147 |
|
8148 "Created: / 30-08-2017 / 00:31:33 / cg" |
|
8149 ! ! |
8365 ! ! |
8150 |
8366 |
8151 !ImageEditor methodsFor:'user actions-image sequences'! |
8367 !ImageEditor methodsFor:'user actions-image sequences'! |
8152 |
8368 |
8153 editEachImageFromSequence |
8369 editEachImageFromSequence |