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

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Process only pixels inside the selection (if a selection exists)?
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

PeterPanino

933 Posts

Posted - Jun 13 2024 :  09:16:00  Show Profile  Reply
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;

PeterPanino

933 Posts

Posted - Jun 13 2024 :  10:00:05  Show Profile  Reply
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?
Go to Top of Page

xequte

38610 Posts

Posted - Jun 14 2024 :  05:11:21  Show Profile  Reply
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
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: