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
 Building a Collage
 New Topic  Reply to Topic
Next Page
Author Previous Topic Topic Next Topic
Page: of 2

oldbitman

USA
16 Posts

Posted - Aug 03 2014 :  11:01:48  Show Profile  Reply
I am moving from Imagelib to ImageEn and the capabilities are overwhelming. I am trying to build a "collage" with a base image and up to 4 layers that can be moved, sized and rotated with the mouse before flattening to a final image. I am still going through all the forum posts and samples and wonder if anyone has a sample that will get me started on this?
Thanks

Gary Gonnella

w2m

USA
1990 Posts

Posted - Aug 03 2014 :  11:09:29  Show Profile  Reply
See the ..\Demo\ImageEditing\Layers demo in the demos folder. It shows how to move, resize and rotate layers. There is no reason to construct a new demo when the provided demo shows how to do everything you are looking for.

Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
Go to Top of Page

oldbitman

USA
16 Posts

Posted - Aug 03 2014 :  11:27:53  Show Profile  Reply
Thanks, I hadn't run across that one yet.

Gary Gonnella
Go to Top of Page

oldbitman

USA
16 Posts

Posted - Aug 07 2014 :  10:48:12  Show Profile  Reply
I should be able to find this but reading the ebook and searching I haven't found the solution for the next problem.
I am building the collage correctly and layer0 is my locked background. However is I move one of the layers past the edges of my background and then flatten it increases the size of the image to have a white boarder around the background. I want to limit it to the background size and if they move a layer beyond the edges than that layer will get cropped.
Thanks, and I am continuing to read.

Gary Gonnella
Go to Top of Page

w2m

USA
1990 Posts

Posted - Aug 07 2014 :  12:26:38  Show Profile  Reply
I advised the ImageEn developers about this problem about a year ago. As far as I know it is not yet possible to crop the layer if the layers bounds exceed the bitmap dimensions in layer 0.

For some clients I have worked around the problem by not allowing a layers bounds to extend off the bitmap bounds in layer 0. It works, but it would be a good feature to add optionally cropping any outlying layers.

The improved LayersMerge would look something like this:
procedure LayersMerge(Layer0, Layer1: integer; RemoveUpperLayer: Boolean=true; Crop: boolean);

ImageEnView1.LayersMerge(0, ImageEnView1.LayersCurrent, True, True);

Where the last boolean value would crop the layers.

The LayersMergeAll procedure would also have to be modified as well:
procedure LayersMergeAll(Crop: boolean);



Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
Go to Top of Page

xequte

38514 Posts

Posted - Aug 07 2014 :  14:58:30  Show Profile  Reply
@Bill

We have forgotten about this request, but it hasn't yet made it to the top of the to-do list, unfortunately.

@Gary

As Bill advised, LayersMerge does not support cropping at this stage.

You must use ImageEnView1.LayersMergeAll() to crop to the background.

Note: This method does not support the alpha channel.


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

oldbitman

USA
16 Posts

Posted - Aug 08 2014 :  08:28:39  Show Profile  Reply
Given all that are there some rules that are applied as to how much the canvas is extended and in which direction. It appears that there are specific increments it takes and if I go beyond that with my layer it crops it. If I can find out how much the canvas gets extended and in which directions I can look at the original size and calculate a cropping based on the new size.

Thanks for any help.

Gary Gonnella
Go to Top of Page

oldbitman

USA
16 Posts

Posted - Aug 08 2014 :  12:11:53  Show Profile  Reply
As another option is there a way to limit the movement of the layers so that they don't pass the edges of the background?

Gary Gonnella
Go to Top of Page

w2m

USA
1990 Posts

Posted - Aug 08 2014 :  12:16:54  Show Profile  Reply
procedure TForm1.ImageEnVect1LayerNotify(Sender: TObject; layer: Integer;
  event: TIELayerEvent);
{ ImageEnVect Layer Notify. }
var
  iLayerPosX: Integer;
  iLayerPosY: Integer;
  iLayer0Width: Integer;
  iLayer0Height: Integer;
  iLayerWidth: Integer;
  iLayerHeight: Integer;
