class MakeOutputImage – the code

//  this class is a framework for generating output images
//needs the class ProgressReport

class MakeOutputImage{
  ProgressReport progress;
  PImage thisImage;
  int thisWidth, thisHeight;
  int rot,gruen,blau;
  int startTime,lastTime;  
  int[] inRed,inGreen,inBlue;
  int[] redPlus,redZero,redMinus;  
  int[] greenPlus,greenZero,greenMinus;  
  int[] bluePlus,blueZero,blueMinus;  

  MakeOutputImage(PImage output){
    thisImage=output;
    thisWidth=output.width;
    thisHeight=output.height;
    progress=new ProgressReport(thisHeight,"Output image");
    inRed=new int[2*thisWidth+1];
    inGreen=new int[2*thisWidth+1];
    inBlue=new int[2*thisWidth+1];
    redPlus=new int[thisWidth];
    redZero=new int[thisWidth];
    redMinus=new int[thisWidth];
    greenPlus=new int[thisWidth];
    greenZero=new int[thisWidth];
    greenMinus=new int[thisWidth];
    bluePlus=new int[thisWidth];
    blueZero=new int[thisWidth];
    blueMinus=new int[thisWidth];
  }

//----------------------------------------------------------------------------
//  getting the color at image coordinates i,j
  color theImage(float i,float j){
    return ripples(i,j);
  }

//----------------------------------------------------
//  antialiasing by sampling the image at double frequency and decimation
//  using the tent filter kernel
//  slightly better than block kernel
//  requires the same computer time, but more programming effort

  void samplingColors(float j){
    int thisWidth2=2*thisWidth;
    color f;
    for (int i=0;i<=thisWidth2;i++){  // sampling the image and separating colors
      f=theImage(0.5*(i-1),j);
      inRed[i]=((f >> 16) & 0xFF);
      inGreen[i]=((f >> 8) & 0xFF);
      inBlue[i]=((f) & 0xFF);
    }
  }

  void lineZero(float j){
    samplingColors(j);
    int in;
    for (int i=0;i<thisWidth;i++){
      in=1+2*i;
      redZero[i]=inRed[in-1]+2*inRed[in]+inRed[in+1];
      greenZero[i]=inGreen[in-1]+2*inGreen[in]+inGreen[in+1];
      blueZero[i]=inBlue[in-1]+2*inBlue[in]+inBlue[in+1];
    }    
  }

  void linePlus(float j){
    samplingColors(j+0.5);
    int in;
    for (int i=0;i<thisWidth;i++){
      in=1+2*i;
      redPlus[i]=inRed[in-1]+2*inRed[in]+inRed[in+1];
      greenPlus[i]=inGreen[in-1]+2*inGreen[in]+inGreen[in+1];
      bluePlus[i]=inBlue[in-1]+2*inBlue[in]+inBlue[in+1];
    }    
  }

  void lineMinusPlus(){
    for (int i=0;i<thisWidth;i++){
      redMinus[i]=redPlus[i];
      greenMinus[i]=greenPlus[i];
      blueMinus[i]=bluePlus[i];
    }    
  }

//  antialiasing with the tent formula
//  using nine points for each pixel
  void tent(){
  thisImage.loadPixels();
  progress.reset();
  float norm=1./float(16);
  int i,j,jWidth;
  linePlus(-1);
  for(j=0;j<thisHeight;j++){
    jWidth=j*thisWidth;
    lineZero(j);
    lineMinusPlus();
    linePlus(j);
    for (i=0;i<thisWidth;i++){
      rot=round(norm*(redMinus[i]+2*redZero[i]+redPlus[i]));
      gruen=round(norm*(greenMinus[i]+2*greenZero[i]+greenPlus[i]));
      blau=round(norm*(blueMinus[i]+2*blueZero[i]+bluePlus[i]));
      thisImage.pixels[i+jWidth]=( 255<<24|rot<<16 | gruen<<8 | blau);
    }
    progress.report(j);
  }  
  thisImage.updatePixels();
  } 

//--------------------------------------------------------------------------------------
//  antialiasing and smoothing, sampling and block decimation by 2
//  using four points for each pixel

  void block(){
  thisImage.loadPixels();
  progress.reset();
  float norm=1./float(16);
  int i,j,jWidth;
  color f11,f12,f21,f22;
  for(j=0;j<thisHeight;j++){
    jWidth=j*thisWidth;
    for (i=0;i<thisWidth;i++){
      f11=theImage(i+0.25,j+0.25);
      f12=theImage(i+0.25,j-0.25);
      f21=theImage(i-0.25,j+0.25);
      f22=theImage(i-0.25,j-0.25);
      rot=round(0.25*((((f11 >> 16) & 0xFF)+((f12 >> 16) & 0xFF))+((f21 >> 16) & 0xFF)+((f22 >> 16) & 0xFF)));
      gruen=round(0.25*((((f11 >> 8) & 0xFF)+((f12 >> 8) & 0xFF))+((f21 >> 8) & 0xFF)+((f22 >> 8) & 0xFF)));
      blau=round(0.25*((((f11) & 0xFF)+((f12) & 0xFF))+((f21) & 0xFF)+((f22) & 0xFF)));
      thisImage.pixels[i+jWidth]=( 255<<24|rot<<16 | gruen<<8 | blau);
    }
    progress.report(j);
  }  
  thisImage.updatePixels();
  } 

 //--------------------------------------------------------------------------------------
 //   without antialiasing, for reference 

 void simple(){
  thisImage.loadPixels();
  progress.reset();
  int i,j,jWidth;
  for(j=0;j<thisHeight;j++){
    jWidth=j*thisWidth;
    for (i=0;i<thisWidth;i++){
      thisImage.pixels[i+jWidth]=theImage(i,j);
    }
    progress.report(j);
  }  
  thisImage.updatePixels();
  }
}
This entry was posted in programming and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s