Recent

Author Topic: New version of BGRABitmap  (Read 284686 times)

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
New version of BGRABitmap
« on: April 13, 2014, 08:43:17 pm »
Hello,

A new version of BGRABitmap (7.3) has been released.

UTF8 support
In this version, when a UTF8 filename is expected, it is reflected by the name of the function or of the parameter:
Code: [Select]
    constructor TBGRAAnimatedGif.Create(filenameUTF8: string);
When there was no UTF8-handling function, it has been added. The class TFileStreamUTF8 is now used whenever possible to ensure maximum support of any UTF8 character.

Gtk (linux)
There was a bug when drawing an image on the canvas, sometimes the image had offset. This is hopefully corrected in 7.3 (tested on Lubuntu 32-bit).

New units
- BGRAGrayscaleMask: it is a light version of a bitmap having only one grayscale and linear channel. It does not provide any drawing capacities for now, except setpixel and direct pixel access. It is used internally by BGRAText.

- BGRAReadBMP, BGRAReadGif, BGRAReadPCX, BGRAReadPng, BGRAReadPSD, BGRAReadTGA, BGRAReadIco, bgrareadjpeg, BGRAReadXPM: these units are readers for images, that are automatically included in the program, to provide optimisations, corrections and additions to the standard ones provided by FreePascal. You may not need to make explicit reference to them because you can use them using the new TBGRAImageFormat enumeration.

- BGRAReadLzp, BGRAWriteLzp, BGRALzpCommon: this introduce a new version of Lzp format that you can use just like other image formats. The Lzp use by default a kind of RLE that is fast and does a compression that is in general a bit less efficient than PNG but still quite good (and surely much fast than PNG or zstream). It also supports layers. The software LazPaint use this format to store layered images. Note that in BGRABitmap, for now, you can only load and save flat images, so loading a layered image will just give you the flattened image of it.

- BGRAThumbnail: this unit provide fast loading and computation of thumbnails (using to display images for browsing)

- UnzipperExt: provides an unzipper that works with streams and UTF8 filenames

TAnimatedGif
To make it easy to display animated gif without using too much CPU, the following property has been added:
Code: [Select]
    property TimeUntilNextImageMs: integer read GetTimeUntilNextImage;
It returns the time in milliseconds before the next frame will be rendered. The value zero means that the Gif should be updated immedialty.

BGRABitmapTypes
- TResampleFilter provides now rfBox, which is high quality version of the stretched image. Note that the algorithm for stretched draw has been changed, it is to some extent faster and gives nice results except when the size becomes smaller than a half. In this case, not all pixels may be used to compute the resulting image. This makes it fast whatever the size of the original image is.
- TBGRAImageFormat = (ifUnknown, ifJpeg, ifPng, ifGif, ifBmp, ifIco, ifPcx, ifPaintDotNet, ifLazPaint, ifOpenRaster, ifPsd, ifTarga, ifTiff, ifXwd, ifXPixMap) are all the formats read by BGRABitmap. This goes with the following functions:
Code: [Select]
function DetectFileFormat(AFilenameUTF8: string): TBGRAImageFormat;
function DetectFileFormat(AStream: TStream; ASuggestedExtensionUTF8: string = ''): TBGRAImageFormat;
function SuggestImageFormat(AFilenameOrExtensionUTF8: string): TBGRAImageFormat;
function CreateBGRAImageReader(AFormat: TBGRAImageFormat): TFPCustomImageReader;
function CreateBGRAImageWriter(AFormat: TBGRAImageFormat; AHasTransparentPixels: boolean): TFPCustomImageWriter;
- DefaultBGRAImageReader, DefaultBGRAImageWriter: if you want to specify a reader for a specific file format.
- VGAColors: provide the basic 16 colors separately from CSS colors
- The color conversion between HSLA, GSBA and RGBA have been optimised. Also more functions to decode a string describing a color:
Code: [Select]
function BGRAToStr(c: TBGRAPixel; AColorList: TBGRAColorList = nil; AMaxDiff: Word= 0): string;
function StrToBGRA(str: string): TBGRAPixel; //full parse
function StrToBGRA(str: string; const DefaultColor: TBGRAPixel): TBGRAPixel; //full parse with default when error or missing values
function PartialStrToBGRA(str: string; const fallbackValues: TBGRAPixel; out error: boolean): TBGRAPixel; //partial parse allowed
procedure TryStrToBGRA(str: string; var parsedValue: TBGRAPixel; out missingValues: boolean; out error: boolean);