begin
  { Constrain XPos to layer 0 }
  if (layer <> 0) and ((event = ielMoved) or (event = ielMoving)) then
  begin
    iLayerPosX := ImageEnVect1.Layers[layer].PosX;
    iLayer0Width := ImageEnVect1.Layers[0].Width;
    iLayerWidth := ImageEnVect1.Layers[layer].Width;
    if iLayerPosX > iLayer0Width - iLayerWidth then
      ImageEnVect1.Layers[layer].PosX := iLayer0Width - iLayerWidth
    else if iLayerPosX < 0 then
      ImageEnVect1.Layers[layer].PosX := 0;
  end;

  { Constrain YPos to layer 0 }
  if (layer <> 0) and ((event = ielMoved) or (event = ielMoving)) then
  begin
    iLayerPosY := ImageEnVect1.Layers[layer].PosY;
    iLayer0Height := ImageEnVect1.Layers[0].Height;
    iLayerHeight := ImageEnVect1.Layers[layer].Height;
    if iLayerPosY > iLayer0Height - iLayerHeight then
      ImageEnVect1.Layers[layer].PosY := iLayer0Height - iLayerHeight
    else if iLayerPosY < 0 then
      ImageEnVect1.Layers[layer].PosY := 0;
  end;
end;


This prevents the user from moving a layer > 0 beyond the bounds of layer 0. You can do the same thing with TImageEnView.

Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
Go to Top of Page

oldbitman

USA
16 Posts

Posted - Aug 08 2014 :  12:52:07  Show Profile  Reply
Thank you very much

Gary Gonnella
Go to Top of Page

xequte

38514 Posts

Posted - Aug 11 2014 :  12:54:46  Show Profile  Reply
Hi

FYI, the next release will support cropping when merging layers.

There will also be an an overload of LayersMerge which takes an array of integers containing the indexes of the layers to merge, e.g.

ImageEnView.LayersMerge([0, 1, 2]);  // merge layers 0, 1 and 2

or

ImageEnView.LayersMerge([]);   // merge all layers


Merging selected layers:

// merge selected layers
procedure Tfmain.Button3Click(Sender: TObject); 
begin
  if ImageEnMView1.MultiSelectedImagesCount > 1 then
  begin
    ImageEnMView1.MultiSelectSortList(); // here we need sorted items
    ImageEnView1.LayersMerge( ImageEnMView1.MultiSelectedImagesList );

    RefreshControls();
    RefreshLayerViewer();
  end;
end;


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

oldbitman

USA
16 Posts

Posted - Aug 18 2014 :  11:10:49  Show Profile  Reply
I really hate to be such a pain but there is some setting that I am missing. When I build a collage and merge the layers I get the attached file. I am using high rez images and when I do this through the layers demo I don't get the same problem. I know I am missing something simple.



thanks

Gary Gonnella
Go to Top of Page

w2m

USA
1990 Posts

Posted - Aug 18 2014 :  12:48:08  Show Profile  Reply
It is difficult to say because you did not post any code. Visually the image looks as it should look after you merged layers. What is visually wrong with the image? What should it look like? Show your code.

Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
Go to Top of Page

oldbitman

USA
16 Posts

Posted - Aug 18 2014 :  12:53:16  Show Profile  Reply
The layers are coming out extremely pixelated. However I think I found the problem by setting:
ImageEnView1.LayersRotationFilter := ierBicubic;
ImageEnView1.LayersRotationAntialias := true;


Gary Gonnella
Go to Top of Page

xequte

38514 Posts

Posted - Aug 18 2014 :  13:40:54  Show Profile  Reply
Hi Gary

Yes, that's what you need. Can also be useful to use:

http://www.imageen.com/help/TImageEnView.LayersRotationUseFilterOnPreview.html

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

oldbitman

USA
16 Posts

Posted - Aug 21 2014 :  13:17:18  Show Profile  Reply
And another question. When I rotate an image in a layer then read it's rotate property I always get 0.
I can set the rotation with this: imageEnView1.layers[loop].Rotate := rotate;
When I read it back I get: rotate := imageEnView1.layers[loop].Rotate; I get 0. Is there a different property to read the rotation?

As always, Thanks

Gary Gonnella
Go to Top of Page

xequte

38514 Posts

Posted - Aug 21 2014 :  14:19:09  Show Profile  Reply
Hi Gary

I cannot reproduce that. What method are you using to rotate (via code or user interaction). Do you call anything after rotation and prior to reading Rotate?

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

oldbitman

USA
16 Posts

Posted - Aug 21 2014 :  14:32:12  Show Profile  Reply
Nigel, I am using the user interface to rotate then not calling anything else.
In your sample Rotatelayers:

