Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > BMP image в массив


Автор: fen1ksss 14.9.2010, 18:11
В общем есть картинка bmp формата, нужно разбить эту картинку на RGB и загнать в массив (скорее всего 3 мерный где каждый элемент это r,g,b соответсвенно) для дальнейшей работы с изображением через массив.
Дело в том что как работать с черно-белым понимаю, а как цветное на RGB разбить немного не понимаю, подскажите

Автор: UniBomb 14.9.2010, 18:17
fen1ksss, http://www.delphisources.ru/pages/faq/base/bitmap_scanline_for_pixelformat.html всё описано.

Автор: fen1ksss 14.9.2010, 19:06
Цитата(UniBomb @ 14.9.2010,  18:17)
fen1ksss, http://www.delphisources.ru/pages/faq/base/bitmap_scanline_for_pixelformat.html всё описано.

Тогда здесь RowProcessed[i].rgbtRed содержится 256 оттенков красного?

тогда грубо говоря если я хочу вывести этот массив с красным цветом на форму, то пишу

Код

Canvas.Pixels[i,j]:=RowProcessed[i].rgbtRed;


и выводит, я правильно понимаю?

Автор: UniBomb 14.9.2010, 20:22
Цитата(fen1ksss @  14.9.2010,  20:06 Найти цитируемый пост)
Тогда здесь RowProcessed[i].rgbtRed содержится 256 оттенков красного?

Нет, тут содержится красная составляющая i-того пикселя j-той строки. ScanLine читает изображения по-строчно, выдавая на гора массив значений в формате, определённым PixelFormat. RGB - это модель цветапредставления в виде трёх составляющих - красной, зелёной и синей.

Допустим у тебя есть картинка 16*16 пикселей. Тогда:

Код

ProcessedBitmap.PixelFormat = pf24bit;
RowProcessed := pRGBArray(ProcessedBitmap.Scanline[0]) //будет содержать одномерный массив TRGBTriple в количестве 16-ти элементов


Далее - Допустим верхний левый пиксель имеет чиленное значение цвета, равное 0xFF0000. Т.е. он красный. Тогда:

Код

RowProcessed[0].rgbtRed //тут будет хранится значение 0xFF

Для вывода цвета надо каждую состовляющую поставить на своё место и сложить всё это друг с другом.
Canvas.Pixels[i,j]:=(RowProcessed[i].rgbtRed << 16) + (RowProcessed[i].rgbtGreen << 8) + RowProcessed[i].rgbtBlue;

Автор: Alexeis 14.9.2010, 20:36
UniBomb, в делфях нет оператора "<<" . Он называется shl

Автор: fen1ksss 14.9.2010, 20:47
Цитата(UniBomb @  14.9.2010,  20:22 Найти цитируемый пост)
Тогда здесь RowProcessed[i].rgbtRed содержится 256 оттенков красного?Нет, тут содержится красная составляющая i-того пикселя j-той строки. 

А каждая красная составляющая как раз и может принимать одно из 256 значений взависимости от оттенка красного?

Код

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

    //Доступ к RGB-цветам отдельных пикселей должен осуществляться следующим образом:
    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('a.bmp');
  createbmp;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   OriginalBitmap:=TBitmap.Create;
end;


пишет ошибку, в чем проблема? Изображение 'a.bmp' 800x600

Автор: UniBomb 14.9.2010, 20:55
Alexeis, я значит не зря сомневался  smile 


Цитата(fen1ksss @  14.9.2010,  21:47 Найти цитируемый пост)
А каждая красная составляющая как раз и может принимать одно из 256 значений взависимости от оттенка красного?

Да. Каждая из трёх составляющих может принимать значения от 0 до 255. По коду ничего не скажу, т.к. боюсь соврать как в случае с оператором <<  smile 

Автор: fen1ksss 14.9.2010, 20:58
Вот эти значения (RowProcessed[i].rgbtRed << 16) + (RowProcessed[i].rgbtGreen << 8) + RowProcessed[i].rgbtBlue;
по какому принципу выбираются?
если картинка другого размера?

Автор: UniBomb 14.9.2010, 21:19
fen1ksss, выбираются по одному и тому же принципу. Вот смотри - картинка имеет глубину цвета 24 бита. Три состовляющие. Значит на каждую составляющую приходится по 8 бит или по одному байту. 24 бита - это три байта. Значит числовое значение цвета - это есть ни что иное как трёхбайтное целое число, где старший байт является красной составляющей, средний байт зелёной, а младший - соответсвенно синей.

http://ipicture.ru/


Автор: fen1ksss 14.9.2010, 21:30
UniBomb, понял, спасибо, теперь бы только с ошибкой разобраться

Добавлено через 12 минут и 47 секунд
Может дело в моем image? если просто в paint или другой программе создаю изображение Windows bmp оно ведь 24-битное?

Автор: Illusion Dolphin 15.9.2010, 17:35
Ошибка в строке 62 - I и J после цикла - RowProcessed выходит за пределы. 
Вообще не понимаю зачем надо BMP переводить в массив если это и есть массив smile 

Код

OriginalBitmap.PixelFormat := pf24Bit;
ProcessedBitmap.PixelFormat := pf24Bit;
ProcessedBitmap.Width := OriginalBitmap.Width;
ProcessedBitmap.Height:= OriginalBitmap.Height;
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:=255-RowOriginal[i].rgbtRed;
    RowProcessed[i].rgbtGreen:=255-RowOriginal[i].rgbtGreen;
    RowProcessed[i].rgbtBlue:=255-RowOriginal[i].rgbtBlue;
    Form1.Canvas.Pixels[i,j]:=RGB(RowProcessed[i].rgbtRed, RowProcessed[i].rgbtGreen, RowProcessed[i].rgbtBlue);
  end;
end;


Цитата

если просто в paint или другой программе создаю изображение Windows bmp оно ведь 24-битное

Не всегда.

Автор: fen1ksss 15.9.2010, 20:19
Цитата(Illusion Dolphin @  15.9.2010,  17:35 Найти цитируемый пост)
Ошибка в строке 62 - I и J после цикла - RowProcessed выходит за пределы. 


что можно сделать? i,j описать как longint?

Вот такая ошибка
Process is not accessible
Thread Exit: Thread ID: 3852. Process Project1.exe (3536)

вот юнит с картинкой
http://www.megaupload.com/?d=XX55QNQD


Цитата(Illusion Dolphin @  15.9.2010,  17:35 Найти цитируемый пост)
Вообще не понимаю зачем надо BMP переводить в массив если это и есть массив

В итоге должна должна получиться программа : из видео сделать изображение-панораму.
в массив загонять нужно чтобы дальше сравнивать 2 изображения, находить общие пиксели и накладывать друг на друга

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)