Skip to content

Commit

Permalink
Adjust the size of rotated/flipped images in docx
Browse files Browse the repository at this point in the history
Accounts for transformations applied when handling exif data
  • Loading branch information
silby committed Nov 15, 2024
1 parent a778b98 commit b1f0748
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 13 deletions.
11 changes: 9 additions & 2 deletions src/Text/Pandoc/ImageSize.hs
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ findSvgTag :: ByteString -> Bool
findSvgTag img = "<svg" `B.isInfixOf` img || "<SVG" `B.isInfixOf` img

imageSize :: WriterOptions -> ByteString -> Either T.Text ImageSize
imageSize opts img = checkDpi <$>
case imageType img of
imageSize opts img = do
size <- case imageType img of
Just Png -> getSize img
Just Gif -> getSize img
Just Jpeg -> getSize img
Expand All @@ -159,13 +159,20 @@ imageSize opts img = checkDpi <$>
Just Pdf -> mbToEither "could not determine PDF size" $ pdfSize img
Just Emf -> mbToEither "could not determine EMF size" $ emfSize img
Nothing -> Left "could not determine image type"
xform <- imageTransform img
Right $ checkDpi $ case xform of
ImageTransform _ R90 -> swapDirs size
ImageTransform _ R270 -> swapDirs size
_ -> size
where mbToEither msg Nothing = Left msg
mbToEither _ (Just x) = Right x
-- see #6880, some defective JPEGs may encode dpi 0, so default to 72
-- if that value is 0
checkDpi size =
size{ dpiX = if dpiX size == 0 then 72 else dpiX size
, dpiY = if dpiY size == 0 then 72 else dpiY size }
swapDirs (ImageSize px py dx dy) =
ImageSize py px dy dx


sizeInPixels :: ImageSize -> (Integer, Integer)
Expand Down
29 changes: 18 additions & 11 deletions src/Text/Pandoc/Writers/Docx/OpenXML.hs
Original file line number Diff line number Diff line change
Expand Up @@ -963,19 +963,26 @@ inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do
mknode "a:fillRect" [] ()
]
transform = either (const def) id $ imageTransform img
attrflip NoFlip = []
attrflip FlipH = [("flipH", "1")]
attrflip FlipV = [("flipV", "1")]
xfrmFlip NoFlip = []
xfrmFlip FlipH = [("flipH", "1")]
xfrmFlip FlipV = [("flipV", "1")]
-- 60,000ths of a degree
rotate R0 = []
rotate R90 = [("rot", "5400000")]
rotate R180 = [("rot", "10800000")]
rotate R270 = [("rot", "16200000")]
xfrmRot R0 = []
xfrmRot R90 = [("rot", "5400000")]
xfrmRot R180 = [("rot", "10800000")]
xfrmRot R270 = [("rot", "16200000")]

xfrm = mknode "a:xfrm" ((attrflip (tFlip transform)) <> (rotate (tRotate transform)))
xfrmExtents R0 = (tshow xemu, tshow yemu)
xfrmExtents R180 = (tshow xemu, tshow yemu)
xfrmExtents R90 = (tshow yemu, tshow xemu)
xfrmExtents R270 = (tshow yemu, tshow xemu)

(height, width) = (xfrmExtents . tRotate) transform

xfrm = mknode "a:xfrm" ((xfrmFlip (tFlip transform)) <> (xfrmRot (tRotate transform)))
[ mknode "a:off" [("x","0"),("y","0")] ()
, mknode "a:ext" [("cx",tshow xemu)
,("cy",tshow yemu)] () ]
, mknode "a:ext" [("cx",height)
,("cy",width)] () ]
prstGeom = mknode "a:prstGeom" [("prst","rect")] $
mknode "a:avLst" [] ()
ln = mknode "a:ln" [("w","9525")]
Expand All @@ -996,7 +1003,7 @@ inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do
imgElt = mknode "w:r" [] $
mknode "w:drawing" [] $
mknode "wp:inline" []
[ mknode "wp:extent" [("cx",tshow xemu),("cy",tshow yemu)] ()
[ mknode "wp:extent" [("cx",height),("cy",width)] ()
, mknode "wp:effectExtent"
[("b","0"),("l","0"),("r","0"),("t","0")] ()
, mknode "wp:docPr"
Expand Down

0 comments on commit b1f0748

Please sign in to comment.