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
 Needing a oval crop.
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

BillM

USA
8 Posts

Posted - Dec 02 2017 :  20:43:05  Show Profile  Reply
I work for a funeral home corporation and need to write a tool that makes it easy on our employees to perform two common tasks. One is to crop and resize a photo so that we can print an 11x14 photo. No problems on this - it is done.

The second task is to crop an image to contain the face with little else detail, then to create an oval picture from this.

The following code shows what I am doing and the attachments shows the results of each step in the process.

There are two speed buttons that allow the user to select which task they will be doing and the crop settings are set to enforce the aspect ratios we need.

The first two methods below are the event handlers for these two buttons.

An OnIdle method sets the visible flag of another button to allow the user to carry out the cropping and resizing of the photos once the cropping area has been drawn. The event handler for that button is btnCropAndResizeClick. Regardless as to which speed button is pressed, the photo will be cropped and resized. If the OBIT speed button is pressed, then additional processes are implemented on the image. Namely selecting an ellipse and then masking out the area outside the ellipse.

Stage2.jpg is the cropped resized image with a size of 650 x 900 which is exactly the size we want. The next step is where things are falling apart... see Stage3.jpg

I am trying to select an ellipse with the center of the ellipse in the exact center of the image, the top of the ellipse at the top most pixel in the image, the bottom of the ellipse at the bottom most pixel. and finally the left and right edges of the ellipse to be at the corresponding left and right edges of the image. As can be seen the right, bottom, and left sides of the ellipse extends past the edges of the image. Am I doing something wrong?

Stage6.jpg shows the final results with the squared edges on the right, bottom, and left.

The .zip attachment has images from the six stages that I captured with the SaveTempFile command.



procedure TfrmMain.btnCrop11x14Click(Sender: TObject);
begin
  if btnCrop11x14.SpeedButtonOptions.Down then
  begin
    fTargetW := 3300;
    fTargetH := 4200;

    imgView.CropToolInteraction.Options := [iecoAllowResizing, iecoAllowMoving, iecoSideGripsRespectLocks];
    imgView.CropToolInteraction.LockAspectRatio := fTargetW/fTargetH;

    imgView.MouseInteract := [miCropTool];
  end
  else
  begin
    imgView.CropToolInteraction.Options := [];
    imgView.MouseInteract := [];
  end;
end;

procedure TfrmMain.btnCropObitClick(Sender: TObject);
begin
  if btnCropObit.SpeedButtonOptions.Down then
  begin
    fTargetW := 650;
    fTargetH := 900;

    imgView.CropToolInteraction.Options := [iecoAllowResizing, iecoAllowMoving, iecoSideGripsRespectLocks];
    imgView.CropToolInteraction.LockAspectRatio := fTargetW/fTargetH;

    imgView.MouseInteract := [miCropTool];
  end
  else
  begin
    imgView.CropToolInteraction.Options := [];
    imgView.MouseInteract := [];
  end;
end;

procedure TfrmMain.btnCropAndResizeClick(Sender: TObject);
begin
  fStage := 1;

  if imgView.CropToolInteraction.Selected then
  begin
    imgView.CropToolInteraction.Crop;
    imgView.Update;
    SaveTempFile(imgView, fStage);

    imgView.Proc.Resample(fTargetW,fTargetH);
    imgView.Update;
    SaveTempFile(imgView, fStage);

    if btnCropObit.Down then
    begin
      imgView.SelectEllipse(imgView.fBitmap.Width div 2, imgView.fBitmap.Height div 2, imgView.fBitmap.Width, imgView.fBitmap.Height);

      imgScreenCapture.IO.CaptureFromScreen(iecsForegroundWindowClient, -1);
      SaveTempFile(imgScreenCapture, fStage);

      MaskSelectedEllipse(Sender);
    end;

    imgScreenCapture.IO.CaptureFromScreen(iecsForegroundWindowClient, -1);
    SaveTempFile(imgScreenCapture, fStage);

    SaveTempFile(imgView, fStage, true);

    btnCrop11x14.Down := false;
    btnCropObit.Down := false;

  end;
end;

procedure TfrmMain.MaskSelectedEllipse(Sender: TObject);
var
  iRGB: TRGB;
begin
  imgView.InvertSelection;
  imgView.Proc.Fill(clBlack);
  imgView.DeSelect;

  imgScreenCapture.IO.CaptureFromScreen(iecsForegroundWindowClient, -1);
  SaveTempFile(imgScreenCapture, fStage);

  iRGB := TColor2TRGB(clBlack);

  imgView.Proc.SetTransparentColors(iRGB, iRGB, 0);
  imgView.BackgroundStyle := iebsChessboard;
  imgView.IO.Params.BitsPerSample := 8;
  imgView.IO.Params.SamplesPerPixel := 4;

  imgView.Update;
end;


attach/BillM/2017122203910_images.zip
455.98 KB

xequte

39142 Posts

Posted - Dec 04 2017 :  17:27:50  Show Profile  Reply
Hi Bill

The following will make a circular selection of entire image and then crop it

  ImageEnView1.SelectionBase := iesbBitmap;
  ImageEnView1.SelectEllipse(ImageEnView1.IEBitmap.Width div 2,
                             ImageEnView1.IEBitmap.Height div 2,
                             ImageEnView1.IEBitmap.Width,
                             ImageEnView1.IEBitmap.Height);
  ImageEnView1.Proc.CropSel();


Which is actually the same as calling:

  ImageEnView1.Proc.RoundImage(ImageEnView1.IEBitmap.Width div 2,
                               ImageEnView1.IEBitmap.Height div 2);



Note: You should never directly access ImageEnView1.fBitmap. You should set ImageEnView1.LegacyBitmap to false, and use ImageEnView1.IEBitmap.

Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

BillM

USA
8 Posts

Posted - Dec 04 2017 :  19:09:49  Show Profile  Reply
Perfect. Thank you!
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: