Recent

Author Topic: TBGRABitmap and BMP  (Read 20834 times)

Timewarp

  • Full Member
  • ***
  • Posts: 144
TBGRABitmap and BMP
« on: August 13, 2012, 12:36:02 pm »
I'm trying to use BGRABitmap, but saved jpg is not what I expect. I have tried almost everything by now. Code is bellow, where is the bug? Attached project, I use Win32/1.1/2.7.1

Same code works fine with jpg file, but not bmp. 
Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var i: TImage;
    j: TJPEGimage;
    b: TBitmap;
    c: TBGRABitmap;
begin
 i:=TImage.create(self);
 i.picture.loadfromfile('test.bmp');
 b:=TBitmap.create;
 b.assign(i.picture.graphic);
 c:=TBGRABitmap.create;
 c.assign(b);
 c:=c.RotateCW as TBGRABitmap;
 j:=TJPEGimage.create;
 j.assign(c);
 j.savetofile('test.jpg');
 i.free;
 b.free;
 j.free;
 c.free;
end;

KpjComp

  • Hero Member
  • *****
  • Posts: 680
Re: TBGRABitmap and BMP
« Reply #1 on: August 13, 2012, 01:10:07 pm »
Does this do what your after?

Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var
  srcBitmap,rotBitmap:TBGRACustomBitmap;
  destJpeg:TJPEGImage;
begin
  srcBitmap := TBGRABitmap.Create('test.bmp');
  try
    rotBitmap := srcBitmap.RotateCW;
    try
      destJpeg := TJPEGImage.Create;
      try
        destJpeg.Assign(rotBitmap.Bitmap);
        destJpeg.SaveToFile('test.jpg');
      finally
        destJpeg.free;
      end;
    finally
      rotBitmap.free;
    end;
  finally
    srcBitmap.free;
  end;
end; 

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: TBGRABitmap and BMP
« Reply #2 on: August 13, 2012, 01:23:57 pm »
For loading, avoid using TPicture, TImage or TBitmap. As KpjComp suggests, load it directly like that :
Code: [Select]
srcBitmap := TBGRABitmap.Create('test.bmp');
Or by using LoadFromFile of TBGRABitmap.

For saving as a JPEG, I would recommended to create a TFPWriterJPEG object (found in FPWriteJPEG) and to use SaveToFile(filename, writer), for example like that :
Code: [Select]
rotBitmap.SaveToFile('test.jpg', JpgWriter);
So for example you can do it like that :
Code: [Select]
var
  bmp:TBGRABitmap;
  jpgWriter:TFPWriterJPEG; //in unit FPWriteJpeg
begin
  bmp := TBGRABitmap.Create('test.bmp');
  BGRAReplace(bmp, bmp.RotateCW);
  jpgWriter := TFPWriterJPEG.Create;
  //jpgWriter.CompressionQuality := ...
  bmp.SaveToFile('test.jpg', jpgWriter);
  jpgWriter.Free;
  bmp.Free;
end; 
Conscience is the debugger of the mind

Timewarp

  • Full Member
  • ***
  • Posts: 144
Re: TBGRABitmap and BMP
« Reply #3 on: August 13, 2012, 01:46:39 pm »
Thank you very much! I thought I needed to use Timage. I missed completely that you can load images like TBGRABitmap.Create('test.bmp');

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: TBGRABitmap and BMP
« Reply #4 on: August 13, 2012, 03:47:57 pm »
Quote
i:=TImage.create(self);
 i.picture.loadfromfile('test.bmp');
 b:=TBitmap.create;
 b.assign(i.picture.graphic);
Another mistake there was that you didn't need TImage...
You can do:
Code: [Select]
b:=TBitmap.create;
 b.loadfromfile('test.bmp');

Timewarp

  • Full Member
  • ***
  • Posts: 144
Re: TBGRABitmap and BMP
« Reply #5 on: August 13, 2012, 05:43:48 pm »
Another mistake there was that you didn't need TImage...
You can do:
Code: [Select]
b:=TBitmap.create;
 b.loadfromfile('test.bmp');
No, that was not really mistake. I knew that only works for bmp. My code needs to open other formats too jpg, png

This is reason why I assumed TBGRABitmap too can only take bitmaps. And need to use TImage. If name would have been "TBGRAImage", I would have found solution quickly.

After some testing it seems I may still need bitmaps in few places. Assigning TJPEGImage to TBGRABitmap did not work directly. I'm also using DelphiTwain and that gives me TBitmaps. DelphiTwain BTW compiles without changes, except I needed to add "mode delphi". (Windows ofcourse)

Timewarp

  • Full Member
  • ***
  • Posts: 144
Re: TBGRABitmap and BMP
« Reply #6 on: August 14, 2012, 11:04:03 am »
Hmm, what's happening here? Image1 is empty, but works if I add processmessages line

Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var b: TBGRACustomBitmap;
begin
 b:=TBGRABitmap.create('test.bmp');
 image1.picture.bitmap.assign(b.bitmap);
 //application.processmessages; //???
 b.free;
end;

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: TBGRABitmap and BMP
« Reply #7 on: August 14, 2012, 07:00:08 pm »
Good question. What if you do
Code: [Select]
image1.picture.assign(b.bitmap);?

Quote
No, that was not really mistake. I knew that only works for bmp. My code needs to open other formats too jpg, png

