Конференция "Media" » BMP в массив
 
  • fen1ks © (16.09.10 20:08) [0]
    Нужно BMP-изображение загнать в массив для дальнейшей работы с ним
    получился вот такой код, только никак не могу найти ошибку, подскажите

    [CODE]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;[/CODE]

    По нажатию на кнопку ничего не происходит и выдает
    Process is not accessible
    Thread Exit: Thread ID: 3852. Process Project1.exe (3536)

    вот юнит с BMP - изображением
    http://www.megaupload.com/?d=XX55QNQD
  • Rouse_ © (16.09.10 20:30) [1]

    > только никак не могу найти ошибку, подскажите

    Ворнинги читать потомучто ленишся:
    [DCC Warning] Unit1.pas(47): W1019 For loop control variable must be simple local variable
    [DCC Warning] Unit1.pas(52): W1019 For loop control variable must be simple local variable

    а вот так работает:
    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;
     Form1.Canvas.Pixels[i,j]:=(RowProcessed[i].rgbtRed shl 16)+
       (RowProcessed[i].rgbtGreen shl 8) +
       RowProcessed[i].rgbtBlue;
    end;

    end;

    end;



    только совет - так программировать нельзя
  • fen1ks © (16.09.10 22:31) [2]
    спасибо, что именно нельзя?
  • Rouse_ © (16.09.10 23:01) [3]
    Весь код плохой, от глобальных переменных до мемлика, неверного использования канвы, отсутствия закладки на размеры оригинального битмапа, неверную работу с цветом
  • fen1ks © (17.09.10 00:10) [4]
    понял, это просто черновой вариант

    еще вопрос: мне нужен массив допустим s[i,j]=(RowProcessed[i].rgbtBlue shl 16)+ (RowProcessed[i].rgbtGreen shl 8)+RowProcessed[i].rgbtRed;

    каким типом его описать?
  • 0x00FF00 © (17.09.10 02:00) [5]

    > каким типом его описать?

    s: array of array of Byte, вестимо.
    хотя это и не идеальный вариант с точки зрения производительности.
    правильнее было бы сделать с помощью ссылки на array [0..0] of Byte, и потом копировать не поэлементно, а с помощью, скажем, GetDIBits.
  • fen1ks © (17.09.10 19:30) [6]
    Если описываю
    s1: array of array of Byte

    , на строке
    s1[i,j]:=(RowProcessed[i].rgbtBlue shl 16)+(RowProcessed[i].rgbtGreen shl 8)+RowProcessed[i].rgbtRed;


    выдает такую ошибку
    [Pascal Error] Unit1.pas(61): E1012 Constant expression violates subrange bounds


    > правильнее было бы сделать с помощью ссылки на array [0.
    > .0] of Byte, и потом копировать не поэлементно, а с помощью,
    >  скажем, GetDIBits.


    можно пример использования GetDIBits в моем случае
  • Rouse_ © (17.09.10 20:52) [7]

    > еще вопрос: мне нужен массив допустим s[i,j]=(RowProcessed[i].
    > rgbtBlue shl 16)+ (RowProcessed[i].rgbtGreen shl 8)+RowProcessed[i].
    > rgbtRed;
    >
    > каким типом его описать?

    TRGBTriple как он и был изначально при 24 битах :)
    Т.е.
    var
     Data: array of TRGBTriple;
  • fen1ks © (17.09.10 21:58) [8]
    понимаю что что то глупое спрашиваю, но если
    var
    s: array of TRGBTriple;

    то

    s[i,j]=(RowProcessed[i].rgbtBlue shl 16)+ (RowProcessed[i].rgbtGreen shl 8)+RowProcessed[i].rgbtRed;

    та же ошибка...
  • Rouse_ © (17.09.10 22:21) [9]
    так естественно, TRGBTriple это структура, и работать с нужно с ее полями
  • fen1ks © (17.09.10 23:18) [10]
    с чем именно не подскажите?
  • Rouse_ © (17.09.10 23:30) [11]
    каждый байт цвета изначально отображен в банной структуре, соответственно открой ее описание и работай с полями самой структуры а не через микс цвета через SHL
  • fen1ks © (18.09.10 01:16) [12]
    спасибо, буду разбираться
  • анонимус (29.07.11 02:00) [13]


    type

    TPixel = Record
       X : integer;
       Y : integer;
       w : Extended;
    end;

    TPixelArray = ARRAY OF TPixel;
    ................

    procedure TForm1.Button5Click(Sender: TObject);
    var
     tBmp: TBitmap;
     r: Trect;
     h: HWND;
     QP: TQuickPixels;
     PixelArr: TPixelArray;
     I: Integer;
     x: Integer;
     y: Integer;
     num:integer;
     Pi: TPixel;

    begin
     h := FindWindow(nil, PChAR('Калькулятор'));
     if h > 0 then
      begin
         GetWindowRect(h, r);
          ShowWindow(h, SW_SHOWNORMAL);
         sleep(200);
         // пересчёт
         GetWindowRect(h, r);
     
      tBmp := TBitmap.Create;
      tBmp.Width := 300;
      tBmp.Height := 100;
      PrintWindow(h, tBmp.Canvas.Handle, 0);
      tBmp.PixelFormat := pf24bit;
      Image10.Picture.Assign(tBmp);

       QP := TQuickPixels.Create;
       QP.Attach(tBmp);

       num:=0;
       for y := 0 to QP.Height-1 do
       begin
         for x := 0 to QP.Width-1 do
            begin
            if (x < QP.width-1) then
            begin

           
                PixelArr[num].x:= (y * QP.width + x);
              PixelArr[num].y:= y * QP.width + (x+1);
              PixelArr[num].w:= diff(QP, x, y, x+1, y);
              num:=num+1;

            end;

       
            end;
       end;
        tBmp.Free;
     end;
    end;
    end;




    При попытке записи в массив, выдает ошибку. Если смотреть в отладчике на значения в этом массиве, то пишет  Inaccessible value. Как это победить?
  • brother © (29.07.11 03:55) [14]
    > PixelArr

    где установка длинны массива? где try excepr?
    ps пока, код не ё.
  • brother © (29.07.11 03:58) [15]
    > num:=num+1;

    inc(num)

    > QP := TQuickPixels.Create;

    где уничтожение?

    в общем, пока брр, а не код
  • brother © (29.07.11 03:59) [16]
    > excepr?

    except конечно
  • brother © (29.07.11 04:00) [17]
    > где установка длинны массива?

    SetLength
  • анонимус (29.07.11 06:39) [18]
    понятно что брр, я делфи вижу третий день в жизни, можно поподробней? )
  • анонимус (29.07.11 07:00) [19]


    procedure TForm1.Button5Click(Sender: TObject);
    var
     tBmp: TBitmap;
     r: Trect;
     h: HWND;
     QP: TQuickPixels;
     PixelArr: TPixelArray;
     I: Integer;
     x: Integer;
     y: Integer;
     num:integer;
     Pi: TPixel;

    begin
     h := FindWindow(nil, PChAR('Калькулятор'));
     if h > 0 then
      begin
        begin
       GetWindowRect(h, r); // отыскивает размеры рамки ограничивающей прямоугольник определяемого окна
     
         ShowWindow(h, SW_SHOWNORMAL); // делает окно активным
         sleep(200);
         // пересчёт
         GetWindowRect(h, r); // отыскивает размеры рамки ограничивающей прямоугольник определяемого окна
       //end;
       tBmp := TBitmap.Create;
       tBmp.Width := 300;
       //r.Right - r.Left;
       tBmp.Height := 100;
       //r.Bottom - r.Top;
       PrintWindow(h, tBmp.Canvas.Handle, 0);
       tBmp.PixelFormat := pf24bit;
       Image10.Picture.Assign(tBmp);

       QP := TQuickPixels.Create;
       QP.Attach(tBmp);

       SetLength(PixelArr,QP.Height*QP.width*4);
       num:=0;
       for y := 0 to QP.Height-1 do
       begin
         for x := 0 to QP.Width-1 do
            begin
               if (x < QP.width-1) then
                   begin

    //                Pi.x:= (y * QP.width + x);
    //                Pi.y:= y * QP.width + (x+1);
    //                Pi.w:= diff(QP, x, y, x+1, y);
    //                PixelArr[num]:= Pi;

                     PixelArr[num].x:= (y * QP.width + x);
                     PixelArr[num].y:= y * QP.width + (x+1);
                    PixelArr[num].w:= diff(QP, x, y, x+1, y);
                    inc(num);
                   end;
            end;
       end;
      // Image10.Picture.Assign(tBmp);

       //sleep(2000);
       tBmp.Free;
       QP.Destroy;
       end;
      end;
    end;




    с какой целью тут exept не понял. И еще а есть тут что нибудь, чтобы автоматов выровнять текст кода нормально?
  • brother © (29.07.11 08:05) [20]
    > QP.Destroy;

    QP.free
    почитай почему не destroy напрямую
 
Конференция "Media" » BMP в массив
Есть новые Нет новых   [134430   +4][b:0][p:0.004]