Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Мультимедиа в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.09.2010, 20:02   #1
fen1ksss
Пользователь
 
Регистрация: 29.11.2009
Сообщений: 44
По умолчанию BMP в массив

Нужно BMP-изображение загнать в массив для дальнейшей работы с ним
получился вот такой код, только никак не могу найти ошибку, подскажите

Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

CONST
  PixelCountMax = 32768;

TYPE
  pRGBArray = ^TRGBArray;
  TRGBArray = ARRAY[0..PixelCountMax-1] OF TRGBTriple;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  OriginalBitmap:TBitmap;
  ProcessedBitmap:TBitmap;
  i,j:integer;
  RowOriginal:pRGBArray;
  RowProcessed:pRGBArray;

implementation

{$R *.dfm}

procedure CreateBMP;
begin
if OriginalBitmap.PixelFormat <> pf24bit then
  begin
    ShowMessage('Изображение должно быть 24-х битным');
    Exit;
  end;

for j:=OriginalBitmap.Height-1 downto 0 do
begin
  RowOriginal:=pRGBArray(OriginalBitmap.Scanline[j]);
  RowProcessed:=pRGBArray(ProcessedBitmap.Scanline[j]);

  for i:=OriginalBitmap.Width-1 downto 0 do
  begin
    RowProcessed[i].rgbtRed:=RowOriginal[i].rgbtRed;
    RowProcessed[i].rgbtGreen:=RowOriginal[i].rgbtGreen;
    RowProcessed[i].rgbtBlue:=RowOriginal[i].rgbtBlue;
  end;
end;
Form1.Canvas.Pixels[i,j]:=(RowProcessed[i].rgbtRed shl 16)+
(RowProcessed[i].rgbtGreen shl 8) +
RowProcessed[i].rgbtBlue;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  OriginalBitmap.LoadFromFile('0003.bmp');
  ProcessedBitmap.width:=800;
  ProcessedBitmap.height:=600;
  createbmp;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   OriginalBitmap:=TBitmap.Create;
   ProcessedBitmap:=TBitmap.Create;
end;
По нажатию на кнопку ничего не происходит и выдает
Process is not accessible
Thread Exit: Thread ID: 3852. Process Project1.exe (3536)

вот юнит с BMP - изображением
http://www.megaupload.com/?d=XX55QNQD
fen1ksss вне форума Ответить с цитированием
Старый 16.09.2010, 20:21   #2
DomiNick
Студент, не
Старожил
 
Аватар для DomiNick
 
Регистрация: 29.01.2009
Сообщений: 2,067
По умолчанию

Ну есть же поиск по форуму..... Например воть: http://www.programmersforum.ru/showthread.php?t=110388

И "OriginalBitmap.Free; ProcessedBitmap.Free;" не забываем при Destroy формы... *

З.Ы. Никогда не понимал зачем все делают какое-то [0..PixelCountMax-1]...



P.S. Не проверял, но на вскидку - где например "ProcessedBitmap.PixelFormat:=pf24b it;" ?
I am the First of Cyber Evolution...
I am the First to Program your Future...

Последний раз редактировалось DomiNick; 16.09.2010 в 20:26. Причина: P.S.
DomiNick вне форума Ответить с цитированием
Старый 16.09.2010, 21:31   #3
alexprey
Форумчанин
 
Регистрация: 25.05.2010
Сообщений: 169
По умолчанию

Слушайте а не проще использовать
TBitmap.Canvas.Pixels ???
alexprey вне форума Ответить с цитированием
Старый 16.09.2010, 21:48   #4
DomiNick
Студент, не
Старожил
 
Аватар для DomiNick
 
Регистрация: 29.01.2009
Сообщений: 2,067
По умолчанию

И ждать результата раз в сорок (если не в 140) дольше?
I am the First of Cyber Evolution...
I am the First to Program your Future...
DomiNick вне форума Ответить с цитированием
Старый 16.09.2010, 22:10   #5
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Продолжая мысь о простом хранении - не проще хранить в HBitMap, при необходимости подключаясь к нему и вытягивая инфу о пикселях? Лично у меня такой метод нисколько не тормозит даже на 800 * 600 картинках, при обновлении 40 раз\сек.

P.S. Если запросите, дам весь код своей системы.
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Старый 16.09.2010, 22:23   #6
fen1ksss
Пользователь
 
Регистрация: 29.11.2009
Сообщений: 44
По умолчанию

