Recent

Author Topic: Write to Image.Picture.JPEG.Canvas  (Read 23114 times)

LacaK

  • Hero Member
  • *****
  • Posts: 691
Write to Image.Picture.JPEG.Canvas
« on: September 16, 2015, 07:56:54 pm »
I have on form TImage where is loaded JPEG image (TJPEGImage).

I want write to this image.

I use for example:
Code: [Select]
with Image1.Picture.JPEG.Canvas do begin
    Pen.Color:=clRed;
    Line(0,30,50,80);
end;

Line is written, but in "transparent" (gray) color. I am not able set other color.
Same result when I use for example:
Code: [Select]
for y:=10 to 50 do
      for x:=10 to 50 do begin
        //Canvas.Pixels[x,y] := clBlue;
        Canvas.Colors[x,y] := TColorToFPColor(clBlue);
end;

But when I load Bitmap (TBitmap) above works as expected.
Where should be problem ?

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Write to Image.Picture.JPEG.Canvas
« Reply #1 on: September 16, 2015, 08:24:34 pm »
2 questions.
1) why would you try to use a jpeg canvas at all? Simple copy it to a bitmap and draw there.
2) what is the pixel format of the jpeg? Something tells me its either a palette based image or something exotic like 16 or 12 bit.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: Write to Image.Picture.JPEG.Canvas
« Reply #2 on: September 16, 2015, 08:27:53 pm »
How about this:
Code: [Select]
  with Image1.Canvas do
  begin
    Pen.Color := clRed;
    Line(0, 30, 50, 80);
  end;
Or do you need to save the changed image to jpg?

LacaK

  • Hero Member
  • *****
  • Posts: 691
Re: Write to Image.Picture.JPEG.Canvas
« Reply #3 on: September 16, 2015, 08:44:42 pm »
JPEG is normal no specific.
Look at attached project please. Run and press "Button2"

When I assign Image1.Picture.Bitmap to temporary TBitmap and write there, still does not work ...

I need write to Image1.Picture.JPEG.Canvas because when I write only to Image1.Canvas changes are gone when image is scrolled out of visible area and then back ...

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: Write to Image.Picture.JPEG.Canvas
« Reply #4 on: September 16, 2015, 09:19:19 pm »
The fun part is if you make a fourth button and do this:
Code: [Select]
procedure TForm1.Button4Click(Sender: TObject);
begin
  with Image1.Picture.Jpeg.Canvas do
  begin
    Pen.Color := clRed;
    Line(0, 30, 50, 80);
  end;
  Image1.Picture.Jpeg.SaveToFile('c:\temp\test.jpg');
  Image1.Picture.Jpeg.LoadFromFile('c:\temp\test.jpg');
end;

You do get a red line  :P

LacaK

  • Hero Member
  • *****
  • Posts: 691
Re: Write to Image.Picture.JPEG.Canvas
« Reply #5 on: September 16, 2015, 10:14:14 pm »
The fun part is if you make a fourth button and do this:
Code: [Select]
procedure TForm1.Button4Click(Sender: TObject);
begin
  with Image1.Picture.Jpeg.Canvas do
  begin
    Pen.Color := clRed;
    Line(0, 30, 50, 80);
  end;
  Image1.Picture.Jpeg.SaveToFile('c:\temp\test.jpg');
  Image1.Picture.Jpeg.LoadFromFile('c:\temp\test.jpg');
end;

You do get a red line  :P
Yes, I noticed it also ... but original question remains : why Button2 does not write red line ?

derek.john.evans

  • Guest
Re: Write to Image.Picture.JPEG.Canvas
« Reply #6 on: September 16, 2015, 10:26:02 pm »
This is a PixelFormat issue. A lot of JPEG & PNG's are loaded as pf32bit. TCanvas doesn't work with pf32bit. (ie: alpha channels)

you need to convert the TBitmap to pf24bit.

Code: Pascal  [Select][+][-]
  1. procedure BitmapMake24Bit(const ABitmap: TBitmap);
  2. var
  3.   LTempBitmap: TBitmap;
  4. begin
  5.   if ABitmap.PixelFormat <> pf24bit then begin
  6.     LTempBitmap := TBitmap.Create;
  7.     try
  8.       LTempBitmap.PixelFormat := pf24bit;
  9.       LTempBitmap.SetSize(ABitmap.Width, ABitmap.Height);
  10.       LTempBitmap.Canvas.Draw(0, 0, ABitmap);
  11.       ABitmap.PixelFormat := pf24bit;
  12.       ABitmap.Canvas.Draw(0, 0, LTempBitmap);
  13.     finally
  14.       FreeAndNil(LTempBitmap);
  15.     end;
  16.   end;
  17. end;  
  18.  

Example Use:
Code: Pascal  [Select][+][-]
  1.   Image1.Picture.LoadFromFile('MyPicture.jpg');
  2.   BitmapMake24Bit(Image1.Picture.Bitmap);
  3.   Image1.Picture.Bitmap.Canvas.Pen.Color := clRed;
  4.   Image1.Picture.Bitmap.Canvas.Line(0, 0, 100, 100);    
  5.  


