Recent

Author Topic: [Solved] Change background color of a BMP  (Read 19034 times)

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
Re: Change background color of a BMP
« Reply #15 on: June 20, 2017, 06:39:59 pm »
I see that MaskEdit is a bitmap with either black or white pixels, and the goal is to have the white pixels of the Mask show up Red in the Image.Bitmap, while the black pixels of the mask should show the original pixel in the Image.Bitmap.

It doesn't look like MaskEdit is used when you fill the Image with
    Bitmap.Canvas.Draw(0, 0, CardBitmap);
When I run your Test app, all I get is a red card.
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
Re: Change background color of a BMP
« Reply #16 on: June 20, 2017, 06:42:00 pm »
I am using Win10. Do you think that's why we are getting different results?
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

Handoko

  • Hero Member
  • *****
  • Posts: 5150
  • My goal: build my own game engine using Lazarus
Re: Change background color of a BMP
« Reply #17 on: June 20, 2017, 06:51:04 pm »
So, the results of Linux and Wndows are different?

Have you tried the my very first example and OP's code? With some modifications I think it will give you the result that you want.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Change background color of a BMP
« Reply #18 on: June 20, 2017, 06:57:33 pm »
I see that MaskEdit is a bitmap with either black or white pixels, and the goal is to have the white pixels of the Mask show up Red in the Image.Bitmap, while the black pixels of the mask should show the original pixel in the Image.Bitmap.

It doesn't look like MaskEdit is used when you fill the Image with
    Bitmap.Canvas.Draw(0, 0, CardBitmap);
When I run your Test app, all I get is a red card.
1) This example doesn't work on Windows due to some unknown reasons - I have red card too. As I remember, such code worked in Delphi. Trying to fix it.
2) No, Lazarus uses weird algorithm like Dest = Dest xor Src; Dest = Dest and Mask; Dest = Dest xor Src; instead of MaskBlt. Therefore white means keeping dest (i.e. background) color and black means replacing it with src one.
3) You use wrong algorithm - you should use Alpha-blend, I described in my previous post. It puts transparent red film over your card.
« Last Edit: June 20, 2017, 06:59:52 pm by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

Handoko

  • Hero Member
  • *****
  • Posts: 5150
  • My goal: build my own game engine using Lazarus
Re: Change background color of a BMP
« Reply #19 on: June 20, 2017, 07:22:56 pm »
How about this result?

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Graphics, Dialogs, StdCtrls, ExtCtrls, LCLType;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Button2: TButton;
  17.     Image1: TImage;
  18.     Image2: TImage;
  19.     OpenDialog1: TOpenDialog;
  20.     procedure Button1Click(Sender: TObject);
  21.     procedure Button2Click(Sender: TObject);
  22.   end;
  23.  
  24. var
  25.   Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. const
  30.   RedShift = 40;
  31.   GreenShift = -40;
  32.   BlueShift = -40;
  33.  
  34. {$R *.lfm}
  35.  
  36. { TForm1 }
  37.  
  38. procedure TForm1.Button1Click(Sender: TObject);
  39. var
  40.   AJpg:  TJPEGImage;
  41. begin
  42.   if not(OpenDialog1.Execute) then Exit;
  43.   AJpg := TJpegImage.Create;
  44.   AJpg.LoadFromFile(OpenDialog1.FileName);
  45.   Image1.Picture.Bitmap.Assign(AJpg);
  46.   AJpg.Free;
  47.   Button2.Enabled := True;
  48. end;
  49.  
  50. procedure ChangeColor(var Data: Byte; Shift: Integer);
  51. var
  52.   Temp: Integer;
  53. begin
  54.   Temp := Data + Shift;
  55.   if (Temp > 255) then Temp := 255
  56.     else
  57.       if (Temp < 0) then Temp := 0;
  58.   Data := Temp;
  59. end;
  60.  
  61. procedure TForm1.Button2Click(Sender: TObject);
  62. var
  63.   ScanData: PRGBQuad;
  64.   X, Y: Integer;
  65. begin
  66.   Image2.Picture.Clear;
  67.   Image2.Picture.Assign(Image1.Picture);
  68.   Image2.Picture.Bitmap.BeginUpdate;
  69.   for Y := 0 to (Image1.Picture.Bitmap.Height-1) do
  70.   begin
  71.     ScanData := Image2.Picture.Bitmap.ScanLine[Y];
  72.     for X:= 0 to (Image1.Picture.Bitmap.Width-1) do
  73.     begin
  74.       ChangeColor(ScanData^.rgbRed, RedShift);
  75.       ChangeColor(ScanData^.rgbGreen, GreenShift);
  76.       ChangeColor(ScanData^.rgbBlue, BlueShift);
  77.       Inc(ScanData);
  78.     end;
  79.   end;
  80.   Image2.Picture.Bitmap.EndUpdate;
  81. end;
  82.  
  83. end.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Change background color of a BMP
« Reply #20 on: June 20, 2017, 07:42:16 pm »
How about this result?
Alpha-blend does almost the same, but it's more universal - you can even blend one picture over another. 8-)
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

Handoko

  • Hero Member
  • *****
  • Posts: 5150
  • My goal: build my own game engine using Lazarus
