Here's a way that might work, though I'm not sure if it would break in some cases:
flip[height_?NumericQ][g : Graphics[p_, options___]] :=
Graphics[GeometricTransformation[
p, {{{1, 0}, {0, -1}}, {0, height}}], options]
Then flip[imageheight][Graphics[...]]
gets you what you want! But we can do better by packaging this into a custom version of Show
:
ImageShow[img_Image, graphics___Graphics] :=
Show[img, Sequence @@ (flip[ImageDimensions[img][[2]]] /@ {graphics})]
Then simply using it in place of Show
gets you what you want, e.g. ImageShow[img, Graphics[...]]
. (By the way, I checked—I was worried about being off-by-one, but I think this puts the origin at the right place!)
EDIT: It was mentioned that Text
works...well, undesirably, appearing upside down. So, I created different versions of the above functions that correct text by default, but allow an option to be passed to turn this off.
ClearAll[flip, ImageShow]
correctText[Text[text_, options___Rule]] :=
GeometricTransformation[Text[text, options], {{1, 0}, {0, -1}}]
correctText[Text[text_, {x_, y_}, args___]] :=
GeometricTransformation[Text[text, {x, -y}, args], {{1, 0}, {0, -1}}]
correctText[Text[text_, Scaled[{x_, y_}], args___]] :=
GeometricTransformation[Text[text, Scaled[{x, -y}], args], {{1, 0}, {0, -1}}]
correctText[Text[text_, Scaled[{dx_, dy_}, {x_, y_}], args___]] :=
GeometricTransformation[
Text[text, Scaled[{dx, -dy}, {x, -y}], args], {{1, 0}, {0, -1}}]
SetAttributes[correctText, Listable]
correctText[x_] := x
flip[height_?NumericQ, OptionsPattern[{CorrectText -> True}]][g : Graphics[p_, options___]] :=
Graphics[GeometricTransformation[
If[OptionValue[CorrectText], correctText[p],
p], {{{1, 0}, {0, -1}}, {0, height}}], options]
ImageShow[img_Image, graphics___Graphics, opts : OptionsPattern[{CorrectText -> True}]] :=
Show[img,
Sequence @@ (flip[ImageDimensions[img][[2]], opts] /@ {graphics})]
(* Test: *)
img = ExampleData[{"TestImage", "House"}];
ImageShow[img,
Graphics[{EdgeForm[{Thick, Blue}], FaceForm[],
Text["ABCDEF", {50, 20}], Rectangle[{10, 20}, {30, 60}]}]]
ImageShow[img,
Graphics[{EdgeForm[{Thick, Blue}], FaceForm[],
Text["ABCDEF", {50, 20}], Rectangle[{10, 20}, {30, 60}]}], CorrectText -> False]
height = Last@ImageDimensions[img]; Show[img, Graphics[{EdgeForm[{Thick, Blue}], FaceForm[], Rectangle[{10, 1 + height - 20}, {30, 1 + height - 60}]}]]
give what you need? $\endgroup$