BGRAPolygon
Fixed a bug in FillShapeAliased about the computation of the horizontal position of the polygons.

BGRAScene3d
Added the following function to apply a function on each vertex/face:
Code: [Select]
     procedure ForEachVertex(ACallback: TVertex3DCallback);
    procedure ForEachFace(ACallback: TFace3DCallback);
Added the possibility to set custom flags on vertex/faces with the property CustomFlag.

BGRASliceScaling
UTF8 support to load TBGRASliceScaling and TBGRAMultiSliceScaling objects

BGRASSE
Fixed some compilation issues (constref instead of const).

BGRAStreamLayers
Supports now both Lzp compression, i.e. Zstream and RLE.

BGRAText and BGRATextFX
UTF8 support more explicit. Use of TGrayscaleMask to reduce memory usage and speed it up.
Conscience is the debugger of the mind

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: New version of BGRABitmap
« Reply #1 on: April 13, 2014, 09:05:08 pm »
TBGRABitmap
There is no more LoadAsBmp32 as this is handled by BGRAReadBmp.

There are a lot of new functions for loading/saving:
Code: [Select]
     procedure LoadFromFileUTF8(const filenameUTF8: string); virtual;
     procedure LoadFromFileUTF8(const filenameUTF8: string; AHandler: TFPCustomImageReader); virtual;
     procedure SaveToFileUTF8(const filenameUTF8: string); virtual; overload;
     procedure SaveToFileUTF8(const filenameUTF8: string; Handler:TFPCustomImageWriter); virtual; overload;

To create a handler for a specific format, use CreateBGRAImageReader/CreateBGRAImageWriter.

The function Assign can now take instead of TBitmap any TRasterImage.
Code: [Select]
    procedure Assign(ARaster: TRasterImage); override; overload;
FillMask has an additional optional parameter DrawMode:
Code: [Select]
    procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel; ADrawMode: TDrawMode); override;
    procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ADrawMode: TDrawMode); override;

There are new functions:
Code: [Select]
    procedure CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadePosition: byte; mode: TDrawMode = dmDrawWithTransparency); override;
    procedure CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadeMask: IBGRAScanner; mode: TDrawMode = dmDrawWithTransparency); override;
    procedure StretchPutImage(ARect: TRect; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); override;

StretchPutImage does what is says: it is faster than storing the resampled image first with Resample and then use Putimage.
CrossFade: draws a transition between two images. If the fade position is a constant value, then it is equivalent to simple fade between two images. When using a fademask, you can vary the progression of the fade not only during time but also in space. For example you can make the left part of the image show Source1 and the right part show Source2.

You may need to adjust the values of the property ScanOffset if the images are not all aligned on the same top-left corner.

Some functions give you the resulting bounds of drawing an image with an affine transformation:
Code: [Select]
     function GetImageAffineBounds(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap): TRect;
     function GetImageAngleBounds(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; ARestoreOffsetAfterRotation: boolean = false): TRect;
You should transmit these bounds to the drawing function you use after that.


VerticalFlip and HorizontalFlip now can take a rectangle as a parameter to specify the area to be flipped. Note that these functions do not care about the clipping rectangle, so if you want to take it into account, you need to do an IntersectRect with ClipRect.

Similary ApplyMask take more parameters:
Code: [Select]
    procedure ApplyMask(mask: TBGRACustomBitmap; ARect: TRect; AMaskRectTopLeft: TPoint); override;To specify the area and an offset for the mask. ApplyMask do not care about the clipping rectangle either.

Drawing checkers is now a basic function:
Code: [Select]
    procedure DrawCheckers(ARect: TRect; AColorEven,AColorOdd: TBGRAPixel);
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4449
    • https://lainz.github.io/
Re: New version of BGRABitmap
« Reply #2 on: April 14, 2014, 07:24:38 pm »
Thanks for the update!