Цитата:
Сообщение от Alex Cones Посмотреть сообщение
Продолжая мысь о простом хранении - не проще хранить в HBitMap, при необходимости подключаясь к нему и вытягивая инфу о пикселях? Лично у меня такой метод нисколько не тормозит даже на 800 * 600 картинках, при обновлении 40 раз\сек.

P.S. Если запросите, дам весь код своей системы.
Суть программы: есть последовательность кадров и нужно ее засунуть в один кадр, т.е. сделать панорамное изображение.

Есть функция сравнения 2 массивов - 2 кадров, нахожу наименьшее отличие одного от другого и накладываю и так далее.
Для этого как раз и нужен массив, а как загонять изображение в массив это все равно (конечно не canvas.pixels), вот пробовал вариант через scanline, но до конца не получилось, если есть варианты, выложите плиз.
fen1ksss вне форума Ответить с цитированием
Старый 17.09.2010, 09:22   #7
Прик
Форумчанин
 
Регистрация: 08.09.2010
Сообщений: 880
По умолчанию

Цитата:
Сообщение от fen1ksss Посмотреть сообщение
По нажатию на кнопку ничего не происходит...
А ничего и не должно происходить визуально (дальше будет ясно почему).
Процедура банально копирует одно изображение в другое, причем самым "садистстким" методом - по каждому цвету, составляющему пиксел. Но это бы еще ничего, если бы не вывод копии на форму по-пиксельно. Тут и слов нет.
Естественно, по этим причинам появление изображение на форме происходит заметно медленно.
Вот такой код выводит изображение за заметное для глаза время:
Код:
for j := OriginalBitmap.Height-1 downto 0 do begin
  RowOriginal:=pRGBArray(OriginalBitmap.Scanline[j]);
  RowProcessed:=pRGBArray(ProcessedBitmap.Scanline[j]);
  for i:=OriginalBitmap.Width-1 downto 0 do begin
    //Доступ к RGB-цветам отдельных пикселей должен осуществляться следующим образом:
    RowProcessed[i].rgbtRed:=RowOriginal[i].rgbtRed;
    RowProcessed[i].rgbtGreen:=RowOriginal[i].rgbtGreen;
    RowProcessed[i].rgbtBlue:=RowOriginal[i].rgbtBlue;
    Form1.Canvas.Pixels[i,j]:=(RowProcessed[i].rgbtRed shl 16)+
                      (RowProcessed[i].rgbtGreen shl 8) +
           RowProcessed[i].rgbtBlue;
  end;
end;
А вот такой "мгновенно":
Код:
  for j:=OriginalBitmap.Height-1 downto 0 do begin
    RowOriginal:=pRGBArray(OriginalBitmap.Scanline[j]);
    RowProcessed:=pRGBArray(ProcessedBitmap.Scanline[j]);
    for i:=OriginalBitmap.Width-1 downto 0 do
      RowProcessed[i] := RowOriginal[i];
  end;
  Form1.Canvas.Draw(0, 0, ProcessedBitmap);
А "ничего не происходит" от обычной невнимательности - вывод на форму пикселей вынесен за пределы циклов.
Автору темы желательно попрактиковаться в работе с графикой, прежде чем браться за не самую простую, обозначенную им, задачу.

Вопрос.
А упомянутая функция "сравнения 2 массивов - 2 кадров" что принимает в качестве параметров (какой тип/какие типы и сколько) и что возвращает как результат сравнения?

Последний раз редактировалось Прик; 17.09.2010 в 09:54. Причина: Вопрос
Прик вне форума Ответить с цитированием
Старый 17.09.2010, 11:06   #8
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Для общего развития все таки покажу свой код:

1) Качаем сорсы от FVFL
2) Пишем у себя код:
Код:
 Type
  TTexture = Record
   Bitmap : HBitMap;
   Width  : LongInt;
   Height : LongInt;
  End;

  TBuffer = Record
   DC   : HDC;
   Tex  : TTexture;
  End;

  TWarehouse = Record
   Buffer   : TBuffer;
   <Кадры> : TTexture; <Или лучше array>
  End;
Код:
 Var
  Warehouse : TWarehouse;
