4

So I have GUI Class that will call another class called ImageProcessor that contains a bunch functions that will perform image processing algorithms like edgeDetection, gaussianblur, contourfinding, contour map generations, etc. The GUI passes an image to ImageProcessor, which performs one of those algorithm on it and it returns the image back to the GUI to display. So essentially ImageProcessor is a library of independent image processing functions right now.

It is called in the GUI like so

Image image = ImageProcessor.EdgeDetection(oldImage);

Some of the algorithms procedures require many functions, and some can be done in a single function or even one line.

All these functions for the algorithms jam packed into ImageProcessor can be pretty messy, and ImageProcessor doesn't sound it should be a library. So I was thinking about making every algorithm be a class with a shared interface say IAlgorithm. Then I pass the IAlgorithm interface from the GUI to the ImageProcessor.

public interface IAlgorithm{
   public Image Process();
}
public class ImageProcessor{

  public Image Process(IAlgorithm TheAlgorithm){
        return IAlgorithm.Process();
  }
}

Calling in the GUI like so

Image image = ImageProcessor.Process(new EdgeDetection(oldImage));

I think it makes sense in an object point of view, but the problem is I'll end up with some classes that are just one function. What do you think is a better design, or are they both crap and you have a much better idea? Thanks!

  • Classes with a single function are no problem (you can nest them in a single file, at least in Java). Using classes gives you more flexibility (imagine the user will define a macro: with classes you simply create a list like (new EdgeDetection(), new SimpleSharpening(4), new Rotation(90)). Classes give you more flexibility (which you mightn't need). – maaartinus Nov 1 '13 at 9:15
5

What you're dealing with here aren't objects, they're functions. They take arguments and return something of type Image, they don't hide data or encapsulate anything. Some OO people will tell you that "everything is an object", but they're wrong.

The arguments aren't always going to be the same either; you could have a blur function that takes an image and a float that tells it how much blur to apply, or a fade function that takes two images and a float that tells it how much of image2 to blend into image1. I don't think the idea of an interface works if the functions don't take the same arguments.

Treating them like functions is also more readable than the other two approaches:

Image image = ImageProcessor.Process(new EdgeDetection(oldImage));

Image image = ImageProcessor.EdgeDetection(oldImage);

Image image = edgeDetect(oldImage);

If you're using Java, it may not let you have free-standing functions, but you can use your original approach with static import statements to avoid having to prefix everything with ImageProcessor. all the time.

Your ImageProcessor isn't really a class (you can't use it to make objects), it's a convenient container for some related functions. You're being tempted to split it up into pieces because you're thinking of it as a single large thing, but it's already split into pieces: it's just that the pieces are functions, not objects or classes.

1

IMO the first scenerio is more readable and easy to understand

Image image = ImageProcessor.EdgeDetection(oldImage);

a simple utility method call

while the second introduces complexity that does not seem to serve any purpose

1

I don't know if my solution could help you, but I think I'll create an abstraction:

interface ImageEffect {

    Image apply(Image source);

}

and then:

class EdgeDetection implements ImageEffect {
    ...
}

class GaussianBlur implements ImageEffect {
    ...
}

But, if you have only 2 or 3 effects I think you could simply create an object:

class Picture {

    private Image image;

    public Picture(Image image) {
        this.image = image;
    }

    public Picture edgeDetection() {
        this.image = [...]
    }

    public Picture gaussianBlur() {
        this.image = [...]
    }

    public Image toImage() {
        return image;
    }

}

so that in the end you can call something like this:

[...]
new Picture(myimage)
    .edgeDetection()
    .gaussianBlur()
    .toImage();
[...]

Why I suggest 2 ways to solve the same problem? The reason is that the solution you need depends on what "forces" are engaged in your software. You are the only one that can manage this "forces" and the design you'll create it will be simply a "side effect". I suggest you to use TDD to find the design good for you.

  • Welcome to Programmers. We encourage responses that explain the why along with the what. I think you have the foundation of a great answer here, but it would help if you edited you answer and explained why this approach would better meet the OP's needs. – user53019 Apr 2 '14 at 22:26
  • 1
    One potential nice thing about this, depending on how it'll be used, is the constructor for GaussianBlur can take a radius, and each effect can have whatever number of parameters, providing an object that can be used to process any number of images the same way. In contrast, a function taking all the parameters each call would have to repeat any precomputation, e.g. convolution kernels or lookup tables. While the idea of an ImageProcessor being a function not an object seems reasonable, there is this potential need for state, to hold precomputed data. – DarenW Apr 3 '14 at 3:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.