Operacje na bitmapach.

0

Witam, jestem na etapie dodawania kolejnych opcji w moim programie (kod poniżej). Dwie kolejne to: histogram bitmapy oraz maski. Ale przed tym chcialbym zmienić troszke program. Tylko nie wiem jak sie za to zabrac. Otóż chodzi o to by działał szybciej, wiem że ma byc to z udziałem wskaźników ale nie wiem jak to wdrążyć w życie. Jestem otwarty na wszelkie inne propozycje udoskonalenia programu.

#include <vcl.h>
#pragma hdrstop

#include "grafa_zad1.h"
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::NegatywClick(TObject *Sender)
{
for (int y = 0; y<Image1->Picture->Bitmap->Height; y++)
for (int x = 0; x<Image1->Picture->Bitmap->Width; x++)
{
TColor kolor=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
Byte r=GetRValue(kolor);
Byte g=GetGValue(kolor);
Byte b=GetBValue(kolor);


Image2->Picture->Bitmap->Canvas->Pixels[x][y]=RGB(255-r,255-g,255-b);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SaveAs1Click(TObject *Sender)
{
if (SavePictureDialog1->Execute()){
Image2->Picture->SaveToFile(SavePictureDialog1->FileName);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Open1Click(TObject *Sender)
{
if (OpenPictureDialog1->Execute()){
Image1->Picture->LoadFromFile(OpenPictureDialog1->FileName);
Image2->Picture->LoadFromFile(OpenPictureDialog1->FileName);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Exit1Click(TObject *Sender)
{
exit(1);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::AboutClick(TObject *Sender)
{
	Form2->ShowModal();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::RedClick(TObject *Sender)
{
for (int y = 0; y<Image1->Picture->Bitmap->Height; y++)
for (int x = 0; x<Image1->Picture->Bitmap->Width; x++)
{
TColor kolor=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
Byte r=GetRValue(kolor);
Byte g=GetGValue(kolor);
Byte b=GetBValue(kolor);

Image2->Picture->Bitmap->Canvas->Pixels[x][y]=RGB(r,r,r);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::GreenClick(TObject *Sender)
{
for (int y = 0; y<Image1->Picture->Bitmap->Height; y++)
for (int x = 0; x<Image1->Picture->Bitmap->Width; x++)
{
TColor kolor=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
Byte r=GetRValue(kolor);
Byte g=GetGValue(kolor);
Byte b=GetBValue(kolor);

Image2->Picture->Bitmap->Canvas->Pixels[x][y]=RGB(g,g,g);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::BlueClick(TObject *Sender)
{
for (int y = 0; y<Image1->Picture->Bitmap->Height; y++)
for (int x = 0; x<Image1->Picture->Bitmap->Width; x++)
{
TColor kolor=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
Byte r=GetRValue(kolor);
Byte g=GetGValue(kolor);
Byte b=GetBValue(kolor);

Image2->Picture->Bitmap->Canvas->Pixels[x][y]=RGB(b,b,b);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Y_luminacjaClick(TObject *Sender)
{

for (int y = 0; y<Image1->Picture->Bitmap->Height; y++)
for (int x = 0; x<Image1->Picture->Bitmap->Width; x++)
{
TColor kolor=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
Byte r=GetRValue(kolor);
Byte g=GetGValue(kolor);
Byte b=GetBValue(kolor);
float YY = (0.257 * r) + (0.504 * g) + (0.098 * b) + 16;
Image2->Picture->Bitmap->Canvas->Pixels[x][y]=RGB(YY,YY,YY);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::U_chrominacjaClick(TObject *Sender)
{
for (int y = 0; y<Image1->Picture->Bitmap->Height; y++)
for (int x = 0; x<Image1->Picture->Bitmap->Width; x++)
{
TColor kolor=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
Byte r=GetRValue(kolor);
Byte g=GetGValue(kolor);
Byte b=GetBValue(kolor);
float UU= -(0.148 * r) - (0.291 * g) + (0.439 * b) + 128;
Image2->Picture->Bitmap->Canvas->Pixels[x][y]=RGB(UU,UU,UU);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::V_chrominacjaClick(TObject *Sender)
{
for (int y = 0; y<Image1->Picture->Bitmap->Height; y++)
for (int x = 0; x<Image1->Picture->Bitmap->Width; x++)
{
TColor kolor=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
Byte r=GetRValue(kolor);
Byte g=GetGValue(kolor);
Byte b=GetBValue(kolor);
float VV=  (0.439 * r) - (0.368 * g) - (0.071 * b) + 128;
Image2->Picture->Bitmap->Canvas->Pixels[x][y]=RGB(VV,VV,VV);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Open2Click(TObject *Sender)
{
  if (OpenPictureDialog1->Execute()){
Image1->Picture->LoadFromFile(OpenPictureDialog1->FileName);
Image2->Picture->LoadFromFile(OpenPictureDialog1->FileName);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SaveAs2Click(TObject *Sender)
{
if (SavePictureDialog1->Execute()){
Image2->Picture->SaveToFile(SavePictureDialog1->FileName);
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Exit2Click(TObject *Sender)
{
exit(1);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Filtr_progowyChange(TObject *Sender)
{
for (int y = 0; y<Image1->Picture->Bitmap->Height; y++)
for (int x = 0; x<Image1->Picture->Bitmap->Width; x++)
{
TColor kolor=Image1->Picture->Bitmap->Canvas->Pixels[x][y];
Byte r=GetRValue(kolor);
Byte g=GetGValue(kolor);
Byte b=GetBValue(kolor);
kolor=0.299*r+0.587*g+0.114*b;
if (Filtr_progowy->Position > kolor)
kolor=0;
else
kolor=255;
kolor=RGB(kolor,kolor,kolor);
Image2->Picture->Bitmap->Canvas->Pixels[x][y]=RGB(kolor,kolor,kolor);
}
}
//---------------------------------------------------------------------------



0

Ustaw PixelFormat bitmapom na pf32bit.

struct Negatyw
{
	inline void operator()(unsigned &piksel1, unsigned &piksel2)
	{
		piksel2 = !piksel1 && 0x00FFFFFF;
	}
};

template<class Func>
void __fastcall TForm1::DlaKazdejParyPikseli()
{
	unsigned *linia1, *linia2;
	Func func;
	for (int y = 0; y < Image1->Picture->Bitmap->Height; y++)
	{
		linia1 = (unsigned*) Image1->Picture->Bitmap->ScanLine[y];
		linia2 = (unsigned*) Image2->Picture->Bitmap->ScanLine[y];
		for (int x = Image1->Picture->Bitmap->Width; x-- > 0;)
		{
			func(linia1[x], linia2[x]);
		}
	}
}

void __fastcall TForm1::NegatywClick(TObject *Sender)
{
	DlaKazdejParyPikseli< ::Negatyw >();

}
0

A mogłbys to po krotce wytlumaczyc?

0

Nie ma sprawy.
DlaKazdejParyPikseli jest to funkcja szablonowa, która wykonuje operacje na pikselach obu bitmap.
Pixels[x][y] jest wolny, bo każdy odczyt/zapis pojedynczego piksela wiąże się z konwersją koloru i innymi pierdołami. Dlatego aby przyspieszyć pracę użyłem metody ScanLine, która zwróci bezpośredni wskaźnik na piksele bitmapy. Jaki format mają piksele wskazywane przez ten wskaźnik zależy od własności PixelFormat.
Teraz funkcji tej musimy jakoś przekazać akcję do wykonania na pikselach. Zrealizowane jest to przez parametr szablonu - strukturę Func. Struktura ta (lub klasa) musi mieć zdefiniowany publiczny operator() przyjmujący dwie referencje do pikseli (unsigned &piksel1, unsigned &piksel2) . Operator ten jest wywoływany przez DlaKazdejParyPikseli aby wykonać żądaną akcję na pikselach. Przykładowa struktura Negatyw w swoim operator() przypisuje drugiemu pikselowi zanegowany kolor pierwszego piksela.

Dodam jeszcze, że w formacie pf32bit piksele mają identyczny format jak TColor, tudzież możesz używać makr GetRValue, RGB itp.
W sumie możesz zamienić wszędzie unsigned na TColor i będzie to samo.
Format ten to liczba 32 bitowa - 4 bajty. Pierwszy (najmłodszy) bajt to kolor czerwony, później zielony, niebieski a ostatni jest nieużywany. Ten nieużywany bajt to żadna strata, a przyspieszenie gdyż wtedy ilość bajtów (4) jest potęgą dwójki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1