Re: Change background color of a BMP
« Reply #21 on: June 20, 2017, 07:44:31 pm »
I agree alpha blend is more universal. I use it a lot on GIMP. But for less accuracy solutions, mine works good. It's very simple, so it is performance wise. :D

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Change background color of a BMP
« Reply #22 on: June 20, 2017, 07:53:09 pm »
I agree alpha blend is more universal. I use it a lot on GIMP. But for less accuracy solutions, mine works good. It's very simple, so it is performance wise. :D
It works fine with white background, but result may not be so nice in case of more complex pictures. Two extra integer multiplications aren't much slower on modern hardware. Also it's accelerated in most graphic libraries. Most SIMD extensions are designed with exactly such kind of operations in mind. For example, as I know, in 3D libraries texture color is mixed with vertex color by default, so all you need - to set desired vertex colors and that's it.
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

Handoko

  • Hero Member
  • *****
  • Posts: 5150
  • My goal: build my own game engine using Lazarus
Re: Change background color of a BMP
« Reply #23 on: June 20, 2017, 07:56:35 pm »
... result may not be so nice in case of more complex pictures.

That's why I called it less accuracy solution.

Yours is good too, perhaps the best solution. Unfortunately it still has some bugs needed to fix. Maybe you can use may code but change the ChangeColor procedure with your MyAlphaBlend function.
« Last Edit: June 20, 2017, 08:02:38 pm by Handoko »

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Change background color of a BMP
« Reply #24 on: June 20, 2017, 08:23:23 pm »
That's why I called it less accuracy solution.

Yours is good too, perhaps the best solution. Unfortunately it still has some bugs needed to fix. Maybe you can use may code but change the ChangeColor procedure with your MyAlphaBlend function.
Yeah, all, that is needed - to replace ChangeColor with MyAlphaBlend. With only once exception - MyAlphaBlend is function, that takes source color as first parameter and returns color as result, instead of passing color as var. Second color - can be constant or even color of pixel from another picture. Alpha - is 0..255. 0 means "take Color1", 255 means "take Color2". All other values - linear interpolation of this two.
« Last Edit: June 20, 2017, 08:27:18 pm by Mr.Madguy »
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
Re: Change background color of a BMP
« Reply #25 on: June 20, 2017, 09:17:24 pm »
Thank you very much Madguy and Handoko. This all seems to work fine with JPG files. For some strange reason, not with BMPs.

This works in Button1
  AJpg.LoadFromFile('Jack.jpg');
  Image1.Picture.Bitmap.Assign(AJpg);     

This bombs when I click Button2, although it looks perfect after clicking Button1.
  Image1.Picture.Bitmap.LoadFromFile('Jack.bmp');

I'm not sure why it bombs.
« Last Edit: June 21, 2017, 12:31:25 am by bobonwhidbey »
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

Handoko

  • Hero Member
  • *****
  • Posts: 5150
  • My goal: build my own game engine using Lazarus
Re: Change background color of a BMP
« Reply #26 on: June 21, 2017, 04:15:52 am »
I investigated your problem. What I got is, for bmp files you need to change how the data stored internally. So you have use:

Code: Pascal  [Select][+][-]
  1. var
  2.   ScanData: PRGBTriple;

I tested it on Linux64, it worked.

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
Re: Change background color of a BMP
« Reply #27 on: June 21, 2017, 06:41:34 am »
This code, which is similar to my original, works perfectly. Thank you for your help.

If I comment out the  aJPG.Assign(CardBMP)  line, it does not work. This seems especially strange to me because the aJPG image is not being assigned to BMP. Just the process of assigning the JPG image seems to be necessary. Weird!

Unlike the fading approach you used, I prefer replacing the almost white pixels with the light red. This approach leaves all the non white colors, yellows and other colors, still as vibrant as before.

I tried PRGBTriple, also changing the colors to rgbTred, etc. but to no success.


Code: Pascal  [Select][+][-]
  1.   procedure ColorHilite;
  2.   const
  3.     delta = 50;  // from trial and error
  4.     maxd = 255 - delta;
  5.   var
  6.     Row: PRGBQuad;
  7.     x, y: integer;
  8.     R, G, B: integer;
  9.   begin
  10.     aJPG.Assign(CardBMP);   // unknown why this is necessary
  11.     BMP.Assign((CardBMP);  // weird, aJPG is not being assigned
  12.     R := GetRValue(HiliteColor);
  13.     G := GetGValue(HiliteColor);
  14.     B := GetBValue(HiliteColor);
  15.     BMP.BeginUpdate;
  16.     for y := 0 to BMP.Height - 1 do
  17.     begin
  18.       Row := BMP.ScanLine[Y];
  19.       for X := 0 to (BMP.Width - 1) do
  20.       begin
  21.         if (Row^.rgbRed > MaxD) and (Row^.rgbGreen > MaxD) and
  22.           (Row^.rgbBlue > MaxD) then
  23.         begin
  24.           Row^.rgbRed := R;
  25.           Row^.rgbGreen := G;
  26.           Row^.rgbBlue := B;
  27.         end;
  28.         Inc(Row);
  29.       end;   // for X
  30.     end; // for Y
  31.  
  32.     BMP.EndUpdate;
  33.     CardBMP.Assign(BMP);
  34.   end; // ColorHilite  
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

Handoko

  • Hero Member
  • *****
  • Posts: 5150
  • My goal: build my own game engine using Lazarus
Re: Change background color of a BMP
« Reply #28 on: June 21, 2017, 07:06:00 am »
Can you please provide the compilable code for me to test? Copy all the necessary files (exclude binary, *.exe, *.bak, images and lib folder) to a new folder. Compress that folder and send the zip file to this forum.

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Change background color of a BMP
« Reply #29 on: June 21, 2017, 08:24:38 am »
May be problem caused by the fact, that when you access raw JPG image - it's actually packed, so you can't access colors directly? That's, why I use BMPs.
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

 

TinyPortal © 2005-2018