This is reason why I assumed TBGRABitmap too can only take bitmaps. And need to use TImage. If name would have been "TBGRAImage", I would have found solution quickly.
This is a false assumption, thus a mistake, but it's not that bad.

TBGRABitmap is called like this because it is a bit map, i.e., pixels are just put one after another, without any compression. The "bmp" extension has been chosen to express that it is a bit map, even if it can be a compressed bmp too. I suppose compression came afterwards.

Anyway, I suppose you understand how to load and save images, and I understand why you did a mistake in the first place. I can only advice you to browse BGRABitmap functions to see if you can find what you want to do before trying something more complicated.
Conscience is the debugger of the mind

Timewarp

  • Full Member
  • ***
  • Posts: 144
Re: TBGRABitmap and BMP
« Reply #8 on: August 14, 2012, 08:17:06 pm »
Good question. What if you do
Code: [Select]
image1.picture.assign(b.bitmap);
That is: External SIGSEGV, In file bgrawinbitmap.pas at line 150 FAlphaCorrectionNeeded:=True;

Code in post1 doesn't work, because BGRABitmap can't handle 24bit

In Delphi you could simply do

b.pixelformat:=pf32bit;

But that doesn't help here, because changing pixelformat seems to be totally unimplemented in LCL.

Basically what is needed, 24bit -> 32bit conversion

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: TBGRABitmap and BMP
« Reply #9 on: August 14, 2012, 09:22:42 pm »
Hmm.. what if you use MakeBitmapCopy function ?

Normally BGRABitmap can handle 24 bit per pixel.
Conscience is the debugger of the mind

Timewarp

  • Full Member
  • ***
  • Posts: 144
Re: TBGRABitmap and BMP
« Reply #10 on: August 14, 2012, 10:24:15 pm »
Hmm.. what if you use MakeBitmapCopy function ?
Both work without problems.
image1.picture.assign(b.MakeBitmapCopy(clblack));
image1.picture.bitmap.assign(b.MakeBitmapCopy(clblack));
Normally BGRABitmap can handle 24 bit per pixel.
It can't in post1.

I still have that problem, because I get 24bit TBitmaps from Twain.

So far I have (ugly) workaround, however it works for now. Fix for post1 code:

Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var i: TImage;
    j: TJPEGimage;
    b: TBitmap;
    c: TBGRABitmap;
    s: TMemoryStream;
begin
 i:=TImage.create(self);
 i.picture.loadfromfile('test.bmp');
 b:=TBitmap.create;
 j:=TJPEGimage.create;
 b.assign(i.picture.graphic);

 if b.pixelformat=pf24bit then
 begin
  // forces b to 32bit
  j.assign(b);
  s:=TMemoryStream.Create;
  s.Position:=0;
  j.SaveToStream(s);
  s.Position:=0;
  j.LoadFromStream(s);
  b.assign(j);
  s.free;
 end;

 c:=TBGRABitmap.create;
 c.assign(b);
 c:=c.RotateCW as TBGRABitmap;
 j.assign(c);
 j.savetofile('test.jpg');
 i.free;
 b.free;
 j.free;
 c.free;
end;

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: TBGRABitmap and BMP
« Reply #11 on: August 14, 2012, 11:12:16 pm »
Well anyway you don't need this, because you can load it directly with LoadFromFile or with TBGRABitmap.Create(...), right?
Conscience is the debugger of the mind

Timewarp

  • Full Member
  • ***
  • Posts: 144
Re: TBGRABitmap and BMP
« Reply #12 on: August 14, 2012, 11:53:26 pm »
Not that exact code, but bitmap from Twain is memory bitmap, I can't use loadfromfile.

TBGRABitmap.Create(bmp); unfortunately has the same problem as post1. (bmp is TBitmap) It just doesn't work with 24bit

circular

  • Hero Member
  • *****
  • Posts: 4221
    • Personal webpage
Re: TBGRABitmap and BMP
« Reply #13 on: August 15, 2012, 09:52:30 pm »
Do you get the message "Unable to convert image to 24 bit" ? It means that it tries to convert to 24 bit, but that it does not work. Not that it cannot handle 24 bit.

Anyway, you can trace what is going on when the Assign(TBitmap) procedure is called. It uses internally LoadFromRawImage. Debug it step by step using F8 and F7.

The variable ARawImage.Description is used to determine how to read the data. What does it contain ?
Conscience is the debugger of the mind

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: TBGRABitmap and BMP
« Reply #14 on: August 16, 2012, 07:57:13 am »
Hmm, what's happening here? Image1 is empty, but works if I add processmessages line

Code: [Select]
procedure TForm1.Button1Click(Sender: TObject);
var b: TBGRACustomBitmap;
begin
 b:=TBGRABitmap.create('test.bmp');
 image1.picture.bitmap.assign(b.bitmap);
 //application.processmessages; //???
 b.free;
end;
Propably similar to what would happen if you could set
Code: [Select]
label1.FCaption:='Test'Setting just internal data, doesn't enforce graphical updates, and you wouldn't see the text change on screen. In your case, you don't see the image change. Could there be something like image1.Picture.Restore, image1.Restore, image1.Repaint or other such methods?

Other thing is, stop making things difficult! Use simplest code designed for the task. If it doesn't work, send us 1 image and sample program in which it doesn't work with that code, and we can check out if it's bug in BGRABitmap or something else. Should KpjComp's code in second post work?

 

TinyPortal © 2005-2018