algorytm.org

Implementacja w C/C++

Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Dithering dla obrazów kolorowych - Implementacja w C/C++
Ocena użytkownikóww: *****  / 1
SłabyŚwietny
Nadesłany przez Tomasz Lubiński, 30 lipca 2009 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.
Pobierz pełne rozwiązanie.

Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.

Dithering - C++/Unit1.cpp:
//Tomasz Lubiński (C) 2009
// www.algorytm.org
//Algorytmy Ditheringu
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
typedef struct Pixel
{
   Byte b;
   Byte g;
   Byte r;
   Byte reserved;
} TPixel;


/* by uniknac indeksow mniejszych od zera w tablicy bledow */
#define SHIFT 3

/* zmienne potrzebne w trakcie obliczen */
TPixel colors[16];
float eb[253][232], eg[253][232], er[253][232];

float dif[11][3][6] =
{
   {
      {0,        0,        0,        0,        7.0/16.0, 0},
      {0,        0,        3.0/16.0, 5.0/16.0, 1.0/16.0, 0},
      {0,        0       , 0,        0,        0,        0}
   },
   {
      {0,        0,        0,        0,        7.0/48.0, 5.0/48.0},
      {0,        3.0/48.0, 5.0/48.0, 7.0/48.0, 5.0/48.0, 3.0/48.0},
      {0,        1.0/48.0, 3.0/48.0, 5.0/48.0, 3.0/48.0, 1.0/48.0}
   },
   {
      {0,        0,        0,        0,        8.0/42.0, 4.0/42.0},
      {0,        2.0/42.0, 4.0/42.0, 8.0/42.0, 4.0/42.0, 2.0/42.0},
      {0,        1.0/42.0, 2.0/42.0, 4.0/42.0, 2.0/42.0, 1.0/42.0}
   },
   {
      {0,        0,        0,        0,        8.0/32.0, 4.0/32.0},
      {0,        2.0/32.0, 4.0/32.0, 8.0/32.0, 4.0/32.0, 2.0/32.0},
      {0,        0       , 0,        0,        0,        0}
   },
   {
      {0,        0,        0,        0,        7.0/16.0, 0},
      {0,        1.0/16.0, 3.0/16.0, 5.0/16.0, 0,        0},
      {0,        0       , 0,        0,        0,        0}
   },
   {
      {0,        0,        0,        0,        5.0/32.0, 3.0/32.0},
      {0,        2.0/32.0, 4.0/32.0, 5.0/32.0, 4.0/32.0, 2.0/32.0},
      {0,        0       , 2.0/32.0, 3.0/32.0, 2.0/32.0, 0}
   },
   {
      {0,        0,        0,        0,        4.0/16.0, 3.0/16.0},
      {0,        1.0/16.0, 2.0/16.0, 3.0/16.0, 2.0/16.0, 1.0/16.0},
      {0,        0       , 0,        0,        0,        0}
   },
   {
      {0,        0,        0,        0,        2.0/4.0,  0},
      {0,        0,        1.0/4.0,  1.0/4.0,  0,        0},
      {0,        0       , 0,        0,        0,        0}
   },
   {
      {0,        0,        0,        0,        1.0/8.0,  1.0/8.0},
      {0,        0,        1.0/8.0,  1.0/8.0,  1.0/8.0,  0},
      {0,        0,        0,        1.0/8.0,  0,        0}
   },
   {
      {0,        0,        0,        0,        4.0/8.0,  0},
      {0,        1.0/8.0,  1.0/8.0,  2.0/8.0,  0,        0},
      {0,        0,        0,        0,        0,        0}
   },
   {
      {0,        0,        0,        0,        8.0/16.0, 0},
      {1.0/16.0, 1.0/16.0, 2.0/16.0, 4.0/16.0, 0,        0},
      {0,        0,        0,        0,        0,        0}
   }
};

