docs: def do_rotation(self, mirror, rot):
          """Apply rotation and/or mirroring."""
          infile = self.tmpfile
          outfile = self.basename + '.rot'
          # NOTE: pnmrotate: angle must be between -90 and 90 and
          # rotations is CCW not CW per IIIF spec
          #
          # BUG in pnmrotate: +90 and -90 rotations the output image
          # size may be off. See for example a 1000x1000 image becoming
          # 1004x1000:
          #
          # simeon@RottenApple iiif>file testimages/67352ccc-d1b0-11e1-89ae-279075081939.png
          # testimages/67352ccc-d1b0-11e1-89ae-279075081939.png: PNG image data, 1000 x 1000, 8-bit/color RGB, non-interlaced
          # simeon@RottenApple iiif>cat testimages/67352ccc-d1b0-11e1-89ae-279075081939.png  | pngtopnm | pnmrotate -90 | pnmtopng > a.png; file a.png; rm a.png
          # a.png: PNG image data, 1004 x 1000, 8-bit/color RGB, non-interlaced
          # simeon@RottenApple iiif>cat testimages/67352ccc-d1b0-11e1-89ae-279075081939.png  | pngtopnm | pnmrotate 90 | pnmtopng > a.png; file a.png; rm a.png
          # a.png: PNG image data, 1004 x 1000, 8-bit/color RGB, non-interlaced
          #
          # WORKAROUND is to add a pnmscale for the 90degree case, some
          # simeon@RottenApple iiif>cat testimages/67352ccc-d1b0-11e1-89ae-279075081939.png  | pngtopnm | pnmrotate -90| pnmscale -width 1000 -height 1000 | pnmtopng > a.png; file a.png; rm a.png
          # a.png: PNG image data, 1000 x 1000, 8-bit/color RGB, non-interlaced
          #
          # FIXME - add mirroring
          #
          if (rot == 0.0):
              # print "rotation: no rotation"
              self.tmpfile = infile
          elif (rot <= 90.0 or rot >= 270.0):
              if (rot >= 270.0):
                  rot -= 360.0
              # print "rotation: by %f degrees clockwise" % (rot)
              if (self.shell_call('cat ' + infile + ' | ' + self.pnmrotate + ' -background=#FFF ' + str(-rot) + '  > ' + outfile)):
                  raise IIIFError(
                      text="Oops... got nonzero output from pnmrotate.")
              self.tmpfile = outfile
          else:
              # Between 90 and 270 = flip and then -90 to 90
              rot -= 180.0
              # print "rotation: by %f degrees clockwise" % (rot)
              if (self.shell_call('cat ' + infile + ' | ' + self.pnmflip + ' -rotate180 | ' + self.pnmrotate + ' ' + str(-rot) + '  > ' + outfile)):
                  raise IIIFError(
                      text="Oops... got nonzero output from pnmrotate.")
              self.tmpfile = outfile
          # Fixup size for 90s
          if (abs(rot % 180.0 - 90.0) < 0.001):
              outfile2 = self.basename + '.rot2'
              if (self.shell_call('cat ' + self.tmpfile + ' | ' + self.pnmscale + ' -width ' + str(self.height) + ' -height ' + str(self.width) + ' > ' + outfile2)):
                  raise IIIFError(
                      text="Oops... failed to fixup size after pnmrotate.")
              self.tmpfile = outfile2