Код:
Procedure LoadFromFile(Var T : TTexture; FileName : PChar);
 Var
  F : File;
  Data : Array of Integer;
  CurrentTool : Byte;
 Begin
  SetLength(Data, 5);
  ZeroMemory(@Data[0], Length(Data) * SizeOf(Integer));
  ZeroMemory(@CurrentTool, 1);
  AssignFile(F, FileName);
  Reset(F, 1);
  BlockRead(F, Data[0], SizeOf(Integer));
  BlockRead(F, T.Width, SizeOf(T.Width));
  BlockRead(F, T.Height, SizeOf(T.Height));
  T.Bitmap := CreateCompatibleBitmap(Application.FRMMain.IMGMain.DC, T.Width, T.Height);
  While Not(Eof(F)) Do
   Begin
    BlockRead(F, CurrentTool, 1);
    Case CurrentTool Of
     1 : Begin
         BlockRead(F, Data[0], SizeOf(Integer));
         UNTEffects.AddBlue(T, Data[0]);
        End;
    2 : Begin
         BlockRead(F, Data[0], SizeOf(Integer));
         UNTEffects.AddGreen(T, Data[0]);
        End;
    3 : Begin
         BlockRead(F, Data[0], SizeOf(Integer));
         UNTEffects.AddRed(T, Data[0]);
        End;
    4 : Begin
         UNTEffects.ConvertToBW(T);
        End;
    5 : Begin
         BlockRead(F, Data[0], SizeOf(Integer));
         UNTEffects.Brigthness(T, Data[0]);
        End;
   ... // Остальные эффекты
   End;
   End;
  CloseFile(F);
 End;
