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
 Building a Collage

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
oldbitman Posted - Aug 03 2014 : 11:01:48
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
20   L A T E S T    R E P L I E S    (Newest First)
oldbitman Posted - May 15 2015 : 13:20:22
Wow Bill, I didn't realize who you were. If you can't see what I am doing wrong I must have really screwed things up. When all else fails go to the book. I am rereading/searching your book. Thanks for the great document.

Gary Gonnella
oldbitman Posted - May 15 2015 : 11:54:06
Thanks Bill.

On another subject I would like to ask if anyone would be interested in taking over development on several related projects?

20 years ago I co-founded a company to build systems to do digital photos in theme parks and events. This includes ride photos on roller coaster and specialties such as "Old Time Photo". A few years ago some of my employees took over the company but I have always been the only one doing the programming in Delphi. These program have grown over the last 20 years and I am not the best programmer in the world. Now it is 20 years later and I am 65 and just not very good at keeping track of things, and find programming to be much harder than it was.

Any interested in discussing this.

thanks.

Gary Gonnella
w2m Posted - May 15 2015 : 10:57:31
That is because I responded but afterword I saw you were already doing what I was going to suggest so I deleted my post.

Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
oldbitman Posted - May 15 2015 : 10:55:03
I got an email yesterday that w2m responded to my post but it is not showing up here on the forums?

Gary Gonnella
oldbitman Posted - May 14 2015 : 16:36:31
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
oldbitman Posted - Aug 22 2014 : 09:22:51
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
xequte Posted - Aug 22 2014 : 02:35:10
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
oldbitman Posted - Aug 21 2014 : 14:32:12
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
xequte Posted - Aug 21 2014 : 14:19:09
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
oldbitman Posted - Aug 21 2014 : 13:17:18
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
xequte Posted - Aug 18 2014 : 13:40:54
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
oldbitman Posted - Aug 18 2014 : 12:53:16
The layers are coming out extremely pixelated. However I think I found the problem by setting:
ImageEnView1.LayersRotationFilter := ierBicubic;
ImageEnView1.LayersRotationAntialias := true;


Gary Gonnella
w2m Posted - Aug 18 2014 : 12:48:08
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
oldbitman Posted - Aug 18 2014 : 11:10:49
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
xequte Posted - Aug 11 2014 : 12:54:46
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
oldbitman Posted - Aug 08 2014 : 12:52:07
Thank you very much

Gary Gonnella
w2m Posted - Aug 08 2014 : 12:16:54
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
oldbitman Posted - Aug 08 2014 : 12:11:53
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
oldbitman Posted - Aug 08 2014 : 08:28:39
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
xequte Posted - Aug 07 2014 : 14:58:30
@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