Podmienky:
- predpokladám u programátora základné znalosti z C++ a objektového programovania
- nastavenie projektu v sekcii "Bitmaps Property pages":
- Use of MFC: Use Standard Windows Libraries
- Character set: Use Unicode Character Set
- Common Language Runtime support: Pure MSIL Common Language Runtime Support (/clr:pure)
- Whole Program optimalization: No whole Program optimalization
Projekt som nazval "Bitmaps", namespace takisto "Bitmaps". Hlavný obsah zdrojového kódu je uložený v súbore Form1.h.
V prílohe sú dva súbory Bitmaps.cpp a Form1.h a dva testovacie obrázky na ukážku motorhead1.bmp a motorhead2.bmp.
Na formulári sú vložené 4 objekty Picturebox. Picturebox1 a Picturebox2 slúžia ako zdroj pre obrázok po skombinovaní bitmáp do jednej a vložení nového bitmapového obrázku do objektu Picturebox3. Po štarte aplikácie si nakopírujte obrázky do adresára, kde sa nachádza výsledný spustiteľný súbor Bitmaps.exe a môžete skúšať. Nahrajte pomocou tlačidla "Load picture 1" prvý obrázok, pomocou tlačidla "Load picture 2" druhý, nastavte percentuálny odtieň druhého obrázku v prvom pomocou objektu "trackBar1" a stlačte tlačidlo "Combine pictures". Výsledok je vidno ihneď. Pootočenie obrázku "Picturebox2" je možné tlačidlom "Rotate picture". Nastavte uhol pootočenia a stlačte tlačidlo. Obrázok z objektu "Picturebox2" bude pootočený a zobrazený v objekte "Picturebox4".
Malé vysvetlenie k programu.
Kombinácia obrázkov spočíva v prečítaní RGB čísla farby každého jedného bodu "pixelu" oboch bitmáp, rozložení farby na R,G a B zložky a vypočítaní z nich nového RGB čísla farby z nových zložiek RGB. Rovnica výpočtu je jednoduchá a zo zrdrojového kódu zrejmá. Ide o rozdelenie pomeru pôvodných RGB zložiek podľa nastaveného pomeru odtieňu od jednej farby k druhej. Pomery sú sčítané a súčet nových pomerov zložky tvorí novú zložku. Nové čislo farby sa potom vypočíta zo všetkých nových RGB zložiek.
Rotácia obrázku spočíva v prečítaní RGB čísla farby bodu, vypočítaní novej súradnice bodu pootočenú o zadaný uhol v objekte "numericUpDown1" a nastavení tohto čísla farby RGB do nového bodu. Rovnice pootočenia sú vidno v zdrojom kóde takisto a trochu si nimi pripomenieme matematiku zo strednej školy.:)
Kód v CPP - mixBitmaps:
private: System::Drawing::Bitmap^ MixBitmaps(System::Drawing::Bitmap^ bitmap1, System::Drawing::Bitmap^ bitmap2, int steps, int stepno) { //typedef unsigned char * buffer; int h = bitmap1->Height < bitmap2->Height ? bitmap1->Height : bitmap2->Height; int w = bitmap1->Width < bitmap2->Width ? bitmap1->Width : bitmap2->Width; // Check if h or w are nonzero ... if (h == 0 && w == 0) { throw std::invalid_argument("Bitmaps must be loaded!"); } this->progressBar1->Value = 0; System::Drawing::Bitmap^ result = gcnew Bitmap(w, h, System::Drawing::Imaging::PixelFormat::Format24bppRgb); System::Drawing::Color color, color1, color2; int R, G, B; double s1 = (double) (steps - stepno) / (double) steps; double s2 = (double) stepno / (double) steps; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { color1 = bitmap1->GetPixel(x, y); color2 = bitmap2->GetPixel(x, y); R = color1.R * s1 + color2.R * s2; G = color1.G * s1 + color2.G * s2; B = color1.B * s1 + color2.B * s2; color = System::Drawing::Color::FromArgb(R, G, B); result->SetPixel(x, y, color); } this->progressBar1->Value = Math::Floor ((double) y * (100 / (double) h)); this->progressBar1->Refresh(); } this->progressBar1->Value = 0; return result; }
Kód v CPP - rotateBitmap:
private: System::Drawing::Bitmap^ RotateBitmap(System::Drawing::Bitmap^ src_bitmap, int angle_deg) { int h = src_bitmap->Height; int w = src_bitmap->Width; // Check if h or w are nonzero ... if (h == 0 && w == 0) { throw std::invalid_argument("Bitmap must be loaded!"); } this->progressBar1->Value = 0; System::Drawing::Bitmap^ result = gcnew Bitmap(w, h, System::Drawing::Imaging::PixelFormat::Format24bppRgb); System::Drawing::Color color; double angle_rad = 2 * Math::PI * (double) angle_deg / 360; double cosin_angle = Math::Cos(angle_rad); double sin_angle = Math::Sin(angle_rad); double cx = (double) w / 2.0; double cy = (double) h / 2.0; int nx, ny; double deltaX, deltaY; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { deltaX = (double) x - cx; deltaY = (double) y - cy; nx = Math::Floor(deltaX * cosin_angle + deltaY * sin_angle + cx); ny = Math::Floor(deltaY * cosin_angle - deltaX * sin_angle + cy); if (nx >= 0 && nx < w && ny >= 0 && ny < h) { color = src_bitmap->GetPixel(x, y); result->SetPixel(nx, ny, color); } } this->progressBar1->Value = Math::Floor ((double) y * (100 / (double) h)); this->progressBar1->Refresh(); } this->progressBar1->Value = 0; return result; }
Príjemnú zábavu.
S pozdravom