You can turn the white material transparent:
ImageCompose[img2, ColorReplace[img1, White -> Transparent]]

To change the size, you can ImageResize. Here I have made the resize parameter variable with the slider:
Manipulate[ImageCompose[img2,
ImageResize[ColorReplace[img1, White -> Transparent], s]], {s, 50, 300, 1}]

There are also several options for the ImageCompose function and you might try them: you can put the object "on top of" or "xor with", etc.
Answer from bill s on Stack ExchangeYou can turn the white material transparent:
ImageCompose[img2, ColorReplace[img1, White -> Transparent]]

To change the size, you can ImageResize. Here I have made the resize parameter variable with the slider:
Manipulate[ImageCompose[img2,
ImageResize[ColorReplace[img1, White -> Transparent], s]], {s, 50, 300, 1}]

There are also several options for the ImageCompose function and you might try them: you can put the object "on top of" or "xor with", etc.
You can set the alpha channel relative to the pixel brightness - white pixels get transparent, darker pixels get more and more opaque:
addAlpha[img_] :=
SetAlphaChannel[img,
ColorNegate[ImageAdjust[ColorConvert[img, "Grayscale"]]]]
Then you can use ImageCompose to combine them:
{a, b} = Import /@ {"https://i.sstatic.net/yPsWy.jpg",
"https://i.sstatic.net/dSvA2.jpg"};
ImageCompose[b, addAlpha[a], {0, 0}, {0, 0}]

Or Inset to place the semitransparent images in another graphic:
ParametricPlot[{Sin[5 x], Cos[7 x]}, {x, 0, 2 \[Pi]},
Epilog -> {
Inset[addAlpha[a], {0, .5}, Center, 2],
Inset[addAlpha[b], {.5, 0}, Center, 3]
}]

