Graphics::TBitmap* Bitm = new Graphics::TBitmap;
TJPEGImage* jpgmage = new TJPEGImage;
jpgmage->LoadFromFile(OpenDialog1->FileName);
Bitm->Assign(jpgmage);
imj->Picture->Graphic = Bitm;
imj->Canvas->Draw(0,0,Bitm);
Очень долго строится гистограмма
Столкнулся со следующей проблемой: постоение гистограммы изображения (размеры около 3500х2500) занимает ну очень много времени - больше 40 секунд, по-моему, это много.
Строю следующим образом:
1) Ну, во-первых у меня исходное изображение jpeg, поэтому сначала перекодирую
Код:
2) Теперь непосредственно постоение:
Код:
for (j=0;j<imj->Picture->Bitmap->Height;j++)
for (i=0;i<imj->Picture->Bitmap->Width;i++)
{
r=GetRValue(imj->Picture->Bitmap->Canvas->Pixels[j]);
g=GetGValue(imj->Picture->Bitmap->Canvas->Pixels[j]);
b=GetBValue(imj->Picture->Bitmap->Canvas->Pixels[j]);
y=(int) (0.299*r+0.587*g+0.114*b);
Yarr[y]++;
}
for (i=0;i<imj->Picture->Bitmap->Width;i++)
{
r=GetRValue(imj->Picture->Bitmap->Canvas->Pixels[j]);
g=GetGValue(imj->Picture->Bitmap->Canvas->Pixels[j]);
b=GetBValue(imj->Picture->Bitmap->Canvas->Pixels[j]);
y=(int) (0.299*r+0.587*g+0.114*b);
Yarr[y]++;
}
Понятно, что есть и более очевидный подход: Сначала так jpgmage->Grayscale=true; а потом просто брать любую компоненту, НО, когда я делаю так, мне выдается весьма странный результат (ниже две картинки, соответственно при первом и втором подходе). Да и работает не сильно быстрее.
Мне почему-то кажется, что есть более быстрый способ построения гистограммы.
Заранее спасибо за помощь.
Картинка_1
Картинка_2
Код:
// насколько Я знаю, TImage->Picture умеет загружать Jpeg
imj->Picture->LoadFromFile(OpenDialog1->FileName);
TMemoryStream* MS = new TMemoryStream();
// загрузим образ в поток памяти, чтобы работать с ним как с char массивом
imj->Picture->Bitmap->SaveToStream( MS );
MS->Position = 0; // по-моему надо "на старт" сделать
unsigned char *pixel = (unsigned char*)MS->Memory;
BITMAPFILEHEADER bmp_hdr1;
BITMAPINFOHEADER bmp_hdr2;
memcpy ( &bmp_hdr1, pixel, 14); pixel +=14; // копируем заголовок BMP и смещаем указатель
memcpy ( &bmp_hdr2, pixel, 40); pixel +=40; // копируем заголовок BMP и смещаем указатель
// если BMP без палитры, то pixel указывает на первую точку изображения
int pixelsize = bmp_hdr2.biBitCount / 8;
// например для biBitCount = 24 bit /8 = 3 байта
// например для biBitCount = 32 bit /8 = 4 байта
// всего точек ...
int count = bmp_hdr2.biWidth * bmp_hdr2.biHeight;
int y;
// цикл по всем точкам ...
for (int i = 0; i < count; i++)
{
y =(int) ( 0.299*pixel[0]+0.587*pixel[1]+0.114*pixel[2] );
Yarr[y]++;
pixel += pixelsize; // смещаем указатель на следующий пиксел
}
delete MS; // удалим поток
imj->Picture->LoadFromFile(OpenDialog1->FileName);
TMemoryStream* MS = new TMemoryStream();
// загрузим образ в поток памяти, чтобы работать с ним как с char массивом
imj->Picture->Bitmap->SaveToStream( MS );
MS->Position = 0; // по-моему надо "на старт" сделать
unsigned char *pixel = (unsigned char*)MS->Memory;
BITMAPFILEHEADER bmp_hdr1;
BITMAPINFOHEADER bmp_hdr2;
memcpy ( &bmp_hdr1, pixel, 14); pixel +=14; // копируем заголовок BMP и смещаем указатель
memcpy ( &bmp_hdr2, pixel, 40); pixel +=40; // копируем заголовок BMP и смещаем указатель
// если BMP без палитры, то pixel указывает на первую точку изображения
int pixelsize = bmp_hdr2.biBitCount / 8;
// например для biBitCount = 24 bit /8 = 3 байта
// например для biBitCount = 32 bit /8 = 4 байта
// всего точек ...
int count = bmp_hdr2.biWidth * bmp_hdr2.biHeight;
int y;
// цикл по всем точкам ...
for (int i = 0; i < count; i++)
{
y =(int) ( 0.299*pixel[0]+0.587*pixel[1]+0.114*pixel[2] );
Yarr[y]++;
pixel += pixelsize; // смещаем указатель на следующий пиксел
}
delete MS; // удалим поток
ЗЫ: Насчет медленности алгоритма подсчета распределения, то не переживай узкое место не здесь