// Этот код используйте, если хотите использовать эффекты из FVFL, иначе делайте загрузку из файла:
 Procedure LoadHB(FileName : PChar; Var Tex : TTexture);
 Begin
  Tex.Bitmap := LoadImage(GetModuleHandle(Nil), FileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
  VirtualDraw(Tex);
 End;
Код:
 Procedure CreateDCnHB;
  Begin
   Application.FRMMain.IMGMain.DC := GetDC(Application.FRMMain.IMGMain.Handle);
   Warehouse.Buffer.DC := CreateCompatibleDC(Application.FRMMain.IMGMain.DC);
   Warehouse.Buffer.Tex.Bitmap := CreateCompatibleBitmap(Application.FRMMain.IMGMain.DC, 800, 600);
   VirtualDraw(Warehouse.Buffer.Tex);
   SelectObject(Warehouse.Buffer.DC, Warehouse.Buffer.Tex.Bitmap);
  End;
Здесь у меня Application - не тот application, это следующая запись:
Код:
   TIMG = Record
    Handle     : HWND;
    DC         : HDC;
   End;

   TFRM  =  Record
    Handle      : HWND;
    IMGMain     : TIMG;
   End;

   TApplication = Record
    WinClass               : TWndClass;
    ApplicationHandle      : HWND;          // hInst
    OldHeight              : Integer;
    OldWidth               : Integer;
    (* Message *)  Msg     : TMSG;
    (* Forms   *)  FRMMain : TFRM;
   End;
- Изменяем как хотим, оставляем только переменную DC в любом месте.
Код:
  Procedure VirtualDraw(Var Source : TTexture);
  Var
   Bit     : BitMap;
  Begin
   GetObject(Source.Bitmap, SizeOf(Bit), @Bit);
   Source.Height := Bit.bmHeight;
   Source.Width := Bit.bmWidth;
  End;  // Процедура заполнения ширины\высоты
Код:
 Procedure Draw(Var T : TTexture; X,Y : Integer);
  Var
   Loc     : HDC;
  Begin
   Loc := CreateCompatibleDC(Warehouse.Buffer.DC);
   SelectObject(Loc, T.Bitmap);
   BitBlt(Warehouse.Buffer.DC, X, Y, T.Width, T.Height, Loc, 0, 0, SRCCOPY);
   DeleteDC(Loc);
  End;// Рисование на буфере.
 Procedure DrawT(Var T : TTexture; X,Y : Integer);
  Var
   Loc     : HDC;
  Begin
   Loc := CreateCompatibleDC(Warehouse.Buffer.DC);
   SelectObject(Loc, T.Bitmap);
   TransparentBlt(Warehouse.Buffer.DC, X, Y, T.Width, T.Height, Loc, 0, 0, T.Width, T.Height, $FF00FF);
   DeleteDC(Loc);
  End;  // То же с прозрачностью
Код:
 Procedure DrawB;
  Begin
   BitBlt(Application.FRMMain.IMGMain.DC,
          0, 0, 800, 600, Warehouse.Buffer.DC, 0, 0, SRCCOPY);
  End; // Вывод на экран. Размеры указывайте по форме.
Прикладываю проект, полностью построеннный на этом коде:
(Там только меню)
Вложения
Тип файла: rar Finder.rar (83.5 Кб, 44 просмотров)
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Старый 17.09.2010, 19:23   #9
fen1ksss
Пользователь
 
Регистрация: 29.11.2009
Сообщений: 44
По умолчанию

Цитата:
Сообщение от Прик Посмотреть сообщение
Вот такой код выводит изображение за заметное для глаза время:
Код:
for j := OriginalBitmap.Height-1 downto 0 do begin
  RowOriginal:=pRGBArray(OriginalBitmap.Scanline[j]);
  RowProcessed:=pRGBArray(ProcessedBitmap.Scanline[j]);
  for i:=OriginalBitmap.Width-1 downto 0 do begin
    //Доступ к RGB-цветам отдельных пикселей должен осуществляться следующим образом:
    RowProcessed[i].rgbtRed:=RowOriginal[i].rgbtRed;
    RowProcessed[i].rgbtGreen:=RowOriginal[i].rgbtGreen;
    RowProcessed[i].rgbtBlue:=RowOriginal[i].rgbtBlue;
    Form1.Canvas.Pixels[i,j]:=(RowProcessed[i].rgbtRed shl 16)+
                      (RowProcessed[i].rgbtGreen shl 8) +
           RowProcessed[i].rgbtBlue;
  end;
end;
А вот такой "мгновенно":
Код:
  for j:=OriginalBitmap.Height-1 downto 0 do begin
    RowOriginal:=pRGBArray(OriginalBitmap.Scanline[j]);
    RowProcessed:=pRGBArray(ProcessedBitmap.Scanline[j]);
    for i:=OriginalBitmap.Width-1 downto 0 do
      RowProcessed[i] := RowOriginal[i];
  end;
  Form1.Canvas.Draw(0, 0, ProcessedBitmap);
что то при замене 1 на второе ничего не выводится на форму... хотя вроде все точно копирую

Цитата:
Сообщение от Прик Посмотреть сообщение
Автору темы желательно попрактиковаться в работе с графикой, прежде чем браться за не самую простую, обозначенную им, задачу.
несомненно, просто это курсовая работа, так что пришлось браться с того, что задали

Цитата:
Сообщение от Прик Посмотреть сообщение
Вопрос.
А упомянутая функция "сравнения 2 массивов - 2 кадров" что принимает в качестве параметров (какой тип/какие типы и сколько) и что возвращает как результат сравнения?
на самом деле
Код:
Form1.Canvas.Pixels[i,j]:=(RowProcessed[i].rgbtRed shl 16)+
                      (RowProcessed[i].rgbtGreen shl 8) +
           RowProcessed[i].rgbtBlue;
это просто проверка того, что изображение находится в массиве, на самом деле мне нужен массив, допустим s1[i,j] = (RowProcessed[i].rgbtRed shl 16)+(RowProcessed[i].rgbtGreen shl 8) + RowProcessed[i].rgbtBlue;

Далее беру часть 2 изображения, так же засовываю в массив, допустим s2[i,j]

"Пробегаю s2 по всему s1" ища наименьшую разностную функцию, там где эта функция наименьшая, там теоретически и совпадают 2 кадра и просто накладываю 2 на 1.

Остается вопрос, каким типом описать s1 и s2? подскажите
fen1ksss вне форума Ответить с цитированием
Старый 17.09.2010, 20:05   #10
Прик
Форумчанин
 
Регистрация: 08.09.2010
Сообщений: 880
По умолчанию

Оба фрагмента копирования и вывода я проверял - работают, т.е. изображение ProcessedBitmap выводятся на форму и в первом и во втором случае.

Вам не нужны какие-то особенные массивы (s, s2), так как TBitmap при загруженном изображении можно рассматривать как двухмерный массив элементов типа Integer, которые интерпретируются как TColor.
После загрузки картинок в один и второй объекты класса TBitmap уже можно спокойно применять к ним "разностную функцию".

Небольшое замечание: создавая объекты TBitmap нужно озаботится освобождением памяти от этих объектов когда они уже не нужны.
Прик вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
timage в bmp varelik Мультимедиа в Delphi 8 21.12.2009 09:55
Программа BMP PradoSV Общие вопросы C/C++ 0 23.11.2009 23:25
bmp картинки B@R@B@$HK@ Общие вопросы C/C++ 0 09.06.2009 23:08
Как загрузить BMP в массив и обратно в С++ Ilja Общие вопросы C/C++ 8 07.03.2009 23:48
Декодирование BMP Rezet Мультимедиа в Delphi 6 24.01.2009 22:33