home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2003 November
/
PCWK1103B.iso
/
PCWK-txt
/
Warsztat_Cpp_Builder
/
fotoretusz.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2003-10-02
|
9KB
|
363 lines
/*
Ten plik ƒr≤d│owy mo┐e byc dowolnie wykorzystywany, pod warunkiem,
┐e ka┐da aplikacja zbudowana z jego wykorzystaniem zawieraµ bΩdzie
informacje o pochodzeniu niniejszego zestawu funkcji.
Pawe│ Br╣goszewski, PC World Kompuer 11/2003
*/
#include "fotoretusz.h"
#include "vcl\Math.hpp"
#ifndef sqr
#define sqr(A) (A)*(A)
#endif
//
// Zmiana jasnosci bitmapy bmp o wartosc val
//
int DostosujJasnosc( Graphics::TBitmap *bmp, int val )
{
int wysokosc, szerokosc;
int r,g,b;
wysokosc = bmp->Height;
szerokosc = bmp->Width;
for( int i=0; i<wysokosc; i++ )
{
RGBQUAD *wiersz = (RGBQUAD *) bmp->ScanLine[i];
for( int j=0; j<szerokosc; j++ )
{
//pobierz sk│adowe RGB
b = wiersz[j].rgbBlue;
g = wiersz[j].rgbGreen;
r = wiersz[j].rgbRed;
r += val;
g += val;
b += val;
r = (r>255)?255:(r<0)?0:r;
b = (b>255)?255:(b<0)?0:b;
g = (g>255)?255:(g<0)?0:g;
//przejdz do nastΩpnego piksela
wiersz[j].rgbBlue = (BYTE) b;
wiersz[j].rgbGreen = (BYTE) g;
wiersz[j].rgbRed = (BYTE) r;
}
}
} //DostosujJasnosc
//
// Zmiana kontrastu bitmapy bmp o wartosc val
//
int DostosujKontrast( Graphics::TBitmap *bmp, int val )
{
int wysokosc, szerokosc;
double v = 1.2725*val;
double v1 = 255/(255-2*v);
double v2 = (255+2*v)/255;
wysokosc = bmp->Height;
szerokosc = bmp->Width;
for( int i=0; i<wysokosc; i++ )
{
RGBQUAD *wiersz = (RGBQUAD *) bmp->ScanLine[i];
for( int j=0; j<szerokosc; j++ )
{
//pobierz sk│adowe RGB
int b = wiersz[j].rgbBlue;
int g = wiersz[j].rgbGreen;
int r = wiersz[j].rgbRed;
//zmodyfikuj sk│adowe r,g,b
if(v>0)
{
r = (r<v)?0:(r>255-v)?255:v1*(r-v);
g = (g<v)?0:(g>255-v)?255:v1*(g-v);
b = (b<v)?0:(b>255-v)?255:v1*(b-v);
}
else if(v<0)
{
r = -v+v2*r;
g = -v+v2*g;
b = -v+v2*b;
}
//sprawdƒ zakresy
r = (r>255)?255:(r<0)?0:r;
b = (b>255)?255:(b<0)?0:b;
g = (g>255)?255:(g<0)?0:g;
//przejdz do nastΩpnego piksela
wiersz[j].rgbBlue = (BYTE) b;
wiersz[j].rgbGreen = (BYTE) g;
wiersz[j].rgbRed = (BYTE) r;
}
}
} //DostosujKontrast
//
// Zmiana nasycenia kolor≤w o wartosv val
//
int DostosujNasycenie( Graphics::TBitmap *bmp, int val )
{
int wysokosc, szerokosc;
double x = 1.0+val/100.0;
wysokosc = bmp->Height;
szerokosc = bmp->Width;
for( int i=0; i<wysokosc; i++ )
{
RGBQUAD *wiersz = (RGBQUAD *) bmp->ScanLine[i];
for( int j=0; j<szerokosc; j++ )
{
//pobierz sk│adowe RGB
int b = wiersz[j].rgbBlue;
int g = wiersz[j].rgbGreen;
int r = wiersz[j].rgbRed;
int szary = (r+g+b)/3.0;
r = szary + (r-szary)*x;
g = szary + (g-szary)*x;
b = szary + (b-szary)*x;
r = (r>255)?255:(r<0)?0:r;
b = (b>255)?255:(b<0)?0:b;
g = (g>255)?255:(g<0)?0:g;
//przejdz do nastΩpnego piksela
wiersz[j].rgbBlue = (BYTE) b;
wiersz[j].rgbGreen = (BYTE) g;
wiersz[j].rgbRed = (BYTE) r;
}
}
} //DostosujNasycenie
// Przygotuj Miniature
// funkcja tworzy miniature z obrazka oryginal, zapisuj╣c j╣ w miniatura
// miniature ma wymiary szerokosc,wysokosc
int PrzygotujMiniature( Graphics::TBitmap *oryginal, Graphics::TBitmap *miniatura,int szerokosc, int wysokosc)
{
TMemoryStream *pms = new TMemoryStream;
if( szerokosc>0 && wysokosc>0 )
{
pms->Position = 0;
oryginal->SaveToStream(pms);
pms->Position = 0;
miniatura->LoadFromStream( pms );
double skok_wys = oryginal->Height/(double)wysokosc;
double skok_szer = oryginal->Width/(double)szerokosc;
miniatura->Width = szerokosc;
miniatura->Height = wysokosc;
int *wiersz_oryginal,*wiersz_min;
for( int i=0; i<wysokosc; i++)
{
wiersz_min = (int *) miniatura->ScanLine[i];
wiersz_oryginal = (int *) oryginal->ScanLine[ (int)(i*skok_wys) ];
for( int j=0; j<szerokosc; j++)
{
wiersz_min[j] = wiersz_oryginal[ (int)(j*skok_szer) ];
}
}
}
delete pms;
} //PrzygotujMiniature
//
// Zmien balans kolorow wg xr, xg i xb, odpowiednio modyfikuj╣cych
// sk│adowe R, G i B
//
int DostosujBalans( Graphics::TBitmap *bmp, int xr, int xg, int xb )
{
int wysokosc, szerokosc;
int r,g,b;
wysokosc = bmp->Height;
szerokosc = bmp->Width;
for( int i=0; i<wysokosc; i++ )
{
RGBQUAD *wiersz = (RGBQUAD *) bmp->ScanLine[i];
for( int j=0; j<szerokosc; j++ )
{
//pobierz sk│adowe RGB
int b = wiersz[j].rgbBlue;
int g = wiersz[j].rgbGreen;
int r = wiersz[j].rgbRed;
r += xr;
g += xg;
b += xb;
r = (r>255)?255:(r<0)?0:r;
b = (b>255)?255:(b<0)?0:b;
g = (g>255)?255:(g<0)?0:g;
//przejdz do nastΩpnego piksela
wiersz[j].rgbBlue = (BYTE) b;
wiersz[j].rgbGreen = (BYTE) g;
wiersz[j].rgbRed = (BYTE) r;
}
}
} //DostosujBalans
//
// Przeksztalc bitmapΩ bmp na jej negatyw
//
int Negatyw( Graphics::TBitmap *bmp)
{
int wysokosc, szerokosc;
wysokosc = bmp->Height;
szerokosc = bmp->Width;
for( int i=0; i<wysokosc; i++ )
{
RGBQUAD *wiersz = (RGBQUAD *) bmp->ScanLine[i];
for( int j=0; j<szerokosc; j++ )
{
// tutaj uzyty jest operator negacji bitowej!
wiersz[j].rgbBlue = ~wiersz[j].rgbBlue;
wiersz[j].rgbGreen = ~wiersz[j].rgbGreen;
wiersz[j].rgbRed = ~wiersz[j].rgbRed;
}
}
}//Negatyw
//
// zmien bitmapΩ bmp na obraz w odcieniach szarosci
//
int OdcienieSzarosci( Graphics::TBitmap *bmp)
{
int wysokosc, szerokosc;
int szary;
wysokosc = bmp->Height;
szerokosc = bmp->Width;
for( int i=0; i<wysokosc; i++ )
{
RGBQUAD *wiersz = (RGBQUAD *) bmp->ScanLine[i];
for( int j=0; j<szerokosc; j++ )
{
// oblicz poziom szarosci piksela
szary = (wiersz[j].rgbBlue+wiersz[j].rgbGreen+wiersz[j].rgbRed)/3;
// podstaw t╣ sam╣ wartosc dla wszystkich skladowych
wiersz[j].rgbBlue = szary;
wiersz[j].rgbGreen = szary;
wiersz[j].rgbRed = szary;
}
}
}//OdcienieSzarosci
//
// Filtr3x3 przektsztalca bitmape bmp wg filtru filtr[3][3] i zapisuje
// wynik w outbmp
//
int Filtr3x3( Graphics::TBitmap *bmp, Graphics::TBitmap *outbmp, double filtr[3][3] )
{
int wysokosc, szerokosc;
int i,j;
RGBQUAD *piksel[3];
wysokosc = bmp->Height;
szerokosc = bmp->Width;
//outbmp->Width = szerokosc;
//outbmp->Height = szerokosc;
double suma = 0;
// oblicz sume elementow tablicy filtru
for( i=0; i<3; i++)
for( j=0; j<3; j++)
suma += filtr[i][j];
for( i=0; i<wysokosc; i++ )
{
// *wiersz to wskaznik do WYJSCIOWEJ bitmapy
RGBQUAD *wiersz = (RGBQUAD *) outbmp->ScanLine[i];
// pobierz piksel i jego s╣siad≤w
// zwracaj╣c uwagΩ na przekroczenie granic obrazka
// *piksel wksazuje na elementy WEJSCIOWEJ bitmapy
piksel[1] = (RGBQUAD *) bmp->ScanLine[i];
if(i>0)
piksel[0] = (RGBQUAD *) bmp->ScanLine[i-1];
else
piksel[0] = piksel[1];
if(i<wysokosc-1)
piksel[2] = (RGBQUAD *) bmp->ScanLine[i+1];
else
piksel[2] = piksel[1];
for( j=0; j<szerokosc; j++ )
{
double b = 0;
double g = 0;
double r = 0;
//oblicz wynikow╣ wartosc skladowych r,g,b po zastosowaniu filtru
for( int k=0; k<3 ; k++ )
for( int l=0; l<3 ; l++ )
{
if(j==0&&k==0)
{
r += filtr[k][l]*piksel[l][0].rgbRed;
g += filtr[k][l]*piksel[l][0].rgbGreen;
b += filtr[k][l]*piksel[l][0].rgbBlue;
}
else if(j==szerokosc-1&&k==2)
{
r += filtr[k][l]*piksel[l][j].rgbRed;
g += filtr[k][l]*piksel[l][j].rgbGreen;
b += filtr[k][l]*piksel[l][j].rgbBlue;
}
else
{
r += filtr[k][l]*piksel[l][j-1+k].rgbRed;
g += filtr[k][l]*piksel[l][j-1+k].rgbGreen;
b += filtr[k][l]*piksel[l][j-1+k].rgbBlue;
}
}
if( suma!=0 )
{
r /= suma;
g /= suma;
b /= suma;
}
//sprawdz zakresy
r = (r>255)?255:(r<0)?0:r;
b = (b>255)?255:(b<0)?0:b;
g = (g>255)?255:(g<0)?0:g;
//zapisz w WYJSCIOWEJ bitmapie
wiersz[j].rgbBlue = (BYTE) b;
wiersz[j].rgbGreen = (BYTE) g;
wiersz[j].rgbRed = (BYTE) r;
}
}
} //DostosujBalans