Wikipedia can explain Kenel's for image processing better than I can:
Convolution is the process of adding each element of the image to its local neighbors, weighted by the kernel. This is related to a form of mathematical convolution.
Image Kernels: Explained Visually, has an interactive demo
The existing code seems to do this in the dither function but it's not really reusable:
for(y=0 ; y != ypixels; y++) {
for (x = 0; x != xpixels; x++) {
inptr = cambuffer + bufstart + x + y * xpixels;
op = *inptr;
if (op > 0x80) np = 0xff; else np = 0;
er = op - np;
*inptr = np;
inptr++; //right
z = (int) *inptr + er * 7/16;
if (z<0) z = 0; else if (z > 255) z = 255;
*inptr = z;
/* snip */
} // x
} // y
Here's an example of the Boxcar (smoothing) Kernel. Unlike the example in Wikipedia, these are not 1's - but I was trying to get some variation, as we'll see later.
const Kernel_t BoxcarKernel = {
{7, 7, 7},
{7, 7, 7},
{7, 7, 7},
};
One thing I learned the hard way was you can't modify the matrix in-place; in other words the result of the calculation has to go into a new array. But where to put it? The answer was in the dither function but I failed to realize that at the time. I tied allocating the entire frame buffer again, but there's not sufficient RAM for that. The trick is that the frame buffer is allocated for RGB with 1 byte per color per pixel, while the effects only work on Greyscale - 1 byte total per pixel.
I don't know about you but since I'm only an occasional C coder, so things like pointers, addresses and the like really hurt my brain.
So I planned to pass a matrix (only a 3x3 array - in the interest of performance), along with the from and to buffers, and a some other values to help in the calculations. Here's the function signature:
void convolution(mono_buffer_t sourceBuffer, mono_buffer_t targetBuffer, Kernel_t Kernel, signed int scaler, signed int offset)
Then it's just a matter of doing some prep, and calling the convolution code:
convolution(cambuffer + bufstart, cambuffer + bufstart + cambuffmono_offset, Kernel, 5, 0);
And then displaying it - just be tweaking the existing display code to work with my "new" buffer definitions:
monopalette (0,255); dispimage(0, 12, xpixels, ypixels, (img_mono | img_revscan), cambuffer + bufstart + cambuffmono_offset);
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.