Expiring Today—Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

merging images - not exactly alphablending

Posted on 2004-09-19
4
Medium Priority
?
156 Views
Last Modified: 2010-05-18

Delphi Graphics experts?

Suppose I have 4 or more images - let's make it 4 for simplicity, and assume they are of equal size. I want to "composite" these images - place them on a new image in the four quadrants (bottom left,bottom right, top left, top right) - in such a way that there is a "smooth transition" between them.

So, between the top left and top right, there should be no obvious boundary... it should "look like" elements of both images are present.

This gets more complex at the center, where there are 4 (in this simple case) adjacent images.

Has anyone done this? And got nice-looking results?

Code would be nice

0
Comment
Question by:Mutley2003
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
4 Comments
 
LVL 34

Accepted Solution

by:
Slick812 earned 2000 total points
ID: 12106759
hello Mutley2003, you do not give very much info about the size of thr different aspects of your images, I have done Edge Blending for bitmaps before, although never more than Two bitmaps at a time, here is some code that tries to do a 4 bitmap blend, however, the math required for the center 4 bitmap blend, is not something I hve time now to figure out, I think it would require a 4 way matrix intered from a trigomometry distance from the center point, but this is more than I have time to try and figure out, , , , , ,

I do a 4 quadrent 3 bitmap blend for the center square, and it is not a perfect blend

code for a button click -


procedure TForm1.sbut_Blend4Bmpssbut_Blend4BmpsClick(Sender: TObject);
type
  Pbgra = ^Tbgra;
  Tbgra = packed record
    b, g, r, a: Byte;
    end;

  ParyBGRA = ^TaryBGRA;
  TaryBGRA = Array[Word] of Tbgra;

const
BlendWidth = 38;