You can use Inset to place the image inside a vector graphics. Inset has various parameters to set the size and position of the image places.
To test it you could use a scaled version of an image and overlay it with a grid. You see the lines match exactly:
img = ImageResize[ExampleData[{"TestImage", "Lena"}], {100, 100}];
Graphics[{Inset[img, {0, 0}, {0, 0}, {100, 100}], Line[#],
Line[Transpose[#]]}, PlotRange -> {{-1, 101}, {-1, 101}}] &@
Table[{i, j}, {i, 0, 100, 5}, {j, 0, 100, 5}]

Earth
Using this in your application, you would only have to copy all the code snips:
cart[{lambda_, phi_}] :=
With[{theta = fc[phi]}, {2/Pi*lambda Cos[theta], Sin[theta]}]
fc[phi_] :=
Block[{theta},
If[Abs[phi] == Pi/2, phi,
theta /.
FindRoot[2 theta + Sin[2 theta] == Pi Sin[phi], {theta, phi}]]];
grid = With[{delta = Pi/18/2},
Table[{lambda, phi}, {phi, -Pi/2, Pi/2, delta}, {lambda, -Pi, Pi,
delta}]];
gr1 = Graphics[{AbsoluteThickness[0.05], Line /@ grid,
Line /@ Transpose[grid]}, AspectRatio -> 1/2];
gr0 = Flatten[{gr1[[1, 2]][[Range[9]*4 - 1]],
gr1[[1, 3]][[Range[18]*4 - 3]]}] //
Graphics[{AbsoluteThickness[0.2], #}] &;
gr2 = Table[{Hue[t/Pi], Point[{t, t/2}]}, {t, -Pi, Pi, 1/100}] //
Flatten // Graphics;
gr = Show[{gr1, gr0, gr2}, Axes -> True];
earthgrid =
gr /. Line[pts_] :> {Orange, Line[cart /@ pts]} /.
Point[pts_] :> Point[cart[pts]]
Creating an earth-map image
invmollweide[{x_, y_}] :=
With[{theta = ArcSin[y]}, {Pi x/(2 Cos[theta]),
ArcSin[(2 theta + Sin[2 theta])/Pi]}];
img =
With[{i =
Import["https://i.sstatic.net/GaQGa.jpg"]},
ImageTransformation[i, invmollweide, {512, 256},
DataRange -> {{-Pi, Pi}, {-Pi/2, Pi/2}},
PlotRange -> {{-2, 2}, {-1, 1}}, Padding -> White]
];
And then putting all together
Graphics[{Inset[img, {-2, -1}, {0, 0}, {4, 2}], First[earthgrid]},
PlotRange -> {{-2, 2}, {-1, 1}}]

Perhaps the StreamPlot is being produced with unwanted margins that can be removed using PlotRangePadding -> 0? This might be one possible source of the apparent misalignment. Compare the left and right halves of this image: on the left, the original; on the right, with PlotRangePadding -> 0.

The $over$ operator correctly implemented
According to the Wikipedia, when composing $A$ $over$ $B$, the output alpha channel value $\alpha_O$ and the output color channel value $C_O$ are calculated as follows:
$\begin{cases}\alpha_O = 1 - (1 - \alpha_A) (1 - \alpha_B) \\C_O = \frac{\alpha_A C_A + (1 - \alpha_A)\alpha_B C_B}{\alpha_O}, \text{if $\alpha_O \neq 0$} \\C_O = 0, \text{if $\alpha_O = 0$} \end{cases}$
where $\alpha_A$ and $\alpha_B$ are alpha channel values of $A$ and $B$, and $C_A$ and $C_B$ – color channel values of $A$ and $B$ correspondingly.
This can be directly implemented in Mathematica 11.1 or above as follows:
imageCompose[b_Image, a_Image] :=
Module[{alphaA = AlphaChannel@a, alphaB = AlphaChannel@b, alphaO,
cA = RemoveAlphaChannel@a, cB = RemoveAlphaChannel@b},
alphaO = 1 - (1 - alphaA) (1 - alphaB);
SetAlphaChannel[(alphaA*cA + (1 - alphaA) alphaB*cB)/alphaO, alphaO]]
Let us check the associative property:
{{i0, i1, i2}} = ImagePartition[
Import["https://i.sstatic.net/r13gh.png"], {Scaled[1/3], Scaled[1]}]
{i0~imageCompose~(i1~imageCompose~i2), (i0~imageCompose~i1)~imageCompose~i2}
Equal @@ %
ColorSeparate /@ %%
True
It holds! So what is the problem with ImageCompose of version 10 and later?
Current implementation of ImageCompose: the diagnosis
When writing the above implementation for the first time I unintentionally made a simple mistake: I forgot to divide the output value for the color channel by $\alpha_O$. Here is what happened:
imageComposeWrong[b_Image, a_Image] :=
Module[{alphaA = AlphaChannel@a, alphaB = AlphaChannel@b, alphaO,
cA = RemoveAlphaChannel@a, cB = RemoveAlphaChannel@b},
alphaO = 1 - (1 - alphaA) (1 - alphaB);
SetAlphaChannel[alphaA*cA + (1 - alphaA) alphaB*cB, alphaO]]
{i0~imageComposeWrong~(i1~imageComposeWrong~i2),
(i0~imageComposeWrong~i1)~imageComposeWrong~i2}
Equal @@ %
ColorSeparate /@ %%
False
The output looks exactly the same as for the current ImageCompose:
{i0~ImageCompose~(i1~ImageCompose~i2), (i0~ImageCompose~i1)~ImageCompose~i2}
Equal @@ %
ColorSeparate /@ %%
False
Numerical comparison reveals tiny differences due to rounding off errors. But the final diagnosis is clear: the developer just forgot to divide the color channel by the alpha channel!
It is a great shame that during more than three years after the release of version 10.0.0 nobody noticed this in the company! Do they themselves use this functionality – or not?!
Please, do not be lazy to report this to the technical support, so that this shameful bug will be fixed as soon as possible! A high priority is given to bugs, which many users write about...
The remedy
From the above considerations the remedy is obvious: we must just divide the color of the ImageCompose output by the alpha channel:
icFix[img_Image] := img/AlphaChannel[img];
{i0~icFix@*ImageCompose~(i1~icFix@*ImageCompose~i2), (i0~icFix@*ImageCompose~i1)~icFix@*ImageCompose~i2}
Subtract @@ % // MinMax
ColorSeparate /@ %%
{-3.10689*10^-6, 3.08454*10^-6}
As one can see, there are still tiny differences due to rounding-off errors, but the associative property in fact is restored and the output is correct!
Original answer
Citing a comment by Rahul:
Well, that's certainly undesirable! Alpha compositing is supposed to be associative (
i0~ImageCompose~(i1~ImageCompose~i2)should equal(i0~ImageCompose~i1)~ImageCompose~i2) and this doesn't do that. One could implement correct alpha compositing manually usingImageApply, but let's see if someone has a better way.
Indeed, in versions 8.0.4 and 9.0.1 ImageCompose is associative:
$Version
{{i0, i1, i2}} = ImagePartition[
Import["https://i.sstatic.net/r13gh.png"], {Scaled[1/3], Scaled[1]}]
{i0~ImageCompose~(i1~ImageCompose~i2), (i0~ImageCompose~i1)~ImageCompose~i2}
Equal @@ %
ColorSeparate /@ %%
"9.0 for Microsoft Windows (64-bit) (January 25, 2013)"
True
... while starting from version 10.0 it is not:
$Version
{{i0, i1, i2}} = ImagePartition[
Import["https://i.sstatic.net/r13gh.png"], {Scaled[1/3], Scaled[1]}]
{i0~ImageCompose~(i1~ImageCompose~i2), (i0~ImageCompose~i1)~ImageCompose~i2}
Equal @@ %
ColorSeparate /@ %%
"10.0 for Microsoft Windows (64-bit) (September 9, 2014)"
False
It is also worth to note that despite that Overlay[{i0, i1}] and Show[i0, i1] look the same as the old ImageCompose[i0, i1], they are not the same. But they do (approximately) equal to each other and do approximately hold the associative property:
$Version
overlayCompose[i0_, i1_] := Rasterize[Overlay[{i0, i1}], "Image", Background -> None];
showCompose[i0_, i1_] := Rasterize[Show[i0, i1], "Image", Background -> None];
{overlayCompose[i0, i1], showCompose[i0, i1], i0~ImageCompose~i1}
ColorSeparate /@ %
{i0~overlayCompose~(i1~overlayCompose~i2), (i0~overlayCompose~i1)~ overlayCompose~i2}
ColorSeparate /@ %
{i0~showCompose~(i1~showCompose~i2), (i0~showCompose~i1)~showCompose~ i2}
ColorSeparate /@ %
"9.0 for Microsoft Windows (64-bit) (January 25, 2013)"
As one can see from the above, Overlay introduces artifact at the top, while Show does not.
You can get the old ImageCompose behavior by using Overlay instead:
Overlay[{i1, i2}]
Edit:
As pointed out by the comment by ybeltukov the Head of an Overlay is "Overlay" and therefore doesn't match the Head of ImageCompose, which is "Image". I didn't realize this, because exporting to a .png file did handle the transformation.
One can use e.g.
ImportString@ExportString[Overlay[{i1, i2}], "PNG"]
to get an object with Head "Image", and that therefore can be used the same way as an object created with ImageCompose inside the notebook.
Try this:
(* clip white borders *)
img = ImageCrop[Import["https://i.sstatic.net/La8Zs.jpg"]];
Plot[-14/81 x (x - 18), {x, -2, 19},
PlotRange -> {-2, 16}, PlotStyle -> Directive[Red, Thick, Dashed],
Prolog -> {Texture[img],
Polygon[{Scaled[{0, 0}], Scaled[{1, 0}], Scaled[{1, 1}], Scaled[{0, 1}]},
VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]},
Ticks -> None]

Notes:
If you want to fit in an image as background, you will often want to trim margins;
ImageCrop[]is a good function for the purpose.Luckily, your background image has its own coordinate system; you can then adjust
PlotRangeappropriately.Prologis most useful for putting primitives in the background.Scaled[]ensures that the background textured polygon is scaled appropriately with respect to the plot range.
EDIT: (see below for old version)
New version with alpha channels, the option to lock the graph at the ball, adjustable player position and a button to remove player and basket:
setalpha[im_] :=
Module[{mask =
ChanVeseBinarize[im, TargetColor -> {1., 1., 1.},
"LengthPenalty" -> 10]},
mask = Blur[Erosion[ColorNegate[mask], 2], 5];
Rasterize[SetAlphaChannel[im, mask], Background -> None]]
basket = setalpha[
Import["http://www.hdwallpaperspk.com/wp-content/uploads/2013/02/ basketball_clipart.jpg"]];
guy = setalpha[
Import["http://www.tu-chemnitz.de/ifm/produkte-medien/basketball_200.png"]];
Manipulate[
Plot[If[locked, (-c - b pos[[1]] + pos[[2]])/pos[[1]]^2, a] x^2 +
b x + c, {x, 0, 16}, PlotRange -> {{0, 17}, {0, 14}},
Frame -> True,
ImageSize -> 500,
BaseStyle -> {20, FontFamily -> "Helvetica"},
FrameLabel -> {"Distance from Back of hoop (ft)", "Heigth (ft)"},
GridLines -> {Range@16, Range@14},
Prolog -> {Inset[If[show, basket, ""], {0.5, 8}, Top, 1],
Inset[If[show, guy, ""], pos, Top, 2.5]}],
Item@Row[{"a ",
Dynamic@Slider[Dynamic@a, {1, 10}, Enabled -> ! locked]}],
Item@Row[{"b ", Dynamic@Slider[Dynamic@b, {1, 10}]}],
Item@Row[{"c ", Dynamic@Slider[Dynamic@c, {1, 10}]}],
{{pos, {16, 6}}, Locator},
{{locked, True, "Lock graph at ball"}, {True, False}},
{{show, True, "Show player and basket"}, {True, False}},
ControlPlacement -> Left]

Old version:
Alternatively, you can also create the whole thing completely in Mathematica. I also added Manipulate for fun:
basket = Import[
"http://www.hdwallpaperspk.com/wp-content/uploads/2013/02/basketball_clipart.jpg"];
guy = Import["http://www.tu-chemnitz.de/ifm/produkte-medien/basketball_200.png"];
Manipulate[
Plot[-(c x - b)^2 + a, {x, 0, 16},
PlotRange -> {{0, 17}, {0, 14}},
Frame -> True,
ImageSize -> 500,
BaseStyle -> {20, FontFamily -> "Helvetica"},
FrameLabel -> {"Distance from Back of hoop (ft)", "Heigth (ft)"},
GridLines -> {Range@16, Range@14},
Prolog -> {Inset[basket, {0.5, 8}, Top, 1],
Inset[guy, {16, 6}, Top, 2.5]}],
{a, 8, 20}, {b, 1, 10}, {c, 0.1, 1}]
ImageCompose[zePlot, {Graphics[{Blue, Disk[{0, 0}, 5]},
PlotRange -> {{-sqrSize, sqrSize}, {-sqrSize, sqrSize}}], 0.2}]

ImageCompose[zePlot, {Graphics[{White, Disk[{0, 0}, 5]},
PlotRange -> {{-sqrSize, sqrSize}, {-sqrSize, sqrSize}},
Background -> Blue], 0.2}]

You can use Show to combine at a Graphics level, as opposed to ImageCompose that in a sense sees the graphics as images and just aligns them on top of each other not knowing about the different scales etc. This is why adding PlotRange to the Graphics fixes it in the ImageCompose case.
Show[zePlot, Graphics[{Opacity[0.2], Blue, Disk[{0, 0}, 5]}]]
Couldn't you simply Fold ImageCompose onto a list of pairs of layers and blend modes?
Version 7 doesn't have those advanced blend modes as far as I recall, but a simple example using Alpha:
img = ExampleData /@ ExampleData["TestImage"][[25 ;; 27]];
Fold[
ImageCompose,
img[[1]],
{
{img[[2]], 0.5}, {img[[3]], 0.2}
}
]

Some of the other standard blend modes could also be realized with the help of these:
ImageAddImageSubtractImageDifferenceImageMultiply