//---------------------------------------------------------------------------
//pobiera kolory zdefiniowane przez uzytkownika
void getColors()
{
   int n, i;

   for (i=0; i<Form1->ComponentCount; i++)
   {
      if (Form1->Components[i]->Name.SubString(0, 5) =="Shape")
      {
         n = StrToInt(Form1->Components[i]->Name.SubString(6, 2)) - 1;
         colors[n].b = GetBValue(((TShape*)Form1->Components[i])->Brush->Color);
         colors[n].g = GetGValue(((TShape*)Form1->Components[i])->Brush->Color);
         colors[n].r = GetRValue(((TShape*)Form1->Components[i])->Brush->Color);
         colors[n].reserved = 0;
      }
   }
}
//---------------------------------------------------------------------------
//znajduje kolor w palecie najblizszy zadanemu pikslowi
int findNearest(float b, float g, float r, int cnt)
{
   int i, result;
   float d, tmp;

   d = (colors[0].b - b) * (colors[0].b - b);
   d += (colors[0].g - g) * (colors[0].g - g);
   d += (colors[0].r - r) * (colors[0].r - r);

   result = 0;

   for (i=1; i<cnt; i++)
   {
      tmp = (colors[i].b - b) * (colors[i].b - b);
      tmp += (colors[i].g - g) * (colors[i].g - g);
      tmp += (colors[i].r - r) * (colors[i].r - r);

      if (d > tmp)
      {
         d = tmp;
         result = i;
      }
   }

   return result;
}
//---------------------------------------------------------------------------
//ucina podana wartosc do zakresu 0-255 (dopuszczalne wartosci dla piksla)
float clip(float x)
{
   if (x > 255) return 255;
   if (x < 0) return 0;
   return x;
}
//---------------------------------------------------------------------------
//propaguje blad do komorek sasiednich
void propagateError(int alg, float w, float e[253][232], int i, int j)
{
   e[i+1+SHIFT][j  ] = e[i+1+SHIFT][j  ] + (w*dif[alg][0][4]);
   e[i+2+SHIFT][j  ] = e[i+2+SHIFT][j  ] + (w*dif[alg][0][5]);

   e[i-3+SHIFT][j+1] = e[i-3+SHIFT][j+1] + (w*dif[alg][1][0]);
   e[i-2+SHIFT][j+1] = e[i-2+SHIFT][j+1] + (w*dif[alg][1][1]);
   e[i-1+SHIFT][j+1] = e[i-1+SHIFT][j+1] + (w*dif[alg][1][2]);
   e[i  +SHIFT][j+1] = e[i  +SHIFT][j+1] + (w*dif[alg][1][3]);
   e[i+1+SHIFT][j+1] = e[i+1+SHIFT][j+1] + (w*dif[alg][1][4]);
   e[i+2+SHIFT][j+1] = e[i+2+SHIFT][j+1] + (w*dif[alg][1][5]);

   e[i-3+SHIFT][j+2] = e[i-3+SHIFT][j+2] + (w*dif[alg][2][0]);
   e[i-2+SHIFT][j+2] = e[i-2+SHIFT][j+2] + (w*dif[alg][2][1]);
   e[i-1+SHIFT][j+2] = e[i-1+SHIFT][j+2] + (w*dif[alg][2][2]);
   e[i  +SHIFT][j+2] = e[i  +SHIFT][j+2] + (w*dif[alg][2][3]);
   e[i+1+SHIFT][j+2] = e[i+1+SHIFT][j+2] + (w*dif[alg][2][4]);
   e[i+2+SHIFT][j+2] = e[i+2+SHIFT][j+2] + (w*dif[alg][2][5]);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
int i,j,cnt,alg;
float wb, wg, wr;
TPixel *pixelOrg, *pixelNew, white, black;

//przygotuj wartosci kolorow z palety
getColors();

//przygotuj obrazy wynikowe
Image2->Canvas->Brush->Color = clWhite;
Image2->Canvas->Rectangle(0, 0, Image2->Width, Image2->Height);
Image2->Picture->Bitmap->PixelFormat = pf32bit;

Image3->Canvas->Brush->Color = clWhite;
Image3->Canvas->Rectangle(0, 0, Image3->Width, Image3->Height);
Image3->Picture->Bitmap->PixelFormat = pf32bit;

//przygotuj format obrazu zrodlowego
Image1->Picture->Bitmap->PixelFormat = pf32bit;

//pobierz liczbe kolorow i algorytm do uzycia
cnt = StrToInt(Form1->Edit1->Text);
alg = Form1->ComboBox1->ItemIndex;

//najblizsze sasiedztwo
for (j=0; j<230; j++){
        pixelOrg = (TPixel *)Image1->Picture->Bitmap->ScanLine[j];
        pixelNew = (TPixel *)Image2->Picture->Bitmap->ScanLine[j];
        for (i=0; i<248; i++){
                *pixelNew = colors[findNearest(pixelOrg->b, pixelOrg->g, pixelOrg->r, cnt)];
                pixelOrg++;
                pixelNew++;
                }
        }

//dithering
memset(eb, 0, sizeof(eb));
memset(eg, 0, sizeof(eg));
memset(er, 0, sizeof(er));

for (j=0; j<230; j++){
        pixelOrg = (TPixel *)Image1->Picture->Bitmap->ScanLine[j];
        pixelNew = (TPixel *)Image3->Picture->Bitmap->ScanLine[j];
        for (i=0; i<248; i++){
                *pixelNew = colors[findNearest(clip(pixelOrg->b + eb[i+SHIFT][j]),
                                               clip(pixelOrg->g + eg[i+SHIFT][j]),
                                               clip(pixelOrg->r + er[i+SHIFT][j]), cnt)];

                propagateError(alg, clip(pixelOrg->b + eb[i+SHIFT][j]) - pixelNew->b , eb, i, j);
                propagateError(alg, clip(pixelOrg->g + eg[i+SHIFT][j]) - pixelNew->g , eg, i, j);
                propagateError(alg, clip(pixelOrg->r + er[i+SHIFT][j]) - pixelNew->r , er, i, j);

                pixelOrg++;
                pixelNew++;
        }
}
}
//---------------------------------------------------------------------------
// Dialog umozliwiajacy zmiane palety barw
void __fastcall TForm1::ShapeMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
     if (ColorDialog1->Execute())
     {
        ((TShape*)Sender)->Brush->Color = ColorDialog1->Color;
     }
}
//---------------------------------------------------------------------------
//Pokazywanie i ukrywanie probek z palety barw
void __fastcall TForm1::Edit1Change(TObject *Sender)
{
   int cnt, n, i;

   cnt = StrToInt(Edit1->Text);

   for (i=0; i<Form1->ComponentCount; i++)
   {
      if (Components[i]->Name.SubString(0, 5) =="Shape")
      {
         n = StrToInt(Components[i]->Name.SubString(6, 2));
         if (n <= cnt) ((TShape*)Components[i])->Visible = true;
            else ((TShape*)Components[i])->Visible = false;
      }
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Label6Click(TObject *Sender)
{
 ShellExecute(Application->Handle,
             "open",
             "http://www.algorytm.org",
             NULL,
             NULL,
             SW_NORMAL);
}
//---------------------------------------------------------------------------

Dodaj komentarz