1

I got this output from the code below circle.ppm and it has a lot of jaggy edges. I need some type of antialiasing method I believe, but I have trouble getting started.

What would be the simplest way of getting rid of them?

//******************** INCLUDE: ********************

#include <fstream>                      // ofstream
#include <iostream>                     // cin, cout
#include <cmath>                        // sqrt, pow

using namespace std;                    // USING STANDARD NAMESPACE

//******************** DECLARATION OF FUNCTIONS: ********************

bool isInsideCircle(int x,int y);       // CHECKS IF (X,Y) IS INSIDE CIRCLE
int Brightness(int x,int y);            // DISTANCE FROM CENTER


//******************** VARIABLES: ********************

const int WIDTH = 255, HEIGHT = 255;    // WIDTH AND HEIGHT RESOLUTION
const int RADIUS = 100;                 // RADIUS OF CIRCLE

const int CENTER_X = 0.5 * WIDTH;       // CENTER X-COORDINATES
const int CENTER_Y = 0.5 * HEIGHT;      // CENTER Y-COORDINATES

int r, g, b;                            // RED, GREEN AND BLUE

//******************** MAIN FUNCTION: ********************

int main() {

  system("open circle.ppm");            // OPENS THE IMAGE
  system("killall ToyViewer");          // CLOSES THE IMAGE

//******************** PPM SETUP: ********************

  ofstream img ("circle.ppm");          // MAKE THE FILE
  img << "P3" << endl;                  // MAGIC NUMBER
  img << WIDTH << endl;                 // WIDTH RESOLUTION
  img << HEIGHT << endl;                // HEIGHT RESOLUTION
  img << "255" << endl;                 // 0-255 MAX RGB VALUE

//******************** FOR EACH PIXEL: ********************

  for (int y = 0; y < HEIGHT; y++) {

      for (int x = 0; x < WIDTH; x++) {

          if (isInsideCircle(x, y)) {

              r = 50 + Brightness(x, y) % 255;
              g = 50 + Brightness(x, y) % 255;
              b = 50 + Brightness(x, y) % 255;
          }

          else {

              r = 0;
              g = 0;
              b = 0;

          }

          img << r << " " << g << " " << b << endl;
      }
  }

//******************** PROGRAM END: ********************

  system("open circle.ppm"); 
  return 0;

}

//******************** FUNCTIONS: ********************

bool isInsideCircle(int x, int y) {

  if (pow((x - CENTER_X),2) + pow((y - CENTER_Y),2) < pow(RADIUS,2)) {

      return true;

  } else {

      return false;
  }
}

int Brightness(int x, int y) {

  return abs( sqrt( pow((x - CENTER_X),2) + pow((y - CENTER_Y),2)) - RADIUS);

}
Daniel Strul
  • 1,458
  • 8
  • 16
  • The jaddy edges are expected, as you are applying a binary mask to your computed image: points are in = 1, points are out = 0. The problem is that points on the edges of the circle are neither fully in nor fully out: they're on the edge. I've re-tagged your image as `image-processing` so that you may get answers from IP developpers. – Daniel Strul Oct 29 '15 at 12:40

1 Answers1

2

As Daniel points out, you have a sharp drop. Not actually from 1 to 0, but from {50,50,50} to {0,0,0}. That's because of the 50 + Brightness lines.

The easy solution is to use a slightly less sharp drop. Define a Brightness2(x,y) which asymptotically drops from 50 to 0.

int Brightness2(int x, int y) {
  int dx = x - CENTER_X;
  int dy = x - CENTER_Y;
  return 50/(1+(dx*dx+dy*dy-RADIUS*RADIUS));
}
MSalters
  • 173,980
  • 10
  • 155
  • 350
  • That did make it smooth out towards the edge, but didn't really do anything to the pixelated edges. I compared the differences here http://i.imgur.com/tiSjNCj.png – Marcus Mathiassen Oct 29 '15 at 13:49
  • @MarcusMathiassen: Well, images are still made out of pixels, so that's unavoidable. You can however add increase smoothing by using `100/(2+(...` or `150/(3+(...` etc. This will double or triple the width of the smoothed ring. – MSalters Oct 29 '15 at 14:06
  • It is worth noting that this method also makes the circle slightly smaller, since the mask is still the same. – Jørgen Fogh Oct 29 '15 at 15:52
  • @MarcusMathiassen Slightly increase the radius of your mask, that is, in `isInsideCircle`, replace `pow(RADIUS,2)` with something like: `pow(RADIUS+1,2)` – Daniel Strul Oct 29 '15 at 16:33
  • @DanielStrul Hmm, that added some weird stuff on the edge, see here http://i.imgur.com/hC7KBAy.png But i might be doing something wrong. Is this how it is supposed to look: 50 + Brightness(x, y) + Brightness2(x, y) % 255; ? – Marcus Mathiassen Oct 29 '15 at 16:59
  • @MarcusMathiassen No, it looks like it's overshooting :-( – Daniel Strul Oct 29 '15 at 17:05
  • @DanielStrul I think maybe the best method would be something you mentioned first. Downsampling or something like it. – Marcus Mathiassen Oct 29 '15 at 17:13
  • @MarcusMathiassen's I'm not sure. There are several bizarre things with your formula `50 + Brightness(x, y) + Brightness2(x, y) % 255`. Try going back to the original definition of of `isInsideCircle`, and multiply rather than adding, e.g.:`50 + Brightness(x, y)/RADIUS * Brightness2(x, y)` – Daniel Strul Oct 29 '15 at 17:18
  • @JørgenFogh: Actually, it makes it bigger, because this is the formula to use when `! isInsideCircle(x, y)`. – MSalters Oct 29 '15 at 19:36
  • 1
    @MarcusMathiassen: Ah, no, that's entirely not what I intended. I meant `if (isInsideCircle(x, y)) // use 50+ Brightness(x, y) else // use Brightness2(x, y)`. – MSalters Oct 29 '15 at 19:38