var
ULBmp, URBmp, LLBmp, LRBmp, OutBmp: TBitmap;
BmpW, BmpH: Integer;
x, y: Integer;
pOne, pTwo, pOut: ParyBGRA;
BlendAmt,Blend1, Blend2: Single;
begin
BmpW := (PaintBox1.Width div 2);
BmpH := (PaintBox1.Height div 2);
ULBmp := TBitmap.Create;
ULBmp.LoadFromFile('E:\Blend11.bmp');
ULBmp.PixelFormat := pf32Bit;
URBmp := TBitmap.Create;
URBmp.LoadFromFile('E:\Blend12.bmp');
URBmp.PixelFormat := pf32Bit;
LLBmp := TBitmap.Create;
LLBmp.LoadFromFile('E:\Blend12.bmp');
LLBmp.PixelFormat := pf32Bit;
LRBmp := TBitmap.Create;
LRBmp.LoadFromFile('E:\Blend11.bmp');
LRBmp.PixelFormat := pf32Bit;
OutBmp := TBitmap.Create;
OutBmp.PixelFormat := pf32Bit;
try
  OutBmp.Canvas.Brush.Color := $EFFADF;
  ULBmp.Height := BmpH + BlendWidth;
  ULBmp.Width := BmpW + BlendWidth;
  URBmp.Height := BmpH + BlendWidth;
  URBmp.Width := BmpW + 1;
  LLBmp.Height := BmpH + 1;
  LLBmp.Width := BmpW + BlendWidth;
  LRBmp.Height := BmpH + 1;
  LRBmp.Width := BmpW + 1;
  OutBmp.Height := PaintBox1.Height;
  OutBmp.Width := PaintBox1.Width;

  BitBlt(OutBmp.Canvas.Handle,0,0, BmpW, BmpH, ULBmp.Canvas.Handle, 0,0, SRCCOPY);
  BitBlt(OutBmp.Canvas.Handle,BmpW+BlendWidth,0, BmpW, BmpH,
         URBmp.Canvas.Handle, BlendWidth,0, SRCCOPY);
  BitBlt(OutBmp.Canvas.Handle,0,BmpH+BlendWidth, BmpW, BmpH,
         LLBmp.Canvas.Handle, 0,BlendWidth, SRCCOPY);
  BitBlt(OutBmp.Canvas.Handle,BmpW+BlendWidth,BmpH+BlendWidth, BmpW,
         BmpH, LRBmp.Canvas.Handle, BlendWidth,BlendWidth, SRCCOPY);

  BlendAmt := 1.0 / BlendWidth;

  Blend1 := BlendAmt;
  for y := 0 to BlendWidth-1 do
    begin
    Blend2 := 1.0 - Blend1;
    pOne := ULBmp.ScanLine[y+BmpH];
    pTwo := LLBmp.ScanLine[y];
    pOut := OutBmp.ScanLine[y+BmpH];
    for x := 0 to ULBmp.Width -(BlendWidth+1) do
      begin
      pOut[x].r := ROUND((Blend2 * pOne[x].r) + (Blend1 * pTwo[x].r));
      pOut[x].g := ROUND((Blend2 * pOne[x].g) + (Blend1 * pTwo[x].g));
      pOut[x].b := ROUND((Blend2 * pOne[x].b) + (Blend1 * pTwo[x].b));
      end;
    Blend1 := Blend1 + BlendAmt;
    end;

  Blend1 := BlendAmt;
  for y := 0 to BlendWidth-1 do
    begin
    Blend2 := 1.0 - Blend1;
    pOne := URBmp.ScanLine[y+BmpH];
    pTwo := LRBmp.ScanLine[y];
    pOut := OutBmp.ScanLine[y+BmpH];
    for x := BlendWidth to ULBmp.Width - BlendWidth do
      begin
      pOut[x+BmpW].r := ROUND((Blend2 * pOne[x].r) + (Blend1 * pTwo[x].r));
      pOut[x+BmpW].g := ROUND((Blend2 * pOne[x].g) + (Blend1 * pTwo[x].g));
      pOut[x+BmpW].b := ROUND((Blend2 * pOne[x].b) + (Blend1 * pTwo[x].b));
      end;
    Blend1 := Blend1 + BlendAmt;
    end;

  Blend1 := BlendAmt;
  for x := 0 to BlendWidth-1 do
    begin
    Blend2 := 1.0 - Blend1;

    for y := 0 to ULBmp.Height - (BlendWidth div 2) do
      begin
      pOne := ULBmp.ScanLine[y];
      pTwo := URBmp.ScanLine[y];
      pOut := OutBmp.ScanLine[y];
      pOut[x+BmpW].r := ROUND((Blend2 * pOne[x+BmpW].r) + (Blend1 * pTwo[x].r));
      pOut[x+BmpW].g := ROUND((Blend2 * pOne[x+BmpW].g) + (Blend1 * pTwo[x].g));
      pOut[x+BmpW].b := ROUND((Blend2 * pOne[x+BmpW].b) + (Blend1 * pTwo[x].b));
      end;
    Blend1 := Blend1 + BlendAmt;
    end;

  Blend1 := BlendAmt;
  for x := 0 to BlendWidth-1 do
    begin
    Blend2 := 1.0 - Blend1;

    for y := (BlendWidth div 2)+1 to ULBmp.Height -BlendWidth do
      begin
      pOne := LLBmp.ScanLine[y];
      pTwo := LRBmp.ScanLine[y];
      pOut := OutBmp.ScanLine[y+(BmpH)];
      pOut[x+BmpW].r := ROUND((Blend2 * pOne[x+BmpW].r) + (Blend1 * pTwo[x].r));
      pOut[x+BmpW].g := ROUND((Blend2 * pOne[x+BmpW].g) + (Blend1 * pTwo[x].g));
      pOut[x+BmpW].b := ROUND((Blend2 * pOne[x+BmpW].b) + (Blend1 * pTwo[x].b));
      end;
    Blend1 := Blend1 + BlendAmt;
    end;

  // / / / / / / / / / / / / / / / / / / / / / / / / / / / /

  Blend1 := BlendAmt;
  for y := BmpH to ULBmp.Height -(BlendWidth div 2) do
    begin
    Blend2 := 1.0 - Blend1;
    pTwo := LLBmp.ScanLine[y-BmpH];
    pOut := OutBmp.ScanLine[y];
    for x := BmpW to ULBmp.Width - ((BlendWidth div 2)+1) do
      begin
      pOut[x].r := ROUND((Blend2 * pOut[x].r) + (Blend1 * pTwo[x].r));
      pOut[x].g := ROUND((Blend2 * pOut[x].g) + (Blend1 * pTwo[x].g));
      pOut[x].b := ROUND((Blend2 * pOut[x].b) + (Blend1 * pTwo[x].b));
      end;
    Blend1 := Blend1 + BlendAmt;
    end;
 

  Blend1 := BlendAmt;
  for y := BmpH to ULBmp.Height -(BlendWidth div 2) do
    begin
    Blend2 := 1.0 - Blend1;
    pTwo := LRBmp.ScanLine[y-BmpH];
    pOut := OutBmp.ScanLine[y];
    for x := BmpW + (BlendWidth div 2) to ULBmp.Width - 1 do
      begin
      pOut[x].r := ROUND((Blend2 * pOut[x].r) + (Blend1 * pTwo[x].r));
      pOut[x].g := ROUND((Blend2 * pOut[x].g) + (Blend1 * pTwo[x].g));
      pOut[x].b := ROUND((Blend2 * pOut[x].b) + (Blend1 * pTwo[x].b));
      end;
    Blend1 := Blend1 + BlendAmt;
    end;

  // / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /

  Blend1 := BlendAmt * (BlendWidth div 2);
  for y := BmpH +(BlendWidth div 2) to ULBmp.Height -1 do
    begin
    Blend2 := 1.0 - Blend1;
    pTwo := ULBmp.ScanLine[y];
    pOut := OutBmp.ScanLine[y];
    for x := BmpW to ULBmp.Width - ((BlendWidth div 2)+1) do
      begin
      pOut[x].r := ROUND((Blend1 * pOut[x].r) + (Blend2 * pTwo[x].r));
      pOut[x].g := ROUND((Blend1 * pOut[x].g) + (Blend2 * pTwo[x].g));
      pOut[x].b := ROUND((Blend1 * pOut[x].b) + (Blend2 * pTwo[x].b));
      end;
    Blend1 := Blend1 + BlendAmt;
    end;

  Blend1 := BlendAmt * (BlendWidth div 2);
  for y := BmpH +(BlendWidth div 2)+1 to ULBmp.Height -1 do
    begin
    Blend2 := 1.0 - Blend1;
    pTwo := URBmp.ScanLine[y];
    pOut := OutBmp.ScanLine[y];
    for x := BmpW + ((BlendWidth div 2)) to ULBmp.Width - 1 do
      begin
      pOut[x].r := ROUND((Blend1 * pOut[x].r) + (Blend2 * pTwo[x].r));
      pOut[x].g := ROUND((Blend1 * pOut[x].g) + (Blend2 * pTwo[x].g));
      pOut[x].b := ROUND((Blend1 * pOut[x].b) + (Blend2 * pTwo[x].b));
      end;
    Blend1 := Blend1 + BlendAmt;
    end;

  PaintBox1.Canvas.Draw(0,0, OutBmp);
  finally
  FreeAndNil(ULBmp);
  FreeAndNil(URBmp);
  FreeAndNil(LLBmp);
  FreeAndNil(LRBmp);
  FreeAndNil(OutBmp);
  end;
