Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rotating page in multipage TIFF breakes page order #506

Closed
rot11 opened this issue Nov 18, 2020 · 5 comments
Closed

Rotating page in multipage TIFF breakes page order #506

rot11 opened this issue Nov 18, 2020 · 5 comments
Assignees
Labels
Milestone

Comments

@rot11
Copy link

rot11 commented Nov 18, 2020

Hi, I'm rotating the first page of a two-page TIFF image with this code:

from wand.image import Image

with Image(filename='two_page.tif') as image:
    with image.sequence[0] as page:
        page.rotate(90)
    image.save(filename='output.tif')

The page is rotated as intended, but the rotated (first) page is saved as second and the initially second page is saved as first. I can't attach the tiff files, but I'm adding two jpgs for easy reproduction. I created the multipage TIFF by calling convert page_*.jpg -compress lzw two_page.tif. Am I doing something wrong or is this a bug?

page_1
page_2

Adding identify output for tiff files to be sure thats not only a bug in my viewer:

$ identify two_page.tif 
two_page.tif[0] TIFF 200x100 200x100+0+0 8-bit Grayscale Gray 12142B 0.020u 0:00.000
two_page.tif[1] TIFF 200x100 200x100+0+0 8-bit Grayscale Gray 0.000u 0:00.000
$ identify output.tif 
output.tif[1] TIFF 200x100 200x100+0+0 8-bit Grayscale Gray 12096B 0.000u 0:00.000
output.tif[2] TIFF 100x200 100x200+0+0 8-bit Grayscale Gray 0.000u 0:00.000

Adding also my env setup:

$ identify -version
Version: ImageMagick 7.0.8-48 Q16 x86_64 2019-06-01 https://imagemagick.org
Copyright: © 1999-2019 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenCL OpenMP(4.5) 
Delegates (built-in): bzlib cairo fontconfig freetype gslib heic jbig jng jp2 jpeg lcms lqr ltdl lzma openexr pangocairo png ps raqm raw rsvg tiff webp wmf x xml zlib

$ pip freeze | grep -i wand
Wand==0.6.3
@emcconville
Copy link
Owner

Hey, Thanks for posting it. I can reproduce this, and it looks like a bug.

Here's a workaround until I can get around to fixing it.

from wand.image import Image

with Image(filename='two_page.tif') as image:
    image.iterator_set(0)
    image.rotate(90)
    image.save(filename='output.tif')

@rot11
Copy link
Author

rot11 commented Nov 18, 2020

Thanks for confirming. I was debugging the library a bit more and found that this patch can also fix my problem. Unfortunately I don't understand why, but maybe it will help.

Index: wand/sequence.py
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- wand/sequence.py	(revision d9d6205884dacd953f76777eb00771446eedfee4)
+++ wand/sequence.py	(date 1605660984225)
@@ -140,8 +140,9 @@
                 raise TypeError('image must be an instance of wand.image.'
                                 'BaseImage, not ' + repr(image))
             with self.index_context(index) as index:
-                library.MagickRemoveImage(self.image.wand)
                 library.MagickAddImage(self.image.wand, image.wand)
+            with self.index_context(index) as index:
+                library.MagickRemoveImage(self.image.wand)
 
     def __delitem__(self, index):
         if isinstance(index, slice):

@emcconville
Copy link
Owner

Under the hood, the image stack is just a linked list. I'm guessing the MagickAddImage inserts the image after the frame @ current index. Moving MagickRemoveImage call after MagickAddImage is all that's needed. I'll have to dig into the C code to verify.

diff --git a/wand/sequence.py b/wand/sequence.py
index 939da52..f3d5f27 100644
--- a/wand/sequence.py
+++ b/wand/sequence.py
@@ -140,8 +140,8 @@ class Sequence(ImageProperty, abc.MutableSequence):
                 raise TypeError('image must be an instance of wand.image.'
                                 'BaseImage, not ' + repr(image))
             with self.index_context(index) as index:
-                library.MagickRemoveImage(self.image.wand)
                 library.MagickAddImage(self.image.wand, image.wand)
+                library.MagickRemoveImage(self.image.wand)
 
     def __delitem__(self, index):
         if isinstance(index, slice):

@emcconville
Copy link
Owner

Hmm. needs more research. Both patches will not work when editing the last image on the stack. However it looks like the current code was written in 2013, and ImageMagick changed the behavior in 2016.
See https://imagemagick.org/discourse-server/viewtopic.php?f=3&t=9218

@emcconville emcconville added this to the Wand 0.6.4 milestone Nov 18, 2020
@emcconville emcconville self-assigned this Nov 18, 2020
@emcconville
Copy link
Owner

emcconville commented Nov 18, 2020

Ah! We just need to check if we're at the end of the list to determine removal order. This will be fixed with Wand-0.6.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants