Skalowanie obrazka z dobrym skutkiem można przeprowadzić tak:
TJPEGImage *jpgFile = new TJPEGImage();
jpgFile->Scale = jsFullSize;
jpgFile->LoadFromFile("c:\\image.jpg");
/* algorytm skalujący celem zachowania proporcji obrazka */
double ws = 0.0;
if(jpgFile->Width > jpgFile->Height)
ws = (double)jpgFile->Width / (double)jpgFile->Height;
else ws = (double)jpgFile->Height / (double)jpgFile->Width;
// zmiana rozmiaru Widht na 800 pikseli
double jpgWidth = 800;
double jpgHeight = jpgWidth / ws;
Graphics::TBitmap *bmpFile = new Graphics::TBitmap;
bmpFile->Width = (int)jpgWidth;
bmpFile->Height = (int)jpgHeight;
bmpFile->Canvas->StretchDraw(Rect(0, 0, bmpFile->Width, bmpFile->Height), jpgFile);
jpgFile->CompressionQuality = 100;
jpgFile->Assign(bmpFile);
jpgFile->SaveToFile("c:\\new image.jpg");
delete jpgFile;
delete bmpFile;
To skalowanie nie pozwala jednak na sterowanie efektem skalowania, a np. powiększając obrazek powinno się go rozmywać, a zmniejszając wyostrzać by uzyskać lepszy efekt. Można w tym celu stworzyć sobie taka funkcję:
#include "Math.hpp"
void __fastcall BlurImage(Graphics::TBitmap *Bitmap)
{
int flt[] = {2, 2, 2, 2, 24, 2, 2, 2, 2}; // wartości sterujące efektem - tutaj raczej rozmycie
int Div = 43; // wartości sterujące efektem - tutaj raczej rozmycie - skala
int XX[3];
BYTE *ptr, *ptru, *ptrd, *ptr1;
Graphics::TBitmap *tmpBitmap = new Graphics::TBitmap();
Bitmap->PixelFormat = pf24bit;
tmpBitmap->Assign(Bitmap);
tmpBitmap->PixelFormat = pf24bit;
for(int y = 1; y < tmpBitmap->Height - 1; y++)
{
ptr = (BYTE *) Bitmap->ScanLine[y];
ptr1 = (BYTE *) tmpBitmap->ScanLine[y];
ptru = (BYTE *) tmpBitmap->ScanLine[y-1];
ptrd = (BYTE *) tmpBitmap->ScanLine[y+1];
for(int x = 3; x < (tmpBitmap->Width - 1) * 3; x += 3)
{
XX[0] = 0; XX[1] = 0; XX[2] = 0;
for (int i1 = -1; i1 <= 1; i1++)
for(int j1 = 0; j1 < 3; j1++)
XX[j1] += ptr1[x + 3 * i1 + j1] * flt[4 + i1];
for(int i2 = -1; i2 <= 1; i2++)
for(int j2 = 0; j2 < 3; j2++)
XX[j2] += ptru[x + 3 * i2 + j2] * flt[1 + i2];
for(int i3 =- 1; i3 <= 1; i3++)
for(int j3 = 0; j3 < 3; j3++)
XX[j3] += ptrd[x + 3 * i3 + j3] * flt[7 + i3];
for(int i4 = 0; i4 < 3; i4++)
{
XX[i4] = XX[i4] / Div;
XX[i4] = Max(XX[i4], 0);
XX[i4] = Min(XX[i4], 255);
ptr[x + i4] = XX[i4];
}
}
}
delete tmpBitmap;
}
Wywołanie funkcji odbywa się po zmianie rozmiaru obrazka:
bmpFile->Canvas->StretchDraw(Rect(0, 0, bmpFile->Width, bmpFile->Height), jpgFile);
BlurImage(bmpFile);
jpgFile->CompressionQuality = 100;
jpgFile->Assign(bmpFile);
Zmieniając wartości można zmienić stopień rozmycia:
int flt[] = {1, 1, 1, 1, 20, 1, 1, 1, 1};
int Div = 20;
Można też uzyskać wyostrzenie:
int flt[] = {0, 0, 0, -1, 4, -1, 0, -1, 0};
int Div = 1;
a tak np. wyostrzenie łagodniejsze:
int flt[] = {-1, 0, 0, -1, 6, -1, 0, 0, 0};
int Div = 3;
i np. bardzo łagodne wyostrzenie:
int flt[] = {0, 0, 0, -1, 10, -1, 0, 0, 0};
int Div = 7;
Jak widzisz możliwości sterowania tym filtrem jest dużo. Możesz nie tylko rozmywać i wyostrzać obrazek, ale również sterować jego kontrastem i nasyceniem.
Dla celów testowych proponuję stworzyć specjalny formularz konfiguracyjny, coś w tym stylu:
filtr.png
Nie masz wystarczających uprawnień, aby zobaczyć pliki załączone do tego postu.