Recent

Author Topic: LazPaint (alpha-blending, antialiasing, filters)  (Read 674483 times)

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
LazPaint (alpha-blending, antialiasing, filters)
« on: February 06, 2011, 02:23:42 am »
LazPaint is a painting program like PaintBrush or Paint .Net implementing drawing functions directly in Free Pascal. (Donate)

Layers can be combined with various blend modes. The drawing takes into account the level of transparency (alpha channel), shape borders are rendered with antialiasing, and color composition includes gamma correction.

With help from the Lazarus community LazPaint has been successfully compiled to work on Windows, Linux Mint, Puppy Linux and MacOS.

It is on GitHub :
https://github.com/bgrabitmap/lazpaint

Wiki help here :
http://wiki.lazarus.freepascal.org/LazPaint

Features
Layered file formats
LZP (read/write): LazPaint file format
ORA (read/write): OpenRaster exchange file format
PDN (read): Paint.NET images
oXo (read): PhoXo images
PSD (read flattened): Photoshop images

Flat images
BMP (read/write): uncompressed bitmaps (including with alpha channel, however many programs do not read the transparency information)
GIF (read(write): user can edit a frame if animated
ICO/CUR (read/write): icon, user can edit a size
JPEG : the well known compression however lossy
PCX (read/write) : Personal Computer eXchange
PNG (read/write) : Portable Network Graphic
TGA (read/write) : also called Targa
TIFF (read/write) : not all compression modes are supported
WebP (read/write) : Google Web image
XPM (read/write) : X PixMap (small C-like format)
XWD (read) : X Window Dump (screen capture)
DNG, CR2, NEF, ARW... (read) : Raw images from camera

Color manipulation
Curves : adjust curves of RGBA channels or by hue, luminosity, saturation.
Posterize : use a reduced number of values for RGB or for luminosity
Colorize : set the color of an image while preserving intensities
Shift colors : cycle colors and change colorness (saturation)
Complementary colors : use complementary colors without changing the lightness
Intensity : make colors lighter or darker without making them white
Lightness : make colors lighter or darker by making them whiter
Normalize : use the whole range of each color channel and alpha channel
Negative : invert colors (with gamma correction)
Linear negative : invert colors (without gamma correction)
Grayscale : converts colors to grayscale with gamma correction

Selection
Selection is composed with rectangles, ellipses, polygons, magic wand and pen drawing.
It contains levels of transparency, so that the border of an elliptic region has antialiasing.
With the left button you can add elements to the selection, and with the right button, you can remove elements from it.
The rotation tool allows to rotate the current selection with a free angle.
Selection fit option reduces the selection to non transparent pixels.                                                                                       
DPI Aware
LazPaint looks the same on high DPI resolutions. It works as well on Retina display and is aware of dark theme. One can change switch to dark theme manually as well.

Languages
LazPaint is available in the following languages : Arabic, Bulgarian, Chinese, Czech, Dutch, German, English, French, Finnish, Japanese, Kabyle, Latvian, Portuguese, Russian, Spanish and Swedish

Filters
Radial blur : non directional blur
Motion blur : directional blur
Custom blur : blur according to a mask
Pixelate : fake big pixels
Sharpen : makes contours more accute, complementary to Smooth
Smooth : softens whole image, complementary to Sharpen
Noise : draw random colors and intensities
Median : computes the median of colors around each pixel, which softens corners
ClearType : add a ClearType effect (displacement of RGB channels)
Inverse ClearType : remove a ClearType effect (displacement of RGB channels)
Contour : draws contours on a white background (like a pencil drawing)
Emboss : draws contours with shadow
Shaded map : draw lightened/shaded map use the image as a map of altitudes
Sphere : spherical projection
Twirl : twirl distortion (like water flowing in hole)
Cylinder : cylinder projection

Command line
LazPaint can be used from the command line to perform a variety of tasks.
From converting one image to another, creating a new image from sctratch, or applying filters to an image.
Following is a list of some of its commands.....

General Commands

HorizontalFlip,  VerticalFlip,  SwapRedBlue,  RotateCW
RotateCCW,  Resample,  Opacity,  Gradient,  New

Filter commands

You can apply filters with default values.
Blur filters : BlurPrecise, BlurRadial, BlurFast, BlurCorona, BlurDisk, BlurMotion, BlurCustom
Pixel filters : Sharpen, Smooth, Median, Emboss, Contour, Grayscale, Negative, LinearNegative, Normalize, SmartZoom3
Deformation filters : Sphere, Twirl, Cylinder, Plane
Rendering filters : PerlinNoise, CyclicPerlinNoise, Clouds, CustomWater, Water, Wood, WoodVertical, Plastik, MetalFloor, Camouflage, SnowPrint, Stone, RoundStone, Marble
« Last Edit: November 08, 2020, 06:34:45 pm by circular »
Conscience is the debugger of the mind

fabienwang

  • Sr. Member
  • ****
  • Posts: 449
  • Lazarus is the best
    • My blog
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #1 on: February 06, 2011, 05:23:25 am »
Very nice circular !
this is already better than mspaint !

if i can suggest you for the next steps:
- add select tool
- filters apply only on selection
- a script language for custom filters (pascal script or lua) (or be able to use Gimp ones
- filename in titlebar + multiple images open in tabs?
I'm using Arch Linux.
Known for: CPickSniff, OpenGrabby
Contributed to: LazPaint

benohb

  • Full Member
  • ***
  • Posts: 218
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #2 on: February 06, 2011, 07:28:44 am »
I was trying to make a similar program :D :D
the Library "bgrabitmap" in ubuntu is slow ..."rather"

# notice
You can change the place of drawing in the window

In the example with the library Unit1.pas / line 274

Code: [Select]
Bmp.Draw(Canvas,rect(0,0,ClientWidth,ClientHeight),True);

0,0 is The beginning of the drawing in the window


# notice2

Can not compile your program linux :'( :'(
I think the problem  in "bgrabitmap"

Thank you
« Last Edit: March 05, 2014, 10:55:42 pm by benohb »

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #3 on: February 06, 2011, 10:13:28 am »
Very nice circular !
this is already better than mspaint !

if i can suggest you for the next steps:
- add select tool
- filters apply only on selection
- a script language for custom filters (pascal script or lua) (or be able to use Gimp ones
- filename in titlebar + multiple images open in tabs?
That's right. I was already thinking about select tool. I would like it to be a kind of mask, with a level from 0 to 255, like a grayscale bitmap.

If you want to do it, you're welcome !  ::)

I was trying to manufacture a similar program :D :D
the Library "bgrabitmap" in ubuntu is slow ..."rather"
I know. If you have an idea to make it faster, it would be welcome.

The filters are also slow, if someone now how to boost them...

Quote
# noting
You can change the place of drawing in the window

In the example with the library Unit1.pas / line 274

Code: [Select]
Bmp.Draw(Canvas,rect(0,0,ClientWidth,ClientHeight),True);

0,0 is The beginning of the drawing in the window
I do not understand.

Quote
# noting2

Can not compile your program linux :'( :'(
I think the problem  in "bgrabitmap"
What error message do you get ?
Conscience is the debugger of the mind

LazaruX

  • Hero Member
  • *****
  • Posts: 597
  • Lazarus original cheetah.The cheetah doesn't cheat
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #4 on: February 06, 2011, 12:57:35 pm »
I tested it for 2 mins only and I think:
Very good project.
Very professional.
Well done
I think with small improvements this could become the new Paint.NET, easier thant GIMP and more powerfull than PBrush.exe

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #5 on: February 06, 2011, 02:17:17 pm »
Thank you   :)

There just some issues about slowness. Part of it depends on the freepascal compiler, which does not produce very efficient code, and part of it depends on finding way to implement faster routines (for instance with filters).
Conscience is the debugger of the mind

Leledumbo

  • Hero Member
  • *****
  • Posts: 8777
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #6 on: February 06, 2011, 04:39:52 pm »
Quote
Part of it depends on the freepascal compiler, which does not produce very efficient code
Really? How can you say so?

Phil

  • Hero Member
  • *****
  • Posts: 2737
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #7 on: February 06, 2011, 06:57:25 pm »
A number of issues on OS X / Carbon:

- See screenshot. Toolbar is rather messed up.

- Once the Colors dialog comes up, then no matter where I click on toolbar, the Colors dialog comes up again.

- Tools dialogs moves after any dialog is displayed.

- Usual sorts of things that one sees in an app that is not optimized for Mac: two Quit menu commands, wrong shortcuts for things like Undo (Cmd+Z, not Ctrl+Z).

- Is there no copy and paste support? If so, they should have Edit menu commands.

- Seems to be kind of bilingual. Open dialog title is in English, Save dialog title is in French.

Thanks.

-Phil

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #8 on: February 06, 2011, 11:33:39 pm »
Quote
Part of it depends on the freepascal compiler, which does not produce very efficient code
Really? How can you say so?
Because I've looked at the generated asm code. For example, with this Pascal code :
Code: Pascal  [Select][+][-]
  1.      p := Data;
  2.      for n := NbPixels-1 downto 0 do  //iteration
  3.      begin
  4.        if p^.alpha <> 0 then
  5.        begin
  6.          p^.red := 255-p^.red;
  7.          p^.green := 255-p^.green;
  8.          p^.blue := 255-p^.blue;
  9.        end;
  10.        //else transparent      
  11.        inc(p);
  12.      end;  
  13.      //endloop
  14.  

It gives an assembly code Which can be interpreted as :

Code: [Select]
mov SELF,rcx            //p := self.Data;
 callq GetDataPtr
 mov rax, P
  
 mov SELF,rax            //n := self.NbPixels-1;
 movslq (rax).NBPIXELS,rax
 dec rax
 mov eax, N
 
 cmpl $00, N             //if n<0 then goto @endloop;
 jl @endloop
 incl N                  //inc(n);
 nop                     //useless
 
 @iteration:
 decl N                  //dec(n);
 
 mov P,rax               //if p^.alpha = 0 then goto @transparent;
 movzbl 0x3(rax),eax
 test rax,rax            //(!) this seems to be wrong, it should test eax
 je @transparent
 
 mov P,rax               //p^.red := 255-p^.red;
 movzbl 0x2(rax),edx
 mov $00000000000000FF,rax
 sub rdx,rax
 mov rax,rdx
 mov P,rax
 mov dl,0x2(rax)
 
 mov P,rax               //p^.green := 255-p^.green;
 movzbl 0x1(rax),edx
 mov $00000000000000FF,rax
 sub rdx,rax
 mov rax,rdx
 mov P,rax
 mov dl,0x1(rax)
 
 mov P,rax               //p^.blue := 255-p^.blue;
 movzbl (rax),edx
 mov $00000000000000FF,rax
 sub rdx,rax
 mov rax,rdx
 mov P,rax
 mov dl,(rax)
 
 @transparent:
 addq $04, P             //inc(p);
 
 cmpl $00, N             //if N > 0 then goto @iteration;
 jg @iteration
 
 @endloop:

 This could be simplified by the compiler in something like :
 
 
Code: [Select]
mov SELF,rcx            //p := self.Data;  
 callq GetDataPtr
 mov rax, rdi            //( p -> rdi )
  
 mov SELF,rax            //n := self.NbPixels-1;
 movslq (rax).NBPIXELS,rdx
 dec rdx                 //( n -> rdx )
 
 js @endloop             //if n<0 then goto @endloop;
  
 xor ecx, ecx
 @iteration:
            
 cmp 0x3(rdi),ecl        //if p^.alpha = 0 then goto @transparent;
 je @transparent
 
 mov P,rax              
 notb 0x2(rdi)           //p^.red := 255-p^.red;
 notb 0x1(rdi)           //p^.green := 255-p^.green;
 notb (rdi)              //p^.blue := 255-p^.blue;
 
 @transparent:
 add $04, rdi            //inc(p);
 
 dec rdx                 //dec(n);
 jns @iteration          //if N >= 0 then goto @iteration;
 
 @endloop:
« Last Edit: February 08, 2011, 10:03:48 am by circular »
Conscience is the debugger of the mind

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #9 on: February 06, 2011, 11:40:13 pm »
A number of issues on OS X / Carbon:

- See screenshot. Toolbar is rather messed up.
You're right. On Windows too, there are some problems with toolbars, elements get scrambled. But, I wonder what I can do about it. Programming the toolbar myself ?

Quote
- Once the Colors dialog comes up, then no matter where I click on toolbar, the Colors dialog comes up again.
Maybe some other bug with the interface. I guess I cannot do anything about it except by programming it myself.

Quote
- Tools dialogs moves after any dialog is displayed.
I don't understand.

Quote
- Usual sorts of things that one sees in an app that is not optimized for Mac: two Quit menu commands, wrong shortcuts for things like Undo (Cmd+Z, not Ctrl+Z).
Ok. What method do you suggest to fix it ?

Quote
- Is there no copy and paste support? If so, they should have Edit menu commands.
Not yet.

Quote
- Seems to be kind of bilingual. Open dialog title is in English, Save dialog title is in French.
Ok I fixed it.

Phil, what about the drawing, is it slow or fast ? Is the rendering correct ?
Conscience is the debugger of the mind

Phil

  • Hero Member
  • *****
  • Posts: 2737
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #10 on: February 06, 2011, 11:43:05 pm »
You can look at some of this for ideas about how to optimize it for Mac:

http://web.me.com/macpgmr/ObjP/MacXPlatform_Part8.html


When I reposition to Tools dialog, then bring up, say, Open dialog (which hides Tools dialog, it appears), then after Open is dismissed, the Tools dialog moves back to some other position instead of the position I moved it to.

I haven't looked at it beyond just the UI.

Thanks.

-Phil

circular

  • Hero Member
  • *****
  • Posts: 4356
    • Personal webpage
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #11 on: February 07, 2011, 12:02:00 am »
When I reposition to Tools dialog, then bring up, say, Open dialog (which hides Tools dialog, it appears), then after Open is dismissed, the Tools dialog moves back to some other position instead of the position I moved it to.
Ok. I fixed it.

Quote
I haven't looked at it beyond just the UI.
Not even click once on the drawing area ?
Conscience is the debugger of the mind

Leledumbo

  • Hero Member
  • *****
  • Posts: 8777
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #12 on: February 07, 2011, 03:32:59 am »
Quote
This could be simplified by the compiler in something like
Looks like an ASMCSE optimization case. Have you enabled that? (not sure about the stability state, but AFAIK it's enabled in -O3 and I've used it and so far no trouble yet, at least in recent version).

wOvAN

  • New Member
  • *
  • Posts: 47
    • wxSoft.Ru
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #13 on: February 07, 2011, 09:54:57 am »
A way to avoid flickering.

Code: [Select]
procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND;
.......
implementation

.......

procedure TFMain.WMEraseBkgnd(var Message: TLMEraseBkgnd);
begin
   //  block Erasing background
   //  inherited EraseBackground(DC);
end;     
                                               


LazaruX

  • Hero Member
  • *****
  • Posts: 597
  • Lazarus original cheetah.The cheetah doesn't cheat
Re: LazPaint (alpha-blending, antialiasing, filters)
« Reply #14 on: February 07, 2011, 10:07:38 am »
Quote
Part of it depends on the freepascal compiler, which does not produce very efficient code
Really? How can you say so?
Because I've looked at the generated asm code. For example, with this Pascal code :
Code: Pascal  [Select][+][-]
  1.      p := Data;
  2.      for n := NbPixels-1 downto 0 do  //iteration
  3.      begin
  4.        if p^.alpha <> 0 then
  5.        begin
  6.          p^.red := 255-p^.red;
  7.          p^.green := 255-p^.green;
  8.          p^.blue := 255-p^.blue;
  9.        end;
  10.        //else transparent      
  11.        inc(p);
  12.      end;  
  13.      //endloop
  14.  

It gives an assembly code Which can be interpreted as :

Code: [Select]
mov SELF,rcx            //p := self.Data;
 callq GetDataPtr
 mov rax, P
 
 mov SELF,rax            //n := self.NbPixels-1;
 movslq (rax).NBPIXELS,rax
 dec rax
 mov eax, N
 
 cmpl $00, N             //if n<0 then goto @endloop;
 jl @endloop
 incl N                  //inc(n);
 nop                     //useless
 
 @iteration:
 decl N                  //dec(n);
 
 mov P,rax               //if p^.alpha = 0 then goto @transparent;
 movzbl 0x3(rax),eax
 test rax,rax            //(!) this seems to be wrong, it should test eax
 je @transparent
 
 mov P,rax               //p^.red := 255-p^.red;
 movzbl 0x2(rax),edx
 mov $00000000000000FF,rax
 sub rdx,rax
 mov rax,rdx
 mov P,rax
 mov dl,0x2(rax)
 
 mov P,rax               //p^.green := 255-p^.green;
 movzbl 0x1(rax),edx
 mov $00000000000000FF,rax
 sub rdx,rax
 mov rax,rdx
 mov P,rax
 mov dl,0x1(rax)
 
 mov P,rax               //p^.blue := 255-p^.blue;
 movzbl (rax),edx
 mov $00000000000000FF,rax
 sub rdx,rax
 mov rax,rdx
 mov P,rax
 mov dl,(rax)
 
 @transparent:
 addq $04, P             //inc(p);
 
 cmpl $00, N             //if N > 0 then goto @iteration;
 jg @iteration
 
 @endloop:

 This could be simplified by the compiler in something like :
 
 
Code: [Select]
mov SELF,rcx            //p := self.Data; 
 callq GetDataPtr
 mov rax, rdi            //( p -> rdi )
 
 mov SELF,rax            //n := self.NbPixels-1;
 movslq (rax).NBPIXELS,rdx
 dec rdx                 //( n -> rdx )
 
 js @endloop             //if n<0 then goto @endloop;
 
 xor ecx, ecx
 @iteration:
           
 cmp 0x3(rdi),ecl        //if p^.alpha = 0 then goto @transparent;
 je @transparent
 
 mov P,rax               
 notb 0x2(rdi)           //p^.red := 255-p^.red;
 notb 0x1(rdi)           //p^.green := 255-p^.green;
 notb (rdi)              //p^.blue := 255-p^.blue;
 
 @transparent:
 add $04, rdi            //inc(p);
 
 dec rdx                 //dec(n);
 jnz @iteration          //if N <> 0 then goto @iteration;
 
 @endloop:

Gangsterish ;-)

 

TinyPortal © 2005-2018