Now i can load files with ñ (n tilde)

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: New version of BGRABitmap
« Reply #3 on: April 14, 2014, 11:39:21 pm »
Wonderful  :)
Conscience is the debugger of the mind

lainz

  • Hero Member
  • *****
  • Posts: 4449
    • https://lainz.github.io/
Re: New version of BGRABitmap
« Reply #4 on: April 21, 2014, 05:05:09 pm »
StretchPutImage is cool you can add StretchAndDraw in a tcanvas as destination?

Also you can add noise filter? Is random bw or random rgb (select one with a radio button) with alpha in a slider. Also in photoshop if i remember well rhere is a blur parameter. Is usefull to add some realism or texture to images. Combined with a blend mode.

Now bgracontrols are faster thanks!

Also we have added uecontrols and analog controls. About 25 usable ui controls! Plus lazpaint!
« Last Edit: April 21, 2014, 05:16:35 pm by 007 »

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: New version of BGRABitmap
« Reply #5 on: April 21, 2014, 09:40:02 pm »
Yes we are on the right track! That's a lot of great controls!

About StretchAndDraw, well the thing is that it would be equivalent to Resample(rmSimpleStretch) + Draw. It would not be optimised as it is not possible to access video memory directly. However I understand that it would be a bit simpler. I guess I would like to encourage people to resample their image once, store it, and then draw it.

About noise filter, yes it is possible to add it. For now, you can do it using the Function filter, by writing "random" in the expression. I reckon it is not very simple.

Conscience is the debugger of the mind

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: New version of BGRABitmap
« Reply #6 on: May 02, 2014, 08:46:32 pm »
New version of BGRABitmap 7.4.

What's new:
- Lanczos filter. Specify rfLanczos2, rfLanczos3 or rfLanczos4 for the ResampleFilter property.
- PutImageAffine, PutImageAngle and FilterRotate have a CorrectBlur parameter that reduces the blur effect due to the mix of pixels
- BGRAGradientScanner.TBGRARandomScanner added: it fills with pixels with random values (grayscale or color)
- BGRATypeWriter.TBGRAPolygonalGlyph has now an option to choose between angle/curve instead of autodetection

Fixes/changes:
- PCX format detection fix
- generic TBitmapTracker fix
- ApplyMask fix for transparent pixels
- randomize called in units where random is used
- BGRAFilters.TFilterTask now has a currentY property

Where to find the sources:
http://sourceforge.net/projects/lazpaint/files/src/
Conscience is the debugger of the mind

VTwin

  • Hero Member
  • *****
  • Posts: 1215
  • Former Turbo Pascal 3 user
Re: New version of BGRABitmap
« Reply #7 on: May 05, 2014, 06:11:13 pm »
Wow! Thanks so much Circular. I really appreciate your work on this.

I am trying to implement some edge detection functions, including Difference of Gaussians or similar. Can I do that using the radial blur?

I noticed you said:

Quote
About noise filter, yes it is possible to add it. For now, you can do it using the Function filter, by writing "random" in the expression. I reckon it is not very simple.

What is "the Function filter"? I can't find a reference. Does it convolve with a kernel?

Thanks again!

Cheers,
Frederick
« Last Edit: May 05, 2014, 06:12:45 pm by Frederick »
“Talk is cheap. Show me the code.” -Linus Torvalds

Free Pascal Compiler 3.2.2
macOS 12.1: Lazarus 2.2.6 (64 bit Cocoa M1)
Ubuntu 18.04.3: Lazarus 2.2.6 (64 bit on VBox)
Windows 7 Pro SP1: Lazarus 2.2.6 (64 bit on VBox)

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: New version of BGRABitmap
« Reply #8 on: May 05, 2014, 09:21:23 pm »
That is an interesting idea to do the difference of gaussians. You can use a radial blur, however, it is not very fast, so you would better use a fast blur I presume.

About function filter, we were talking with 007 of LazPaint filters (menu Filter). It uses an expression parser to apply a formula to each pixel separately. So this is different from kernels that are use to combine pixels.

In order to implement it, I have added BGRAGradientScanner.TBGRARandomScanner that you can use like that:
Code: [Select]
uses BGRABitmap, BGRABitmapTypes, BGRAGradientScanner;

{ TForm1 }

