Link to home
Start Free TrialLog in
Avatar of JustScreenShot
JustScreenShot

asked on

Concatenating multiple Images

Dear experts

I want to concatenate two images that have are overlapped with each other. Sample of two such images are attched. Images 1.png, 2.png, 3.png, 4.png and 5.png are overlapped and I want to create a concatenated version of these images. Overlapped sections of the images should not copied. The overlapped sections didn't have fixed height.

I need a very very fast (As fast as possible) and accurate function for concatenation.

1.png
2.png
3.png
4.png
5.png
Avatar of rfwoolf
rfwoolf
Flag of South Africa image

Attached is a procedure that you can play around with to get the results you need... What the procedure below does is it places a bitmap in the centre of another bitmap on a Timage- you will use the same idea.

Also, In this attached demo you use 2 Opendialogs to point to the images you want to use - you can instead just replace these parts with the path to the images you need - or if you somehow have them in memory.

Basically what you'll need to do is have a TImage and 2 TBitmaps.
You will need to size the Timage big enough to fit the two concatenated images - in other words Timage will be your canvas for laying out of the images.
Then you simply draw the bitmaps onto the canvas:
image1.Picture.Bitmap.Canvas.draw(X,Y,bitmap);//place the bitmap onto the image //where X and Y is the top and left of the image
image1.Picture.Bitmap.Canvas.draw(X,Y,bitmap2);//place the bitmap2 onto the image
For this you will need a TImage component on your form,
as well as a button
as well as an OpenDialogue.
It is recommended (but not essential) that you set your TImage component's Autosize to True;
 
Here is the sourcecode for the button...
 
procedure TForm1.Button1Click(Sender: TObject);
var
  bitmap1   : TBitMap;      //declare bitmap container 1
  bitmap2   : TBitMap;      //declare  bitmap container 2
  daLeft, daTop : Integer;  //declare two integer units for positioning of the second bitmap
begin
  if opendialog1.Execute then //opens a dialogue asking for the first image
  begin
    bitmap1 := TBitmap.Create;  //create the bitmap container 1
    try
      bitmap1.LoadFromFile(opendialog1.FileName);  //load the file the user chose into the bitmap 1
      image1.Picture.Bitmap.Assign(bitmap1);  //load bitmap1 into your form's image component
      //MOVING ON TO NEXT BITMAP
      if opendialog1.Execute then //opens a dialogue asking for the first image
      begin
        bitmap2 := TBitMap.Create; //create the bitmap container 2
        bitmap2.LoadFromFile(opendialog1.FileName);  //load the file the user chose into the bitmap 2
         try
          daLeft := round((bitmap1.width - bitmap2.width) / 2); //calculate left position of 2nd bitmap
          daTop := round((bitmap1.Height - bitmap2.Height) / 2); //calculate top position of 2nd bitmap
          image1.Picture.Bitmap.Canvas.draw(daLeft,daTop,bitmap2);//place the bitmap 2 onto the bitmap 1 on the image
        finally
          bitmap2.Free;  //free the 2nd bitmap container in memory
        end;
      end;
    finally
      bitmap1.Free;   //free the 2nd bitmap container in memory
    end;
  end;
end;

Open in new window

I then forgot a very important part - the output!
You will then say
  Image1.picture.SaveToFile('MyImage.BMP'); -- if you want to save it to a file
or else you can copy it to the clipboard or do what you want.

If you have a problem with the format (BMP) see if you can use PNG instead - I think you can. Alternatively in the JVCL suite there is a TImage type component that works with a variety of formats including GIF, jpeg, BMP etc - so instead of using a TImage you will use TJvImage or something
Avatar of JustScreenShot
JustScreenShot

ASKER

Dear rfwoolf

Thank for the answer. May be I was not clear enough. I actually need an algorithm for finding overlapped sections of the image and delete the overlapped parts and concatenate 3 images or more together.
Yes I'm afraid you didn't explain yourself very well - I still don't understand because the 5 example images don't make sense - there doesn't seem to be a discernable pattern. The images are 'cut' in unexpected places - you need to explain exactly how you'd want it to do it. If you can't explain it to a human, you might have some trouble explaining it to a PC :)
 I think I can see what you are looking for... if I am right then my explanation should help.  The first 4 images, in the area that is text, appear to be the same.  The fifth image has a little more text.  On the right side however the images are different.  So, from what I can see, you want to reconstruct the image on the right by stripping out all of what is in the image on each one, and correctly overlap them to produce a larger, complete, image.

simplified...

image 1
----
        A
        B
----

image 2
----
        B
        C
        D
----

produces...
----
        A
        B
        C
        D
----


  Let me know if I am correct on this.
or, perhaps you want the whole screen?
Dear developmentguru, neither of 5 images ARE NOT the same. Each of them has more text than the previous. Actually I want to create a screenshot from the page wholly.

Assume this page that you are reading my comment. take a capture from the the internal browser window. Now press down key and take a new capture. repeat these steps until you reached to the end of the page. Now I want to concatenate these pictures with each other. At the first step should overlapped sections of images recognized and then the images could stick to each other without overlapped section to make the finall image. this is a feature named "Automatic Scrolling" could be found at screen capture program like SnagIt.
I think one important technical consideration is whether it's possible to calculate which portions of the images can be 'cut off' - for example if you know that the screen scrolls 50 pixels down then you know to cut off 50 pixels. But if that's not possible becomes much harder and you have to start with image algorithms to get the program to 'visually' compare the images for similar pixels .

