Forum > Graphics

How to make a TBitMap in 2-color-Mode (PixelFormat=pf1bit) to work?

(1/5) > >>

Hartmut:
I want to draw font characters of a selectable Font on a TCanvas of a TBitMap and then analyze their shape. For 2 reasons I want to use this TBitMap in 2-color-Mode (PixelFormat=pf1bit):
1) then I have only 2 colors to analyze (not black and white and *many* gray values)
2) it might speed things up to carry only 1 bit per pixel around instead of 24.

My code works with 'PixelFormat=pf24bit', but not with 'PixelFormat=pf1bit'. Here is a short demo:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit Unit1; {$mode objfpc}{$H+} {$IFNDEF LINUX}   {$apptype console} {for writeln on Windows}{$ENDIF} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Types; type  { TForm1 }  TForm1 = class(TForm)  Button1: TButton;  procedure Button1Click(Sender: TObject); private public end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } const BGC = clWhite; {Background Color}      FGC = clBlack; {Foreground Color} procedure drawBitMap(BM: TBitMap);   {"draws" the content of a BitMap as Hex-values}   var col: TColor;       xx,yy: longint;       x,y: integer;   begin   BM.GetSize(xx,yy); {get size of the Bitmap}    for y:=0 to yy-1 do      begin      for x:=0 to xx-1 do         begin         col:=BM.Canvas.Pixels[x,y];         write(IntToHex(col,6), ' ');         end;      writeln;      end;   end; procedure TForm1.Button1Click(Sender: TObject);   var BM: TBitMap;       CV: TCanvas;       SR: TSize;       s: string;   begin   BM:=TBitMap.Create;   BM.PixelFormat:=pf24bit; // works// BM.PixelFormat:=pf1bit;  // works not   writeln('PixelFormat=', BM.PixelFormat);    CV:=BM.Canvas; {abbreviation}   CV.Font.Name:='Courier New';   CV.Font.Height:=12;    s:='X';   SR:=CV.TextExtent(s); {get size of string 's'}   BM.SetSize(SR.cx,SR.cy);    CV.Brush.Color:=BGC;   CV.Clear;   CV.Clear;   CV.Pen.Color:=FGC;    CV.TextOut(0,0,s); {draw 's' on Canvas}   drawBitMap(BM);    {shows the content of a BitMap as Hex-values}    BM.Free;   end; end.
The demo draws letter 'X' on a Canvas and then shows the color-values of every pixel. On the screenshot you see my output:
a) with 'PixelFormat=pf24bit' you can recognize the letter 'X' with values of white ('FFFFFF') and several gray values.
b) with 'PixelFormat=pf1bit' you see, that *all* pixels have the same value ('010000'). I played with const 'BGC' and 'FGC' but this did not help. And there is a message "Gdk-WARNING **: 14:34:05.858: No colormap in gc_get_foreground". What does it mean?

What do I do wrong? I use Lazarus 2.0.10 on Linux Ubuntu 22.04. I attached a compilable project. Thanks in advance.

wp:
The trick is to set the bitmap's Monochrome property to true, and to do this immediately after creating the bitmap, before setting its size. See attached demo

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  FBitmapMono := TBitmap.Create;  FBitmapMono.Monochrome := true;  // before SetSize  FBitmapMono.SetSize(W, H);  FBitmapMono.Canvas.Brush.Color := clWhite;  FBitmapMono.Canvas.FillRect(0, 0, W, H);  FBitmapMono.Canvas.Brush.Color := clBlack;  FBitmapMono.Canvas.Ellipse(5, 5, W-10, H-10);
[P.S.]
Tried this on Windows, where it works. But double-checking on a Linux-VM I see that I get a crash when the monochrome bitmap is painted. And with your code, I get the same result as you.

[P.P.S.]
Now I see the 'x'! I must open the debug console before the bitmap is written to the console...

domasz:
PixelFormats different than 24 and 32 bit are broken in Lazarus.

Hartmut:
Hello wp, thank you for this idea. Unfortunately this trick does not help on my Linux system (as you said). Meanwhile I tested my demo on Windows 7, 32 bit, where it works without problems (no need for the monochrome-trick), see new screenshot. I'm frustrated, that again something, what works on Windows, does not work on Linux. Unfortunately I need this only for Linux...



--- Quote from: domasz on December 19, 2023, 03:55:50 pm ---PixelFormats different than 24 and 32 bit are broken in Lazarus.

--- End quote ---

Hmmm. But on Windows it works perfectly... Is this an official statement from a FPC/Lazarus developer? Is this documented somewhere?

wp:

--- Quote from: Hartmut on December 19, 2023, 05:15:43 pm ---Hello wp, thank you for this idea. Unfortunately this trick does not help on my Linux system (as you said). Meanwhile I tested my demo on Windows 7, 32 bit, where it works without problems (no need for the monochrome-trick), see new screenshot. I'm frustrated, that again something, what works on Windows, does not work on Linux. Unfortunately I need this only for Linux...

--- End quote ---
I did some further investigation why it first did not work in Linux and then it did: I also had switched from gtk2 to qt5 widgetset - on gtk2 it is not working (screenshot like in your initial post), on qt5 it works (screenshot like in my previous post). I also checked gtk3 - here the monochrome bitmap is converted to 24bit.


--- Quote from: Hartmut on December 19, 2023, 05:15:43 pm ---
--- Quote from: domasz on December 19, 2023, 03:55:50 pm ---PixelFormats different than 24 and 32 bit are broken in Lazarus.

--- End quote ---
Hmmm. But on Windows it works perfectly... Is this an official statement from a FPC/Lazarus developer? Is this documented somewhere?
--- End quote ---
In my experience, it depends... It is possible to create 1-bit, or paletted 8-bit bitmaps and to store them. But when they are loaded into a TImage they are always converted to 24 or 32-bit.

Navigation

[0] Message Index

[#] Next page

Go to full version