procedure TForm1.FormPaint(Sender: TObject);
var bmp: TBGRABitmap;
  scan: TBGRARandomScanner;
begin
  bmp := TBGRABitmap.Create(ClientWidth,ClientHeight);
  scan := TBGRARandomScanner.Create(False,255);
  bmp.Fill(scan);
  scan.Free;
  bmp.Draw(Canvas,0,0);
  bmp.Free;
end;
Conscience is the debugger of the mind

VTwin

  • Hero Member
  • *****
  • Posts: 1215
  • Former Turbo Pascal 3 user
Re: New version of BGRABitmap
« Reply #9 on: May 09, 2014, 02:39:54 pm »
Circular,

Thanks for the explanation. I implemented a few edge filters by writing code to convolve and correlate kernels. They are probably not optimal, but work for what I need.

Thanks again for your work on TBGRABitmap. I look forward to any future versions.

Cheers,
Frederick
“Talk is cheap. Show me the code.” -Linus Torvalds

Free Pascal Compiler 3.2.2
macOS 12.1: Lazarus 2.2.6 (64 bit Cocoa M1)
Ubuntu 18.04.3: Lazarus 2.2.6 (64 bit on VBox)
Windows 7 Pro SP1: Lazarus 2.2.6 (64 bit on VBox)

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: New version of BGRABitmap
« Reply #10 on: May 09, 2014, 08:29:40 pm »
New version of BGRABitmap 7.5, just to fix an "intellisense typo" that cause a crash with StretchPutImage on 64-bit processors.

http://sourceforge.net/projects/lazpaint/files/src/
« Last Edit: May 09, 2014, 08:31:34 pm by circular »
Conscience is the debugger of the mind

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: New version of BGRABitmap
« Reply #11 on: July 23, 2014, 04:09:13 pm »
New version 7.6 of BGRABitmap!

SVG support
- Basic handling of CSS units in BGRAUnits.pas
- Basic handling of SVG in BGRASVG.pas

How to use SVG:

Code: [Select]
Uses BGRABitmap, BGRABitmapTypes, BGRASVG, BGRAUnits;
var svg: TBGRASVG;
begin
  bmp := TBGRABitmap.Create(500,500, BGRAWhite);

  //it is recommended to initialise the SVG with size and unit
  //otherwise, the size is kind of undefined

  svg := TBGRASVG.Create(10,6,cuCentimeter);
  svg.Content.AppendPath('M1,1 L9,1 9,5 1,5 z', cuCentimeter).fillColor := CSSGreen;
  svg.Content.AppendRect(2,2,6,2, cuCentimeter).fillColor:= BGRA(255,255,0,192);
  with svg.Content.AppendRect(0,0,svg.Units.ConvertWidth(1,cuCentimeter,cuPixel),
  svg.Units.ConvertHeight(1,cuCentimeter,cuPixel), cuPixel) do
  begin
    fillColor := CSSBlue;
    fillOpacity:= 0.2;
  end;
  svg.Content.AppendRoundRect(3,3,4,1, 0.3,0.3, cuCentimeter).fillColor := CSSOrange;
  with svg.Content.AppendLine(150,150,450,250, cuPoint) do
  begin
    strokeColor := BGRABlack;
    strokeOpacity:= 0.8;
  end;
  svg.Content.AppendLine(svg.ViewBox.min,svg.ViewBox.min+svg.ViewBox.size).strokeColor := CSSRed;
  with svg.Content.AppendCircle(5,3,3,cuCentimeter) do
  begin
    strokeColor := CSSRed;
    strokeWidth := FloatWithCSSUnit(2,cuPoint);
    fillNone;
  end;

  //SVG needs to be drawn on a Canvas2D surface
  svg.Draw(bmp.Canvas2D,50,50,cuPoint);
  //SVG can be saved in a file that can be viewed in
  //a web browser or in InkScape for example
  svg.SaveToFile('test.svg');
  svg.Free;
 
  //you can display the bitmap or save it to a file

  bmp.Free;
end;

Drawing improvements
- PutImageAffine and PutImageAngle have more options
- function to get intermediate pixels using integer values only :
Code: [Select]
     function TBGRABitmap.GetPixel256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; virtual; abstract;
     function TBGRABitmap.GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; virtual; abstract; overload;
     function TBGRABitmap.GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; virtual; abstract; overload;