ImageEnView1.LayersRotationAntialias := true;
ImageEnView1.LayersRotationFilter := ierBilinear;
ImageenView1.LayersFixRotations();
ImageenView1.Update();

If I read the property imageEnView1.layers[loop].Rotate after the LayersFixRotations I always get 0.

However I do appear to get the correct rotation if I read the imageEnView1.layers[loop].Rotate before LayersFixRotations. Maybe I need to store the value at the end of each rotation?

Gary Gonnella
Go to Top of Page

xequte

38514 Posts

Posted - Aug 22 2014 :  02:35:10  Show Profile  Reply
Hi Gary

Yes, once you call LayersFixRotations then the rotation is "Fixed". The rotated image becomes permanent and cannot be reset (and thus the rotate property will be zero).



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

oldbitman

USA
16 Posts

Posted - Aug 22 2014 :  09:22:51  Show Profile  Reply
Thanks Nigel, I got around it by having variables that I save to each time it is rotated. Then I save the values to the config file so the next time I create a collage it puts them in the same place. Moving forward and learning.

Gary Gonnella
Go to Top of Page

oldbitman

USA
16 Posts

Posted - May 14 2015 :  16:36:31  Show Profile  Reply
I have come back to working on this collage project. It is working but there are some major problems. To recap, I am loading an image into layer 0 then placing 2 to 4 overlays on top. I am attempting to save the position including rotation of each overlay then the next time I am loading images with the previous settings. If there is no rotation this works well but when I rotate the numbers I save don't match.

This is a snippet of how I load up the images:
On form activate I set these values:
 ImageEnView1.LayersRotationUseFilterOnPreview :=true;    // make it fast preview
  ImageEnView1.LayersRotationDelayFilterOnPreview := true;


  ImageEnView1.SetLayersGripStyle(clBlack, clLime, bsSolid, 5, iegsCircle);
  ImageEnView1.ForceALTkey := true; // aspect ratio
  ImageEnView1.Blank;
  ImageEnView1.LayersSync := false;
  ImageEnView1.MouseInteract := [miMoveLayers, miResizeLayers {, miRotateLayers}];



This is my function to build the layout:
 function TFRM_collage.BuildCollage(Sender: tObject;
  layers: integer;
  Image1, Image2, Image3, Image4: string;
  shadow: boolean): integer;
var
  localconfigName: string;
  loop: integer;
  ThisIni: TIniFile;
  background: string;
  top: integer;
  left: integer;
  maxsize: integer;
  rotate: single;
  shadowradius: integer;
  shadowoffsetx: integer;
  shadowoffsety: integer;
  shadowintensity: integer;
  Ratio: double;
  schematic: string;