Or, start using TBGRABitmap if you want to draw to a 32 bit bitmap.
« Last Edit: October 02, 2015, 03:07:24 am by Geepster »

derek.john.evans

  • Guest
Re: Write to Image.Picture.JPEG.Canvas
« Reply #7 on: September 16, 2015, 10:31:45 pm »
Note: The above code doesnt handle transparent PNG's, (which have alpha channels)

To handle those, you need to set the background of a pf24bit TBitmap to a color (eg: clWhite), and then draw the PNG onto that. The alpha channel will blend partially transparent pixels into clWhite.

Download a PNG like this to play with:
http://img3.wikia.nocookie.net/__cb20130203061323/disney/images/6/6b/Donald_Duck_transparent.png

LacaK

  • Hero Member
  • *****
  • Posts: 691
Re: Write to Image.Picture.JPEG.Canvas
« Reply #8 on: September 17, 2015, 09:31:01 am »
Thak you very much. Now it works.
It is documented somewhere, that TBitmap must be pf24bit to write to its canvas ?
I have read for example: http://wiki.freepascal.org/Developing_with_Graphics but there is no such note.

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: Write to Image.Picture.JPEG.Canvas
« Reply #9 on: September 17, 2015, 10:36:25 am »
It is documented somewhere, that TBitmap must be pf24bit to write to its canvas ?
I have read for example: http://wiki.freepascal.org/Developing_with_Graphics but there is no such note.
You may add a note yourself under this header:
http://wiki.freepascal.org/Developing_with_Graphics#Painting_on_the_bitmap_of_a_TImage

LacaK

  • Hero Member
  • *****
  • Posts: 691
Re: Write to Image.Picture.JPEG.Canvas
« Reply #10 on: September 17, 2015, 10:52:41 am »
Yes I know, but I would leave it for somebody more experienced with graphics ;-)

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Write to Image.Picture.JPEG.Canvas
« Reply #11 on: September 17, 2015, 11:55:41 am »
is that a linux/gtk only thing? If memory serves me right I have already used 32bit bitmaps on windows under win32 and qt widgeset for a port of the rmklever progress bar, setting successfully the pixel transparency and color. I do not remember to use the tcolortoFPColor function though I simple used an rgbQuad record to manipulate the color and I used direct data access(delphi scanline equivalent) of the fpimage. In any case I think the canvas.pixels should be able to handle 32bit images with no problem and the various drawing methods should call the native widgetset drawing procedures gdi in win32, qt canvas methods etc, which should all support 32bit colors.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

LacaK

  • Hero Member
  • *****
  • Posts: 691
Re: Write to Image.Picture.JPEG.Canvas
« Reply #12 on: September 17, 2015, 08:19:41 pm »
In any case I think the canvas.pixels should be able to handle 32bit images with no problem and the various drawing methods should call the native widgetset drawing procedures gdi in win32, qt canvas methods etc, which should all support 32bit colors.
Then it is probably bug ?
I am on Windows.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Write to Image.Picture.JPEG.Canvas
« Reply #13 on: September 17, 2015, 08:26:35 pm »
In any case I think the canvas.pixels should be able to handle 32bit images with no problem and the various drawing methods should call the native widgetset drawing procedures gdi in win32, qt canvas methods etc, which should all support 32bit colors.
Then it is probably bug ?
I am on Windows.
Give me some time to run a couple of tests against pure win api. My focused was on porting the component instead of testing the 32bit support so I might have overlooked something. But as a first impression I would say either a bug or a case of "cross platform uniformity".
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

derek.john.evans

  • Guest
Re: Write to Image.Picture.JPEG.Canvas
« Reply #14 on: September 18, 2015, 02:00:17 am »
Give me some time to run a couple of tests against pure win api. My focused was on porting the component instead of testing the 32bit support so I might have overlooked something. But as a first impression I would say either a bug or a case of "cross platform uniformity".

Arrrr. I think I found the problem.  I'm wrong (again) 32bit drawing _is_ working, but GDI functions set the alpha to 0.

Drawing a 32bit TBitmap always uses the alpha channel, which means the GDI drawings are 100% transparent, which explains the gray (TForm) color.

Solutions Ive seen involve manually setting the alpha values of the rawimage, which means you loose the alpha of a transparent PNG.

I dont know how Delphi solved this one. Maybe they dont treat 32bit TBitmaps as always being transparent?

** EDIT **
Btw: Delphi doesn't clear a TBitmap to black when you change PixelFormat, and when loading a JPEG, you get a 24bit image. Not a 32bit.

I guess, I would always draw a JPEG into a 24bit image, and "flattern" 32bit PNG to 24bit.

I dont recall 32bit TBitmap editing in Delphi being overly flexable, so, I guess the TBGRABitmap advice still is good.
« Last Edit: September 18, 2015, 02:04:32 am by Geepster »

 

TinyPortal © 2005-2018