-2

I Want to make a program, that can write my TImage pixels rgb color to a memo, the program don't know the resolution.

so how can i recover every pixel color to String variable (R,G,B)?

code

var 
Image_width,Image_height,x,y,i,i2:integer;
Colors:TColor;

begin
Image_width:=Image1.Width;
Image_height:=Image1.Height;
memo1.text:='$image_width=*'+IntToStr(Image_Width)+
            '$$image_height='+IntToStr(Image_Height)+'*$';
x:=1;
y:=1;
for i := 1 to Image_width do begin
 for i2 := 1 to Image_height do begin
  Colors:=Image1.Canvas.Pixels[x,y];
  memo1.Text:=memo1.Text+ColorToString(Colors);
  y:=y+1;
 end;
 x:=x+1
end;
end

|Edited|

procedure TForm1.Button2Click(Sender: TObject);
var
Image_width,Image_height,x,y:integer;
Colors:TColor;
s:string;
begin

 Image_width:=Image1.Width;
 Image_height:=Image1.Height;



 memo1.text:='$image_width=*'+IntToStr(Image_Width)
            +'*$ $image_height=*'+IntToStr(Image_Height)+'*$';


x:=0;
y:=0;

memo1.Lines.BeginUpdate;
for x := 0 to Image_width do begin
    for y := 0 to Image_height do begin
     Colors:=Image1.Canvas.Pixels[x,y];
     memo1.Text:=Memo1.Text+ColorToString(Colors);

    end;
memo1.Lines.EndUpdate;
end;
end;

It completes very slow, i think 19 second with a 640x480 picture. And after the program ready, and it put to memo1, i see something in memo1 but the program "not responding" again..

I tried with the s variable, and the program do the same.

totyak
  • 1
  • 5
  • 2
    Read the pixels using the Scanline property of TBitmap. Or from the `TImage.Canvas.Pixels[]` property. The latter will be slower. – David Heffernan Mar 17 '15 at 11:30
  • 1
    You can write a `record helper for TRGBTriple` and implement it a `ToString` method. The rest is about iterating `ScanLine`d columns and calling that method, – TLama Mar 17 '15 at 11:32
  • Interpreting scan lines though does need you to understand pixel formats...... – David Heffernan Mar 17 '15 at 11:44
  • 2
    @Close voters: I don't think that **Questions seeking debugging help ("why isn't this code working?")** is the right choice here. That reason should be used, well err, for question seeking debugging help, not for *code this for me* posts. – TLama Mar 17 '15 at 12:03
  • I think it is allmost a dublicate of this one; http://stackoverflow.com/questions/13583451/how-to-use-scanline-property-for-24-bit-bitmaps – Jens Borrisholt Mar 17 '15 at 12:03
  • 4
    This question is too brood: there are multiple solutions, and there are multiple sub-solutions. Why don't you strip this question into little pieces? Like: how to get the color of a pixel, how to convert and format a color to a string, how to add a string to a Memo, how to format/outline the strings in a memo, etc... – NGLN Mar 17 '15 at 12:16
  • I wrote something, but it doesn't work.. i tried to make it, with 2 for command in 1, but the application not respond. – totyak Mar 17 '15 at 15:12
  • I want to know how can i recover all of pixels with 1 command – totyak Mar 17 '15 at 15:13
  • 1
    Comments to your edited code. The `for` loops should go to `Image_width-1` and `Image_height-1` respectively. The `memo1.Lines.EndUpdate;` is misplaced. It should be after the `end;` of `for x := 0 to Image_width do begin`. If you had used code formating (`Ctrl-D`) it would have been easy to spot. As I said, repeatedly concatenating `memo1.Text` is awfully slow. Use the other solutions suggested. But you should really explain why you even want to convert images of that size into a hugh string? – Tom Brunberg Mar 19 '15 at 15:41
  • and if i want to save in a file, or a memory stream? It will be faster? – totyak Mar 22 '15 at 19:08

1 Answers1

2

First correction, the pixels start from 0, 0. Not 1, 1 as you have. Replace the initial values before the for loops as follows:

  x := 0; // not 1;
  y := 0; // not 1;

Actually, assigning y at this point is not required as we will soon see.

Second correction, look closer at the inner for loop. i2 steps from 1 to Image_height and y is incremented in each round of the loop, which is ok. Then a visit to the outer loop increments x and we return to the inner loop. What happens with y? It continues from where it stopped previously, while it should first be reset to 0. The cure is to add a line as follows. This is also why the assignment above is redundant.

  for i := 1 to Image_width do
  begin
    y := 0; // Add this line
    for i2 := 1 to Image_height do
    begin

Suggestions for improvement

It is unclear what you mean with resolution being unknown. If you mean color depth, or bits per pixel, it may be that your approach using pixels is more straight forward. Otherwise, as has been suggested in the comments, you could consider using scanline instead of pixels for faster access to the actual bitmap data . For an excellent article see: How to use ScanLine property for 24-bit bitmaps?

Repeatedly concatenating the color strings to the Text property is very slow. In fact it was so slow with a 64 x 64 pixel image that I couldn't wait for it to run to the end. To speed it up you can use a separate string variable to which you concatenate the color strings

  Colors := Image1.Canvas.Pixels[x, y];
  s := s + ColorToString(Colors);

and then after the loops concatenate to the Text property

  Memo1.Text := Memo1.Text + s;

If your intention was to add each pixels colorstring as a new line to the memo you can instead use the Add method

  Colors := Image1.Canvas.Pixels[x, y];
  Memo1.Lines.Add(ColorToString(Colors));

Surrounding the for loops with Memo1.Lines.BeginUpdate; and Memo1.Lines.EndUpdate; further improves speed.

Finally, you could just as well, either use x and y as loop control variables or i and i2 as pixel indexes. I would ditch i and i2, and use x and y as both loop control variables and pixel indexes. But I leave that for you to decide.

Community
  • 1
  • 1
Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54