summaryrefslogtreecommitdiff
path: root/src/process/im_convolve.cpp
diff options
context:
space:
mode:
authorscuri <scuri>2009-10-01 02:56:38 +0000
committerscuri <scuri>2009-10-01 02:56:38 +0000
commit62783aee16f96fe5e513fb230b8efddaa02981df (patch)
tree9dc512b0c758025c5cddba9709420f1bf9058675 /src/process/im_convolve.cpp
parent9a5e93213e08601a58725f44035ac622fb68e849 (diff)
New: functions imProcessUnsharp and imProcessSharp.
Changed: now imProcessUnArithmeticOp, imProcessArithmeticConstOp and imProcessArithmeticOp willl crop the result to 0-255 if destiny has data type byte. Changed: removed IM_UN_INC operation from imProcessUnArithmeticOp. It was not an unary operation. Can simply be done in place by imProcessArithmeticOp and IM_BIN_ADD.
Diffstat (limited to 'src/process/im_convolve.cpp')
-rw-r--r--src/process/im_convolve.cpp190
1 files changed, 136 insertions, 54 deletions
diff --git a/src/process/im_convolve.cpp b/src/process/im_convolve.cpp
index bca2dcd..a88a25c 100644
--- a/src/process/im_convolve.cpp
+++ b/src/process/im_convolve.cpp
@@ -2,7 +2,7 @@
* \brief Convolution Operations
*
* See Copyright Notice in im_lib.h
- * $Id: im_convolve.cpp,v 1.1 2008/10/17 06:16:33 scuri Exp $
+ * $Id: im_convolve.cpp,v 1.2 2009/10/01 02:56:58 scuri Exp $
*/
@@ -1426,59 +1426,6 @@ int imProcessDiffOfGaussianConvolve(const imImage* src_image, imImage* dst_image
return 1;
}
-#ifdef _TEST_CODE_
-int imProcessDiffOfGaussianConvolveTEST(const imImage* src_image, imImage* dst_image, float stddev1, float stddev2)
-{
- int kernel_size1 = imGaussianStdDev2KernelSize(stddev1);
- int kernel_size2 = imGaussianStdDev2KernelSize(stddev2);
- int size = kernel_size1;
- if (kernel_size1 < kernel_size2) size = kernel_size2;
-
- imImage* kernel1 = imImageCreate(size, size, IM_GRAY, IM_FLOAT);
- imImage* kernel2 = imImageCreate(size, size, IM_GRAY, IM_FLOAT);
- if (!kernel1 || !kernel2)
- {
- if (kernel1) imImageDestroy(kernel1);
- if (kernel2) imImageDestroy(kernel2);
- return 0;
- }
-
- imImageSetAttribute(kernel1, "Description", IM_BYTE, -1, (void*)"Gaussian");
- imImageSetAttribute(kernel2, "Description", IM_BYTE, -1, (void*)"Gaussian");
-
- imProcessRenderGaussian(kernel1, stddev1);
- imProcessRenderGaussian(kernel2, stddev2);
-
- // ERROR: kernel 1 should be multiplied by a factor to improve the difference.
-
- imProcessArithmeticOp(kernel1, kernel2, kernel1, IM_BIN_SUB);
- imImageSetAttribute(kernel1, "Description", IM_BYTE, -1, (void*)"Difference of Gaussian");
-
- int ret = 0;
- if (src_image->data_type == IM_BYTE || src_image->data_type == IM_USHORT)
- {
- imImage* aux_image = imImageClone(dst_image);
- if (!aux_image)
- {
- imImageDestroy(kernel1);
- imImageDestroy(kernel2);
- return 0;
- }
-
- imProcessUnArithmeticOp(src_image, aux_image, IM_UN_EQL); // Convert to IM_INT
- ret = imProcessConvolve(aux_image, dst_image, kernel1);
- imImageDestroy(aux_image);
- }
- else
- ret = imProcessConvolve(src_image, dst_image, kernel1);
-
- imImageDestroy(kernel1);
- imImageDestroy(kernel2);
-
- return ret;
-}
-#endif
-
int imProcessMeanConvolve(const imImage* src_image, imImage* dst_image, int ks)
{
int counter = imCounterBegin("Mean Convolve");
@@ -1510,3 +1457,138 @@ int imProcessMeanConvolve(const imImage* src_image, imImage* dst_image, int ks)
return ret;
}
+
+template <class T1, class T2>
+static void DoSharpOp(T1 *src_map, T1 *dst_map, int count, float amount, T2 threshold, int gauss)
+{
+ int i;
+ T1 min, max;
+
+ int size_of = sizeof(imbyte);
+ if (sizeof(T1) == size_of)
+ {
+ min = 0;
+ max = 255;
+ }
+ else
+ {
+ imMinMax(src_map, count, min, max);
+
+ if (min == max)
+ {
+ max = min + 1;
+
+ if (min != 0)
+ min = min - 1;
+ }
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ T2 diff;
+
+ if (gauss)
+ diff = 20*(src_map[i] - dst_map[i]); /* dst_map contains a gaussian filter of the source image, must compensate for small edge values */
+ else
+ diff = dst_map[i]; /* dst_map contains a laplacian filter of the source image */
+
+ if (threshold && abs_op(2*diff) < threshold)
+ diff = 0;
+
+ T2 value = (T2)(src_map[i] + amount*diff);
+ if (value < min)
+ value = min;
+ else if (value > max)
+ value = max;
+
+ dst_map[i] = (T1)value;
+ }
+}
+
+static void doSharp(const imImage* src_image, imImage* dst_image, float amount, float threshold, int gauss)
+{
+ int count = src_image->count;
+
+ for (int i = 0; i < src_image->depth; i++)
+ {
+ switch(src_image->data_type)
+ {
+ case IM_BYTE:
+ DoSharpOp((imbyte*)src_image->data[i], (imbyte*)dst_image->data[i], count, amount, (int)threshold, gauss);
+ break;
+ case IM_USHORT:
+ DoSharpOp((imushort*)src_image->data[i], (imushort*)dst_image->data[i], count, amount, (int)threshold, gauss);
+ break;
+ case IM_INT:
+ DoSharpOp((int*)src_image->data[i], (int*)dst_image->data[i], count, amount, (int)threshold, gauss);
+ break;
+ case IM_FLOAT:
+ DoSharpOp((float*)src_image->data[i], (float*)dst_image->data[i], count, amount, (float)threshold, gauss);
+ break;
+ }
+ }
+}
+
+int imProcessUnsharp(const imImage* src_image, imImage* dst_image, float stddev, float amount, float threshold)
+{
+ int kernel_size = imGaussianStdDev2KernelSize(stddev);
+
+ imImage* kernel = imImageCreate(kernel_size, kernel_size, IM_GRAY, IM_FLOAT);
+ if (!kernel)
+ return 0;
+
+ imImageSetAttribute(kernel, "Description", IM_BYTE, -1, (void*)"Unsharp");
+ imProcessRenderGaussian(kernel, stddev);
+
+ int ret = imProcessConvolveSep(src_image, dst_image, kernel);
+ doSharp(src_image, dst_image, amount, threshold, 1);
+
+ imImageDestroy(kernel);
+
+ return ret;
+}
+
+int imProcessSharp(const imImage* src_image, imImage* dst_image, float amount, float threshold)
+{
+ imImage* kernel = imKernelLaplacian8();
+ if (!kernel)
+ return 0;
+
+ int ret = imProcessConvolve(src_image, dst_image, kernel);
+ doSharp(src_image, dst_image, amount, threshold, 0);
+
+ imImageDestroy(kernel);
+
+ return ret;
+}
+
+static int iProcessCheckKernelType(const imImage* kernel)
+{
+ if (kernel->data_type == IM_INT)
+ {
+ int* kernel_data = (int*)kernel->data[0];
+ for (int i = 0; i < kernel->count; i++)
+ {
+ if (kernel_data[i] < 0) /* if there are negative values, assume kernel is an edge detector */
+ return 0;
+ }
+ }
+ else if (kernel->data_type == IM_FLOAT)
+ {
+ float* kernel_data = (float*)kernel->data[0];
+ for (int i = 0; i < kernel->count; i++)
+ {
+ if (kernel_data[i] < 0) /* if there are negative values, assume kernel is an edge detector */
+ return 0;
+ }
+ }
+ return 1; /* default is kernel is a smooth filter */
+}
+
+int imProcessSharpKernel(const imImage* src_image, const imImage* kernel, imImage* dst_image, float amount, float threshold)
+{
+ int ret = imProcessConvolve(src_image, dst_image, kernel);
+ doSharp(src_image, dst_image, amount, threshold, iProcessCheckKernelType(kernel));
+ return ret;
+}
+