So JustScreenShot - *HOW* you are getting these images is important - because you might be able to collect how many pixels the screen has scrolled.
Avatar of Geert G
http://www.scootersoftware.com

the program is called BeyondCompare and it has a picture compare tool.
You can compare 2 pictures in several modes.

with this you can find the matching blocks manually

next step would be to add the non matching blocks to a total image

repeat the process for each subsequent image

problem is there is no automatic matching block algorithm

VNC also has a way of only sending the blocks of the screenshot that have changed...

Am i getting anywhere close ?
JustScreenShot,

I would agree with the others that the *how* (regarding image collection) is important, as knowing this may allow for alternative suggestions. For example, if you are only dealing with browser window capturing, I do have code that will allow you to capture the "whole" browser window image, regardless of scroll bars.

Russell

 The problem is more complex than you know.  If you scan image 1 and find an exact matching line of pixels in image 2, is that a match?  I personally have seen the same line of text inserted twice for emphasis.  This means that if you scan the same 12 pixels of the line in image one you can find it in more then one location in image 2.  If you do a line by line search and show all matches for each line then you would be able to find the longest consecutive match and use that as your starting block.  This is oversimplified as it only matches vertically.  I would not consider such an algorythm to be complete without taking into account the possibility of horizontal changes.

  You may be able to take an easier approach to this though.  The approach would likely be limited by Windows.  If you were to resize the window to the needed size for a full capture, then capture it.  I am really just thinking out loud here, so bear with me.  In Delphi you can request a window paint itself to a bitmap.  I would expect that this is a function of Delphi more than of windows. You can use Windows messages to figure out the needed extents by finding and sendig messages to the windows scroll bars.  This will get you the needed scroll values that will let you determine the size.  Once you have the size you could create a Delphi window (invisible or off screen) containing a web browser component) of the correct size and go to the web address (also determined using windows messages if needed).  Of course if you are using a Delphi window you could just resize until the scroll bars are off... Once this is done, just request that the window paint to a bitmap and you are done.  Save it, copy to the clipboard, whatever.  One downside to this approach is that many sites have advertising that changes with each visit.  This would likely be different.

  I hope that this helps to clarify the original approach and, perhaps, helps you think outside the box for other possibilities.
Thank for the comments

rfwoolf:
I'm sure this is something possible because programs like SnagIt and CaptureWizPro accomplish that, successfully.

I got images by captureing current window content, pressing down arrow key, capturing window content, pressing down arrow key, captureing window content, .....

Geert_Gruwez:
Thank for the pointing me forward to VNC. I will take a look over it.


rllibby:

I want to use a generic way for all or most of windows and not only Browsers. As I said it's something that SnagIt accomplished it very quick and well.

developmentguru:
Yes. I agree with you that it's almost seems impossible to design an algorithm that could be found overlapped sections of two images. I wrote a very simple function to do this comparision But the result is not good and sometimes the algorithm found inaccurate positions.

Your solution to repaint the content window to a TBitmap is theorically seems to work but practically there are lot's of problem with various windows with this method. I have a very good code samle that accomplish this. I will send the link, in the next hours.

I'm very courious to know how a program likes SnagIt accomplished this task very quickly and accurately.
I'm not sure but may be program like SnagIt is not comparing two images. Maybe it use a completely different approach and it is able to get the current position of the scrolled window. I found an interesting similar question without any answer, here:
https://www.experts-exchange.com/questions/23496918/Problem-with-GetScrollInfo.html?cid=239
Here is a code that I wrote for finding overlapped sections of two images. As I already said it's inaccurate.
procedure FindOverlap(B1, B2: TBitmap; var FoundR1,
  FoundR2: Integer; MatchesRowsMinimum: Integer);
var
  R1, R2, X, RX: Integer;
  MatchesRow: Integer;
  C1, C2: PRGBTripleArr;
begin
  FoundR1 := 0;
  FoundR2 := 0;
 
  for R1 := B1.Height - 1 downto 0 do begin
    C1 := B1.ScanLine[R1];
    for R2 := 0 to B1.Height - 1 do begin
      C2 := B2.ScanLine[R2];
      RX := R2;
      if IsRowEqual(C1, C2, B1.Width) then begin
        MatchesRow := 0;
        for X := R1 to B1.Height - 1 do begin
          C1 := B1.ScanLine[X];
          C2 := B2.ScanLine[RX];
          if IsRowEqual(C1, C2, B1.Width) then
            Inc(MatchesRow)
          else
          begin
            MatchesRow := 0;
            Break;
          end;
 
          if (MatchesRow > MatchesRowsMinimum) then begin
            FoundR1 := R1;
            FoundR2 := R2 + 20;
          end; // if
 
          if RX < B1.Height - 1 then Inc(RX);
          if (FoundR1 <> 0) or (FoundR2 <> 0) then Break;
        end; // for X
      end; // if IsRowEqual
 
      if (FoundR1 <> 0) or (FoundR2 <> 0) then Break;
      Application.ProcessMessages;
    end; // for R2
 
    if (FoundR1 <> 0) or (FoundR2 <> 0) then Break;
    Application.ProcessMessages;
  end; // for R1
end;

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Computer101
Computer101
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial