Hauptseite   Klassenhierarchie   Auflistung der Dateien  

filterpixel8.cpp

00001 /**********************************************************************************
00002 * Copyright (c) 2003, Matthias Bader and Christoph Rueegg <opendev@cdrnet.ch>     *
00003 * All rights reserved.                                                            *
00004 *                                                                                 *
00005 * Project Website: http://www.cdrnet.net/projects/painter/                        *
00006 *                                                                                 *
00007 * Redistribution and use in source and binary forms, with or without modification,*
00008 * are permitted provided that the following conditions are met:                   *
00009 *                                                                                 *
00010 * 1. Redistributions of source code must retain the above copyright notice,       *
00011 * this list of conditions and the following disclaimer.                           *
00012 *                                                                                 *
00013 * 2. Redistributions in binary form must reproduce the above copyright notice,    *
00014 * this list of conditions and the following disclaimer in the documentation       *
00015 * and/or other materials provided with the distribution.                          *
00016 *                                                                                 *
00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"     *
00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE       *
00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE      *
00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE        *
00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR             *
00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF            *
00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS        *
00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN         *
00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)         *
00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF          *
00027 * THE POSSIBILITY OF SUCH DAMAGE.                                                 *
00028 **********************************************************************************/
00029 
00030 #include "filterpixel8.h"
00031 #include <cmath>
00032 
00033 Pixel8Filter::Pixel8Filter() : ChannelFilter<unsigned char>()
00034 {
00035   alreadyChanged2 = 0;
00036   alreadyChanged4 = 0;
00037   alreadyChanged8 = 0;
00038   average2 = 0;
00039   average4 = 0;
00040   average8 = 0;
00041 }
00042 
00043 Pixel8Filter::~Pixel8Filter()
00044 {
00045   delete alreadyChanged2;
00046   delete alreadyChanged4;
00047   delete alreadyChanged8;
00048   delete average2;
00049   delete average4;
00050   delete average8;
00051 }
00052 
00053 ChannelFilter<unsigned char>* Pixel8Filter::EmptyClone()
00054 {
00055   Pixel8Filter *copy = new Pixel8Filter();
00056   copy->SetSubChannel(GetSubChannel());
00057   return(copy);
00058 }
00059 
00060 void Pixel8Filter::OnMouseEvent(const int button, const int state, int x, int y)
00061 {
00062   if(state != 0 || button != 0)
00063     return;
00064   int width = GetWidth();
00065   int height = GetHeight();         
00066 
00067   alreadyChanged2 = new Channel<int>(height/2+5,width/2+5);
00068   alreadyChanged4 = new Channel<int>(height/4+5,width/4+5);
00069   alreadyChanged8 = new Channel<int>(height/8+5,width/8+5);
00070   average2 = new Channel<int>(height/2+5,width/2+5);
00071   average4 = new Channel<int>(height/4+5,width/4+5);
00072   average8 = new Channel<int>(height/8+5,width/8+5);
00073 
00074   for(int i=0;i<width/2+1;i++)
00075     for(int j=0;j<height/2+1;j++)
00076     {
00077       alreadyChanged2->Set(i,j,0xFFFFFF);
00078       average2->Set(i,j,0);
00079     }
00080   for(int i=0;i<width/4+1;i++)
00081     for(int j=0;j<height/4+1;j++)
00082     {
00083       alreadyChanged4->Set(i,j,0xFFFFFF);
00084       average4->Set(i,j,0);
00085     }
00086   for(int i=0;i<width/8+1;i++)
00087     for(int j=0;j<height/8+1;j++)
00088     {
00089       alreadyChanged8->Set(i,j,0xFFFFFF);
00090       average8->Set(i,j,0);
00091     }
00092 
00093   for (int j=0; j<=(height/8-1); j++)
00094     for (int i=0; i<=(width/8-1); i++)
00095     {
00096       Analyze8x8Area(i*8, j*8);
00097 
00098 
00099       if (alreadyChanged8->Get(i,j)<PIX8_HIGLIM)
00100       {
00101         DrawPixel(i*8, j*8, 8, average8->Get(i,j), 40);
00102       }
00103       else
00104       {
00105         if (alreadyChanged4->Get(i*2+1,j*2+1)<PIX8_MEDLIM)
00106           DrawPixel(i*8+4, j*8+4, 4, average4->Get(i*2+1,j*2+1), 30);
00107         else
00108         {
00109           DrawPixel(i*8+4+2, j*8+4+2, 2, average2->Get(i*4+2+1 ,j*4+2+1), 20);
00110           DrawPixel(i*8+4  , j*8+4+2, 2, average2->Get(i*4+2   ,j*4+2+1), 20);
00111           DrawPixel(i*8+4  , j*8+4  , 2, average2->Get(i*4+2   ,j*4+2  ), 20);
00112           DrawPixel(i*8+4+2, j*8+4  , 2, average2->Get(i*4+2+1 ,j*4+2  ), 20);
00113         }
00114 
00115         if (alreadyChanged4->Get(i*2,j*2+1)<PIX8_MEDLIM)
00116           DrawPixel(i*8  , j*8+4, 4, average4->Get(i*2,j*2+1), 30);
00117         else
00118         {
00119           DrawPixel(i*8+2, j*8+4+2, 2, average2->Get(i*4+1 ,j*4+2+1), 20);
00120           DrawPixel(i*8  , j*8+4+2, 2, average2->Get(i*4   ,j*4+2+1), 20);
00121           DrawPixel(i*8  , j*8+4  , 2, average2->Get(i*4   ,j*4+2  ), 20);
00122           DrawPixel(i*8+2, j*8+4  , 2, average2->Get(i*4+1 ,j*4+2  ), 20);
00123         }
00124 
00125         if (alreadyChanged4->Get(i*2,j*2)<PIX8_MEDLIM)
00126           DrawPixel(i*8  , j*8  , 4, average4->Get(i*2,j*2), 30);
00127         else
00128         {
00129           DrawPixel(i*8+2, j*8+2, 2, average2->Get(i*4+1 ,j*4+1), 20);
00130           DrawPixel(i*8  , j*8+2, 2, average2->Get(i*4   ,j*4+1), 20);
00131           DrawPixel(i*8  , j*8  , 2, average2->Get(i*4   ,j*4  ), 20);
00132           DrawPixel(i*8+2, j*8  , 2, average2->Get(i*4+1 ,j*4  ), 20);
00133         }
00134 
00135         if (alreadyChanged4->Get(i*2+1,j*2)<PIX8_MEDLIM)
00136           DrawPixel(i*8+4, j*8  , 4, average4->Get(i*2+1,j*2), 30);
00137         else
00138         {
00139           DrawPixel(i*8+4+2, j*8+2, 2, average2->Get(i*4+2+1 ,j*4+1), 20);
00140           DrawPixel(i*8+4  , j*8+2, 2, average2->Get(i*4+2   ,j*4+1), 20);
00141           DrawPixel(i*8+4  , j*8  , 2, average2->Get(i*4+2   ,j*4  ), 20);
00142           DrawPixel(i*8+4+2, j*8  , 2, average2->Get(i*4+2+1 ,j*4  ), 20);
00143         }
00144       }
00145     }
00146   
00147   delete alreadyChanged2;
00148   delete alreadyChanged4;
00149   delete alreadyChanged8;
00150   delete average2;
00151   delete average4;
00152   delete average8;
00153   alreadyChanged2 = 0;
00154   alreadyChanged4 = 0;
00155   alreadyChanged8 = 0;
00156   average2 = 0;
00157   average4 = 0;
00158   average8 = 0;
00159 }
00160 
00161 void Pixel8Filter::AnalyzeArea(int *deviation, int *average, int x, int y, int size)
00162 {
00163   *average = *deviation = 0;
00164   for(int i=(x - (x % size)); i<=(x | (size-1)); i++)
00165     for(int j=(y - (y % size)); j<=(y | (size-1)); j++)            //TODO: implement efficient checking for & prevention of off-limit accessing
00166       *average+=Get(i,j);
00167   if (size<8)
00168     *average=*average>>size;                                      //divides average by 4,16 or 64 (>>6).
00169   else
00170     *average=*average>>6;
00171   for(int i=(x - (x % size)); i<=(x | (size-1)); i++)
00172     for(int j=(y - (y % size)); j<=(y | (size-1)); j++)
00173       *deviation+=abs(Get(i,j)-*average);
00174 }
00175 
00176 void Pixel8Filter::Analyze8x8Area(int x, int y)
00177 {
00178   int myX, myY, divX, divY;
00179   int i,j;
00180   int avg=0, dev=0;
00181 
00182   myX=x-(x%8);    //start coordinates of the 8x8 block
00183   myY=y-(y%8);
00184   divX=x/8;
00185   divY=y/8;
00186 
00187   for (i=0; i<4; i++)
00188     for (j=0; j<4; j++)
00189     {
00190       avg = average2->Get(divX*4+i,divY*4+j);
00191       AnalyzeArea(&dev,&avg, myX+2*i, myY+2*j, 2);
00192       alreadyChanged2->Set(divX*4+i,divY*4+j,dev);
00193       average2->Set(divX*4+i,divY*4+j,avg);
00194     }
00195 
00196   for (i=0; i<2; i++)
00197     for (j=0; j<2; j++)
00198       if ((alreadyChanged2->Get(divX*4+i*2,divY*4+ j*2) < PIX8_LOWLIM)  && (alreadyChanged2->Get(divX*4+1+i*2,divY*4+j*2)  < PIX8_LOWLIM) &&
00199           (alreadyChanged2->Get(divX*4+i*2,divY*4+1+j*2) < PIX8_LOWLIM)  && (alreadyChanged2->Get(divX*4+1+i*2,divY*4+1+j*2)  < PIX8_LOWLIM)    )
00200       {
00201         avg = average4->Get(divX*2+i,divY*2+j);
00202         AnalyzeArea(&dev,&avg, myX+4*i, myY+4*j, 4);
00203         alreadyChanged4->Set(divX*2+i,divY*2+j,dev);
00204         average4->Set(divX*2+i,divY*2+j,avg);
00205       }
00206       else                              
00207         alreadyChanged4->Set(divX*2+i,divY*2+j,0xFFFFFF);
00208       average4->Set(divX*2+i,divY*2+j,200);
00209 
00210   if (alreadyChanged4->Get(divX*2,divY*2) < PIX8_MEDLIM   &&  alreadyChanged4->Get(divX*2+1,divY*2) < PIX8_MEDLIM   &&
00211       alreadyChanged4->Get(divX*2,divY*2+1) < PIX8_MEDLIM   &&  alreadyChanged4->Get(divX*2+1,divY*2+1) < PIX8_MEDLIM       )
00212   {
00213     avg = average8->Get(divX,divY);
00214     AnalyzeArea(&dev,&avg, myX, myY, 8);
00215     alreadyChanged8->Set(divX,divY,dev);
00216     average8->Set(divX,divY,avg);
00217   }
00218   else
00219     alreadyChanged8->Set(divX, divY, 0xFFFFFF);
00220   
00221 }
00222 
00223 void Pixel8Filter::DrawPixel(int x, int y, int size, int average, int borderIntensityPercent)
00224 {
00225   int intermediate;
00226   
00227   if (size<=1)
00228   {
00229     for (int i=x; i<=x + size -1; i++)
00230       for (int j=y; j<= y + size -1; j++)
00231       {
00232         Set(i,j,Get(i,j)/2+average/2+3);;
00233       }
00234   }
00235   else
00236   {
00237   for (int i=x; i<x + size -1; i++)
00238     for (int j=y; j< y + size -1; j++)
00239     {
00240       intermediate=Get(i,j)/2+average/2+4;
00241       Set(i,j, intermediate >= 255 ?  Get(i,j)/2+average/2 : intermediate);
00242     }
00243       
00244   for (int i=x; i<=x + size-1; i++)
00245     Set(i,y+size-1, average>borderIntensityPercent ? Get(i,y+size-1)/2 + (average-borderIntensityPercent)/2 : 0);
00246 
00247   for (int j=y; j<y +size -1; j++)
00248     Set(x+size-1,j,average>borderIntensityPercent ? Get(x+size-1,j)/2 + (average-borderIntensityPercent)/2 : 0);
00249   }
00250 }
00251 
00252 
00253 

Erzeugt am Fri Jan 31 15:27:35 2003 für OOP Miniprojekt von doxygen1.3-rc2