begin
  SaveMove1 := 1; // set them all to their default values.
  SaveMove2 := 2;
  SaveMove3 := 3;
  SaveMove4 := 4;
  ImageEnView1.LayersRotationFilter := ierBicubic;
  ImageEnView1.LayersRotationAntialias := true;

  result := 0;
  imageEnView1.Clear; // empty it all out
  LocalConfigName := Form1.DataBasePath + '\layout' + inttostr(layers) + '.CLD';
  if not fileexists(LocalConfigName) then
  begin
    result := loop;
    MessageDlg('The Required Layout File Could Not Be Found:' + #13 + #10 + LocalConfigName, mtError, [mbOK], 0);
    BTN_cancelClick(self);
    exit;
  end;
  ThisIni := TIniFile.Create(LocalConfigName);
  background := ThisIni.ReadString('fullpage', 'name', '');
  if not fileexists(background) then
  begin
    result := -1;
    MessageDlg('The Required Background File Could Not Be Found:' + #13 + #10 + background, mtError, [mbOK], 0);
    BTN_cancelClick(self);
    exit;
  end;

// put the bckground image
  imageEnView1.AutoShrink := true;

  imageEnView1.IO.LoadFromFile(background);
  imageEnView1.AutoShrink := true;
  imageEnView1.layers[0].locked := true;
  application.processmessages;

  BackgroundHeight := imageEnView1.layers[0].height;
  BackgroundWidth := imageEnView1.layers[0].width;

  for loop := 1 to layers do
  begin

    application.processmessages;

    top := ThisIni.ReadInteger('image' + inttostr(loop), 'top', 0);
    left := ThisIni.ReadInteger('image' + inttostr(loop), 'left', 0);
    maxsize := ThisIni.ReadInteger('image' + inttostr(loop), 'maxsize', 0);
    rotate := ThisIni.Readfloat('image' + inttostr(loop), 'rotate', 0);
    shadowradius := ThisIni.ReadInteger('image' + inttostr(loop), 'shadowradius', 0);
    shadowoffsetx := ThisIni.ReadInteger('image' + inttostr(loop), 'shadowoffsetx', 0);
    shadowoffsety := ThisIni.ReadInteger('image' + inttostr(loop), 'shadowoffsety', 0);
    shadowintensity := ThisIni.ReadInteger('image' + inttostr(loop), 'shadowintensity', 0);
    Layerrotateangle[loop] := rotate;

// Add the layer
    ImageEnView1.LayersAdd;
//    ImageEnView1.IO.Params.PSD_LoadLayers := true;

    if loop = 1 then
      imageEnView1.IO.LoadFromFile(Image1)
    else if loop = 2 then
      imageEnView1.IO.LoadFromFile(Image2)
    else if loop = 3 then
      imageEnView1.IO.LoadFromFile(Image3)
    else if loop = 4 then
      imageEnView1.IO.LoadFromFile(Image4);


    // Rotate has to be dome before placing
     if rotate <> 0 then
     begin
       imageEnView1.layers[loop].Rotate := rotate;
     end;


    if imageEnView1.layers[loop].Bitmap.Width > imageEnView1.layers[loop].Bitmap.height then // it is landscape
    begin
      Ratio := imageEnView1.layers[loop].Bitmap.height / imageEnView1.layers[loop].Bitmap.Width;
      imageEnView1.layers[loop].width := MaxSize;
      imageEnView1.layers[loop].height := round(Maxsize * Ratio);
    end
    else // no it is portrait
    begin
      Ratio := imageEnView1.layers[loop].Bitmap.Width / imageEnView1.layers[loop].Bitmap.height;
      imageEnView1.layers[loop].height := MaxSize;
      imageEnView1.layers[loop].width := round(Maxsize * Ratio);
    end;
    imageEnView1.Fit;

//    imageEnView1.layers[loop].Rotate := rotate;

    imageEnView1.layers[loop].PosX := left;
    imageEnView1.layers[loop].PosY := top;

//    imageEnView1.autoshrink := true;

    if Shadow then
      ImageEnView1.Proc.AddSoftShadow(shadowradius, shadowoffsetx, shadowoffsety, true, clblack, shadowintensity);

    application.ProcessMessages;
  end; //loop


  ThisIni.free;
  PNL_wait.Visible := false;
  screen.Cursor := crdefault;
  ImageEnView1.Update();
  application.processmessages;
end;



Then once the images have been move and rotated I do this:

  LocalConfigName := Form1.DataBasePath + '\layout' + inttostr(count) + '.CLD';
  if not fileexists(LocalConfigName) then
  begin
    MessageDlg('The Required Layout File Could Not Be Found:' + #13 + #10 + LocalConfigName, mtError, [mbOK], 0);
    BTN_cancelClick(self);
    exit;
  end;


  ImageEnView1.LayersRotationAntialias := true;
  ImageEnView1.LayersRotationFilter := ierBilinear;
  ImageenView1.LayersFixRotations();
  ImageenView1.Update();


  ThisIni := TIniFile.Create(LocalConfigName);

  for loop := 1 to count do
  begin

    ThisIni.writeinteger('image' + inttostr(loop), 'top', imageEnView1.layers[loop].PosY);
    ThisIni.writeinteger('image' + inttostr(loop), 'left', imageEnView1.layers[loop].PosX);
    ThisIni.writeinteger('image' + inttostr(loop), 'maxsize', imageEnView1.layers[loop].width);

    if Layerrotated[loop] then
    begin
      ThisIni.writefloat('image' + inttostr(loop), 'rotate', Layerrotateangle[loop]);
    end; //Layerrotated[loop]

  end; // loop
  application.ProcessMessages;
  ThisIni.free;

  // 20140806 added to merge all layers before finishing
  imageEnView1.layersmergeAll;



  ImageEnview1.IO.SaveToFileJpeg('c:\instevnt\collage\Collage' + inttostr(count) + '.jpg');
.....


I am sure I am doing at least a dozen things wrong. I need it to load up with all of the settings from last time.
Also, has any progress been made on keeping the layers from extending beyond the edge of the background image?

Thanks a lot for looking



Gary Gonnella
Go to Top of Page
Page: of 2 Previous Topic Topic Next Topic  
Next Page
 New Topic  Reply to Topic
Jump To: