Большой Воронежский Форум
» Программирование>Как быстро скопировать из массива в Image->Canvas->Pixels ??
Eвгений 22:15 14.04.2015
Есть двумерный массив unisigned char.
И есть Image1.
Зарисовать попиксельно - это понятно, но боюсь что скорость будет мала, к тому же я получаю картинку по USB, процесс непрерывный.

В свое время я заменил попиксельное копирование на CopyRect из соображений быстродействия, но это касалось копирования из одной области в другую.
А как мне максимально быстро скопировать из двумерного массива char в canvas ?

Ну что-то типа
unsigned char m[640][480];
memcpy(Image1->Canvas->Pixels,m,sizeof(m));


Быстродействие очень важно, хотелось бы на все (307 000 байт) тратить не более 0.3 сек. [Ответ]
Spectator 22:39 14.04.2015
https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx

HDC = Canvas->Handle

SetDIBits => переведет из массива в Bitmap, Bitmap уже в канве отобразить не проблема. [Ответ]
Eвгений 09:35 15.04.2015
Spectator, Сделал немножко не так, мне показалось, что StretchDIBits больше подходит.

Вот кусок кода - который принимает данные и выводит их попиксельно - это работает.

Сообщение от :
unsigned char DataIn[307200];
unsigned char* pDataIn; //буфер
BITMAPINFO bmp;
........................
pDataIn=DataIn;

void __fastcall TForm1::VaComm1RxBuf(TObject *Sender, PVaData Data, int Count)
{
unsigned int i;
HDC hDC;
VaBuffer1->Peek(DataIn+Total,Count);
VaBuffer1->Clear();
Total+=Count;

if (Total==307200) // когда получили весь кадр
{
Memo1->Lines->Add(IntToStr(Count) + ", " + IntToStr((__int64)Total));
Form1->Image1->Canvas->Brush->Color=clWhite;
Form1->Image1->Canvas->FillRect(Form1->Image1->ClientRect); // Очищаем канву
for (i=0; i < Total; i++) // заполняем попиксельно
{

if (CurrentX>=640)
{
CurrentX=0;
CurrentY++;
}

Image1->Canvas->Pixels[CurrentX++][CurrentY]=DataIn[i];
}


}

}

А если заменить попиксельный цикл на

Сообщение от :
hDC=Image1->Canvas->Handle;
StretchDIBits(hDC,1,1,640,480,0,0,640,480, DataIn, &bmp, DIB_RGB_COLORS, SRCCOPY);

картинка белая.

Что я делаю не так? Мне в частности непонятно, какую роль играет здесь BITMAPINFO bmp; [Ответ]
Spectator 10:45 15.04.2015

Сообщение от Eвгений:
Что я делаю не так? Мне в частности непонятно, какую роль играет здесь BITMAPINFO bmp;

скорее всего не заполняешь как раз BITMAPINFO, которую нужно заполнить для того чтобы функция знала, в каком формате хранятся данные изображения.

http://stackoverflow.com/questions/3...xels-using-x-y

при правильном заполнении ты получишь тот же результат, что и попиксельное чтение, но работать будет наверняка намного быстрее. [Ответ]
Eвгений 11:39 15.04.2015
Spectator,
Я почитаю, но прежде хочу возмутиться - неужели нет функции, которая может заполнить BITMAPINFO взяв за основу существующую картинку?
Ну что-то типа
BITMAPINFO = GetBITMAPINFO_FROM_IMAGE(Image1->Canvas) ? [Ответ]
Spectator 11:55 15.04.2015

Сообщение от Eвгений:
Spectator,
Я почитаю, но прежде хочу возмутиться - неужели нет функции, которая может заполнить BITMAPINFO взяв за основу существующую картинку?
Ну что-то типа
BITMAPINFO = GetBITMAPINFO_FROM_IMAGE(Image1->Canvas) ?

почему, есть
GetObject
http://stackoverflow.com/questions/2...-load-a-bitmap [Ответ]
Eвгений 18:13 15.04.2015
Почти получилось вот так

Сообщение от :
WLabel->Caption->Text="Кадр получен";

Memo1->Lines->Add(IntToStr(Count) + ", " + IntToStr((__int64)Total));

Form1->Image1->Canvas->Brush->Color=clWhite;
Form1->Image1->Canvas->FillRect(Form1->Image1->ClientRect);



Image1->Picture->Bitmap->PixelFormat=pf16bit; // подготавливаем Image1 к тому, что будет грузиться 8 битная информация.




memset(&bitmap_info, 0, sizeof(bitmap_info));
bitmap_info.bmiHeader.biSize = sizeof(bitmap_info.bmiHeader);
bitmap_info.bmiHeader.biWidth = 640;
bitmap_info.bmiHeader.biHeight = 480;
bitmap_info.bmiHeader.biPlanes = 1;
bitmap_info.bmiHeader.biBitCount = 16;//bits per pixel
bitmap_info.bmiHeader.biCompression = DIB_RGB_COLORS;

SetDIBits(Image1->Canvas->Handle,Form1->Image1->Picture->Bitmap->Handle,0,Image1->Height,&DataIn,&bitmap_info,DIB_RGB_COLORS);

Быстродействие - мгновенное появление картинки....Так что уж помогите добить этот код...
Но вот только какие-то проблемы с цветами..... Если скажем не заполнять картинку белым цветом перед перерисовкой - то цвета из буфера будут другими...
Ладно, прикручу камеру, получу нативную картинку, тогда буду копать.. [Ответ]
Eвгений 19:15 27.04.2015
Все-таки что-то не так.
Картинка отображается так, как будто она имеет формат RGB555. А у меня RGB565
Как я это понял?
Вот сайт http://rawpixels.net/
Выкладываю бинарник (дамп памяти). Если в настройках на сайте выставить RGB565 (исходный формат) то получится нормальная картинка, черно белая. А если поставить RGB555 - то получится то, что у меня в программе.
В свойствах Image1 я не нашел ничего подходящего.
Как настроить правильный вывод картинки?
Изображения
[Ответ]
Eвгений 19:25 27.04.2015
Да действительно...
Настроил источник в режим RGB555, получил в программе правильную картинку. То есть Image1 c дефольтными настройками, функция SetDIBits выводят картинку в формате RGB555.
Как это побороть? [Ответ]
Вверх