end;

 - - - - - - - - - - - - -  - - - - - - - - - - - - - - -  - - - - - - - -  - - - - - - -  - - - -

I hope this gives you some Ideas, and if you can come up with the math to calulate the relative blend values of 4 bitmaps, let me know
0
 

Author Comment

by:Mutley2003
ID: 12119034
Hi Slick

Thanks for the code.. as you say, the center is likely to be a problem. I have also been thinking as to how this might be generalized to more than 4 images, and possibly irregular. OK, this is just woolly thinking so far, but bear with me.

Suppose we have a "circle of compositing" of radius R.  This imaginary circle is passed over all the pixels in the output image and determines how the original (source) images contribute to the final image.  Assume each source image is positioned in its own invisible layer, and so these layers can overlap.

Approximate the circle by a polygon, so we can use polygon calculations .. point in polygon, polygon intersection etc.

For a given pixel in the final image

* which images does it directly map to (point in polygon)
* if only one image, then copy that source pixel
* if two or more, average those pixels

* are there any pixels in the source images within the circle of compositing ie within a radius R of this one. If so, allow them to make a contribution to this pixel with weight inversely proportional to the Euclidean distance between them. Note that this means that pixels which are not on a horizontal or vertical line can still influence the output pixel.

Well, it needs some more thinking I guess.



btw I will be out of the office for about a week, so don't take my lack of response for lack of interest.
0
 
LVL 34

Expert Comment

by:Slick812
ID: 12119544
OK, I read your last comment, but I can not say that I understood it, I can not get an Idea from your description, of any concievible final or output Image, I guess that there would only be a circle (or a polygon close to a circle) with some sort of "MIX" or blending of several images, which may not all be contained in the circle, or something? Anyway, I can not get a visual in my head of what this might look like, except that it is a circle. . . I do not see any edge blending to this.

And I can not place any of this with the original request of edge blending 4 images? ? ?
0
 

Author Comment

by:Mutley2003
ID: 12176743
Hi Slick812

I tried your code and it gives me good results. Ignore my post of 09/21/04

Thanks for the help
0

Featured Post

New benefit for Premium Members - Upgrade now!

Ready to get started with anonymous questions today? It's easy! Learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Suggested Courses

718 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question