- TBGRAPath (in unit BGRAPath) can contain any path (supports SVG definition of a path)
- arc definition: TArcDef, ArcDef(...) to be used with TBGRAPath
Code: [Select]
function Html5ArcTo(const p0, p1, p2: TPointF; radius: single): TArcDef;
function SvgArcTo(const p0: TPointF; rx, ry, xAngleRadCW: single; largeArc,
  anticlockwise: boolean; const p1: TPointF): TArcDef;
function ArcStartPoint(const arc: TArcDef): TPointF;
function ArcEndPoint(const arc: TArcDef): TPointF;
function IsLargeArc(const arc: TArcDef): boolean;

- function to draw paths:
Code: [Select]
     procedure TBGRABitmap.DrawPath(APath: IBGRAPath; c: TBGRAPixel; w: single); virtual; abstract;
     procedure TBGRABitmap.DrawPath(APath: IBGRAPath; texture: IBGRAScanner; w: single); virtual; abstract;
     procedure TBGRABitmap.FillPath(APath: IBGRAPath; c: TBGRAPixel); virtual; abstract;
     procedure TBGRABitmap.FillPath(APath: IBGRAPath; texture: IBGRAScanner); virtual; abstract;

Canvas2D
- Canvas2d has helper functions that use LCL types, TAffineMatrix, TBGRAPath, TArcDef, to draw ellipses

Notably Canvas2d now support text drawing, with any matrix transformation. To do so, you need to specify a text renderer that supports vectorial drawing:
Code: [Select]
uses BGRABitmap, BGRABitmapTypes, BGRAVectorize;
var bmp: TBGRABitmap;
begin
  bmp := TBGRABitmap.Create;
  bmp.Canvas2D.fontRenderer := TBGRAVectorizedFontRenderer.Create; //here we supply an adequate font renderer
  bmp.Canvas2D.font := '20px Arial';
  bmp.Canvas2D.fillStyle(BGRABlack);
  bmp.Canvas2D.textBaseline := 'top'; //we can align the text to baseline, top, bottom...
  bmp.Canvas2D.translate(50,50);
  bmp.Canvas2D.scale(10,10);
  bmp.Canvas2D.rotate(-30*Pi/180);
  bmp.Canvas2D.fillText('Test1',0,0);
end;

Misc
- LZP format can store paletted RGB (automatically reduce the size of images with less than 256 colors)
- Fixed a bug with TBGRABitmap.SaveToFile calling the wrong sub function
- Fixed a bug with fill function when there would be a point without a successor
- optimisation of bitmap rotation
- more robust streaming of layered images
- other small fixes

http://sourceforge.net/projects/lazpaint/files/src/

Cheers
Conscience is the debugger of the mind

exdatis

  • Hero Member
  • *****
  • Posts: 668
    • exdatis
Re: New version of BGRABitmap
« Reply #12 on: July 23, 2014, 11:51:11 pm »
Thank you very much, circular!

circular

  • Hero Member
  • *****
  • Posts: 4181
    • Personal webpage
Re: New version of BGRABitmap
« Reply #13 on: July 24, 2014, 05:48:33 pm »
You're welcome!  :D
Conscience is the debugger of the mind

Dibo

  • Hero Member
  • *****
  • Posts: 1048
Re: New version of BGRABitmap
« Reply #14 on: July 24, 2014, 11:34:50 pm »
Nice to see how BGRABitmap is growing up and now you are going to CSS world. I'm impressed. Maybe in future we will have good alternative for HTMLPort or IpHTMLPanel ;) . I have question, you are drawing text by your self right? I mean, you are not using OS API for that. I always wanted to create "own drawed" TEdit like control. Main purpose is:
- Text hint / placeholder on all platforms (Qt, Gtk, Windows). This is a hint which is showed when edit text is empty. Normally only Gtk (ver 3+) and Qt has it, but due that windows edit doesn't, LCL is not publishing this property
- Extra buttons inside TEdit

My questions is: do BGRABitmap has some handy routines for text drawing? I tried do this using TCanvas but I have problems with calculating word wrap for static and selected text (it was dependend on OS API), cursor pos etc.

 

TinyPortal © 2005-2018