GithubHelp home page GithubHelp logo

faccha's People

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

faccha's Issues

Implement unit tests

We should write some unit tests to make sure that our algorithms/transformations are working correctly.

Rewrite the interface for users

So this is going to be much text...

We should really try to rewrite the API in a way that makes it easier to use and more error safe.

Some things that should be kept in mind:

  1. Prefer compile time errors to runtime errors.
  2. Keep runtime overhead low.

Status:

  • Implemented 1)
  • Implemented 2)
  • Implemented 3)
  • Implemented 4)
  • Implemented 5)

So the basic idea I had was the following:

    1. We make a struct Pixel or name it Point. It should just contain the x and y coordinates of a pixel.
    • Why do we even need this struct ? If we have a function that takes something like the following as Parameters: void f(unsinged x, unsigned y, unsigned size) it's easy to pass the parameters in the wrong order. If we also define a Size or Bounds struct that should not happen anymore and we'll get compile time errors instead.
    • Priority: Low
    • Things to still consider: Whether we let a Pixel take an Color template argument, or whether a Color inherits from a Pixel.
    1. Then we define a Color struct. Currently we need RgbColor and GrayColor.
    • Why do we even need this ? To abstract an Image over that. An Image should not have much overhead and thus we shouldn't always store the RGB value of every Pixel, if it's not needed.
    • Priority: High
    • Things to still consider: See above.
    1. After that we need to define an Image class. An Image should provide methods for creating it, converting it to an Image of another color type, cloning it and iterating/changing Pixels. An Image should take a template parameter that specifies the Color that is used.
    • Why do we even need this ? To have a nice and clean API for images of any color type.
    • Priority: High
    • Things to still consider: None ? Maybe it would be better to define this as a Concept, but they won't be in C++ in the near future.
    1. Then we define what an "Algorithm" is for an Image and what's required to implement one.
      I would suggest, that an Algorithm on it's most basic level is just something that needs an Image and maybe modifies it. An Algorithm can also have state (i.e. input parameters) that changes the way it behaves. We'll see later why I call it "state". So if we take ImageFramework::getRGBVariance for an example. The state of that would be int& rVar; int& gVar; int& bVar;. The input would be a const Image& (as it's not actually modified).
    • Why do we even need this ? We need a uniform way of running algorithms. If we would just define them as functions that take parameters directly we wouldn't be able to do what is done in the next step.
    • Priority: High
    • Things to consider: We could make each algorithm define whether they need to modify an Image or not, to give better diagnostics if an const Image& is passed in, but the algorithm would need to mutate it. Important: We could make an algorithm return false; on an error, so that we can cancel an chain of algorithms early if an error occurrs and we won't need exceptions for that.

So our "Algorithm" would look something like this:

namespace detail {
struct RGBVariance{
     int& rOut;
     int& gOut;
     int& bOut;
     // or RgbColor& colorOut

     // This COULD contain a function like
     static RGBVariance createVariance(...)
     // that we can "import" into the outer namespace, so the user doesn't get access
     // to this whole class, if he just does "using namespace image::algorithms;".
     // He would then rather get access to all the creation functions like createVariance and so on.

     // Constructor that sets the input/output parameters needed.
     RGBVariance(...)

     // Actual algorithm
     template<typename TColor>
     void operator()(const Image<TColor>& img) {
         // This function would cause an compile time error by doing some magic only if it's called.
         // Because we don't want to run "**RGB**Variance" on an image of ANY color.
     }

     template<>
     void operator()(const Image<RgbColor>& rgbImg) {
         // This function is only called for RgbImages. So it could compute the variance and set
         // the output values.
     }

     // We could be more clever, and define this algorithm just as "Variance" and then also implement
     // it for the GrayScaleColor. Then the output parameter would need to be pointers, as they can be
     // nullptr, but that won't change much. And we would define a second constructor that just takes a
     // GrayColor& out.
};
}
    1. And the final step to make the algorithms nicely usable is to define two functions that allow chaining of algorithms.
    • Why do we even need this ? To make user code look nice. User code would look something like this.
    • Priority: High
    • Things to consider: ???

Implementation:

template<typename... TAlgorithms>
auto createAlgorithm(TAlgorithms&&... algorithmsToRun){
    // some magic here I won't write out while still in the planning face, that makes a chain of lambdas
    // and returns a lambda that takes a single "Image&" or "const Image&" argument.
    // algorithmsToRun would need to be things for wich we can call algorithm::operator()(img);
}

template<template<typename> typename TImage, typename... TAlgorithms>
bool /*<- if we decide to return bools, else void*/ transformImage(TImage& img, TAlgorithms&&... algorithmsToRun) {
     return createAlgorithm(std::forward<TAlgorithms>(algorithmsToRun)...)(img);
}

User code:

using namespace image::algorithms;
using namespace image::loaders;

void f() {
    auto image = loadImageFromFile<RgbColor>("myImage.png");
    auto rOut = 0;
    auto gOut = 0;
    auto bOut = 0;
    // or auto colorOut = RgbColor{};
    auto success = transformImage(image,
             createConvolutionFilter(filter, ...),
             invertImage(),
             getRGBVariance(rOut, gOut, bOut));
}

Please comment on this an post any ideas/suggestions/improvements/questions.

Move Win32_Binary

You should move the ZIP file from the Win32_Binary folder to a GitHub release.

That's better because you can't "forget" to update the bin if you update your code as
GitHub's releases are in fact just git tags. (So a release will always point to a specific commit).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.