ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Process only pixels inside the selection (if a selection exists)?

Note: You must be registered in order to post a reply.
To register, click here. Registration is FREE!

View 
UserName:
Password:
Format  Bold Italicized Underline  Align Left Centered Align Right  Horizontal Rule  Insert Hyperlink   Browse for an image to attach to your post Browse for a zip to attach to your post Insert Code  Insert Quote Insert List
   
Message 

 

Emoji
Smile [:)] Big Smile [:D] Cool [8D] Blush [:I]
Tongue [:P] Evil [):] Wink [;)] Black Eye [B)]
Frown [:(] Shocked [:0] Angry [:(!] Sleepy [|)]
Kisses [:X] Approve [^] Disapprove [V] Question [?]

 
Check here to subscribe to this topic.
   

T O P I C    R E V I E W
PeterPanino Posted - Jun 13 2024 : 09:16:00
How to make this procedure process only the pixels inside the selection if a selection exists (even it is a non-rectangular selection like MagicWand or a multiple selection) otherwise, process all pixels in the image?

procedure TForm1.MakeTransparentByLightness(ImageEnView: TImageEnView; Threshold: Integer);
var
  x, y: Integer;
  IEBitmap: TIEBitmap;
  AlphaBitmap: TIEBitmap;
  PixelColor: TRGB;
  Lightness: Integer;
  AlphaScanLine: PByteArray;
begin
  ImageEnView.Proc.SaveUndo();

  IEBitmap := ImageEnView.IEBitmap; // Reference to the ImageEnView bitmap

  // Ensure the bitmap has an alpha channel
  if not IEBitmap.HasAlphaChannel then
    IEBitmap.AlphaChannel; // IEBitmap.AlphaChannel.Create alpha channel is undeclared

  AlphaBitmap := IEBitmap.AlphaChannel; // Reference the alpha channel bitmap

  // Process each pixel to make those below or above the threshold transparent
  for y := 0 to IEBitmap.Height - 1 do
  begin
    AlphaScanLine := AlphaBitmap.ScanLine[y];
    for x := 0 to IEBitmap.Width - 1 do
    begin
      // Access the pixel color as TRGB
      PixelColor := IEBitmap.Pixels_ie24RGB[x, y];

      // Calculate the Lightness value
      Lightness := PARGBToIntL(PixelColor);

      if Lightness <= Threshold then
        AlphaScanLine[x] := 0 // Make pixel fully transparent
      else
        AlphaScanLine[x] := 255; // Make pixel fully opaque
    end;
  end;

  // Ensure the alpha channel is in sync
  IEBitmap.SyncAlphaChannel;

  // Force the component to redraw:
  ImageEnView.Update;
  IEBitmap.AlphaChannel.SyncFull(); // it works! https://www.imageen.com/ieforum/topic.asp?TOPIC_ID=6072
  UpdateStatusBarWithImageEnView(False);
  Self.ActiveControl := ImageEnView;
end;
2   L A T E S T    R E P L I E S    (Newest First)
xequte Posted - Jun 14 2024 : 05:11:21
Hi Peter

You can optimise it by using IEBitmap.Scanline, rather than IEBitmap.Pixels_ie24RGB.

Also, move IEBitmap.AlphaChannel.SyncFull; before ImageEnView1.Update.

Nigel
Xequte Software
www.imageen.com
PeterPanino Posted - Jun 13 2024 : 10:00:05
I have finally found: TImageEnView.SelectionMask

This allows me to check if a pixel is inside the selection:

ImageEnView.SelectionMask.IsPointInside(x, y)

So, the modified procedure now processes the pixels inside a selection if a selection exists otherwise, all pixels in the image:

procedure TForm1.MakeTransparentByLightness(ImageEnView: TImageEnView; Threshold: Integer);
var
  x, y: Integer;
  IEBitmap: TIEBitmap;
  AlphaBitmap: TIEBitmap;
  PixelColor: TRGB;
  Lightness: Integer;
  AlphaScanLine: PByteArray;
  HasSelection: Boolean;
begin
  ImageEnView.Proc.SaveUndo();

  IEBitmap := ImageEnView.IEBitmap; // Reference to the ImageEnView bitmap

  // Ensure the bitmap has an alpha channel
  if not IEBitmap.HasAlphaChannel then
    IEBitmap.AlphaChannel;

  AlphaBitmap := IEBitmap.AlphaChannel; // Reference the alpha channel bitmap

  // Check if there is an existing selection
  HasSelection := not ImageEnView.SelectionMask.IsEmpty;

  // Process each pixel to make those below or above the threshold transparent
  for y := 0 to IEBitmap.Height - 1 do
  begin
    AlphaScanLine := AlphaBitmap.ScanLine[y];
    for x := 0 to IEBitmap.Width - 1 do
    begin
      // Check if the pixel is within the selection or if no selection exists
      if (not HasSelection) or (ImageEnView.SelectionMask.IsPointInside(x, y)) then
      begin
        // Access the pixel color as TRGB
        PixelColor := IEBitmap.Pixels_ie24RGB[x, y];

        // Calculate the Lightness value
        Lightness := PARGBToIntL(PixelColor);

        if Lightness <= Threshold then
          AlphaScanLine[x] := 0 // Make pixel fully transparent
        else
          AlphaScanLine[x] := 255; // Make pixel fully opaque
      end;
    end;
  end;

  // Ensure the alpha channel is in sync
  IEBitmap.SyncAlphaChannel;

  // Force the component to redraw
  ImageEnView.Update;
  IEBitmap.AlphaChannel.SyncFull;
  UpdateStatusBarWithImageEnView(False);
  Self.ActiveControl := ImageEnView;
end;


Is there any other way to improve or optimize this procedure?