Python PIL.Image.ROTATE_180 Examples

The following are 28 code examples of PIL.Image.ROTATE_180(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module PIL.Image , or try the search function .
Example #1
Source File: model.py    From chinese_ocr with MIT License 6 votes vote down vote up
def eval_angle(im,detectAngle=False):
    """
    估计图片偏移角度
    @@param:im
    @@param:detectAngle 是否检测文字朝向
    """
    angle = 0
    img = np.array(im)
    if detectAngle:
        angle = angle_detect(img=np.copy(img))##文字朝向检测
        if angle==90:
            im = Image.fromarray(im).transpose(Image.ROTATE_90)
        elif angle==180:
            im = Image.fromarray(im).transpose(Image.ROTATE_180)
        elif angle==270:
            im = Image.fromarray(im).transpose(Image.ROTATE_270)
        img = np.array(im)
        
    return  angle,img 
Example #2
Source File: reconstruct.py    From waifu2x-chainer with MIT License 6 votes vote down vote up
def get_tta_patterns(src, n):
    src_lr = src.transpose(Image.FLIP_LEFT_RIGHT)
    patterns = [
        [src, None],
        [src.transpose(Image.ROTATE_90), inv(-90)],
        [src.transpose(Image.ROTATE_180), inv(-180)],
        [src.transpose(Image.ROTATE_270), inv(-270)],
        [src_lr, inv(0, True)],
        [src_lr.transpose(Image.ROTATE_90), inv(-90, True)],
        [src_lr.transpose(Image.ROTATE_180), inv(-180, True)],
        [src_lr.transpose(Image.ROTATE_270), inv(-270, True)],
    ]
    if n == 2:
        return [patterns[0], patterns[4]]
    elif n == 4:
        return [patterns[0], patterns[2], patterns[4], patterns[6]]
    elif n == 8:
        return patterns
    return [patterns[0]] 
Example #3
Source File: upsidedownternet.py    From MITMf with GNU General Public License v3.0 6 votes vote down vote up
def response(self, response, request, data):
        try:
            isImage = getattr(request, 'isImage')
        except AttributeError:
            isImage = False
        
        if isImage:
            try:
                #For some reason more images get parsed using the parser
                #rather than a file...PIL still needs some work I guess
                p = ImageFile.Parser()
                p.feed(data)
                im = p.close()
                im = im.transpose(Image.ROTATE_180)
                output = StringIO()
                im.save(output, format=self.imageType)
                data = output.getvalue()
                output.close()
                self.clientlog.info("Flipped image", extra=request.clientInfo)
            except Exception as e:
                self.clientlog.info("Error: {}".format(e), extra=request.clientInfo)
        
        return {'response': response, 'request': request, 'data': data} 
Example #4
Source File: test_color_lut.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
def test_channels_order(self):
        g = Image.linear_gradient('L')
        im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
                                 g.transpose(Image.ROTATE_180)])

        # Reverse channels by splitting and using table
        self.assert_image_equal(
            Image.merge('RGB', im.split()[::-1]),
            im._new(im.im.color_lut_3d('RGB', Image.LINEAR,
                    3, 2, 2, 2, [
                        0, 0, 0,  0, 0, 1,
                        0, 1, 0,  0, 1, 1,

                        1, 0, 0,  1, 0, 1,
                        1, 1, 0,  1, 1, 1,
                    ]))) 
Example #5
Source File: __init__.py    From photobooth with GNU Affero General Public License v3.0 6 votes vote down vote up
def __init__(self, config, comm, CameraModule):

        super().__init__()

        self._comm = comm
        self._cfg = config
        self._cam = CameraModule

        self._cap = None
        self._pic_dims = None

        self._is_preview = self._cfg.getBool('Photobooth', 'show_preview')
        self._is_keep_pictures = self._cfg.getBool('Storage', 'keep_pictures')

        rot_vals = {0: None, 90: Image.ROTATE_90, 180: Image.ROTATE_180,
                    270: Image.ROTATE_270}
        self._rotation = rot_vals[self._cfg.getInt('Camera', 'rotation')] 
Example #6
Source File: upsidedownternet.py    From piSociEty with GNU General Public License v3.0 6 votes vote down vote up
def response(self, response, request, data):
        try:
            isImage = getattr(request, 'isImage')
        except AttributeError:
            isImage = False
        
        if isImage:
            try:
                #For some reason more images get parsed using the parser
                #rather than a file...PIL still needs some work I guess
                p = ImageFile.Parser()
                p.feed(data)
                im = p.close()
                im = im.transpose(Image.ROTATE_180)
                output = StringIO()
                im.save(output, format=self.imageType)
                data = output.getvalue()
                output.close()
                self.clientlog.info("Flipped image", extra=request.clientInfo)
            except Exception as e:
                self.clientlog.info("Error: {}".format(e), extra=request.clientInfo)
        
        return {'response': response, 'request': request, 'data': data} 
Example #7
Source File: __init__.py    From platypush with MIT License 5 votes vote down vote up
def __init__(self, fps=16, skip_frames=2, scale_factor=1, rotate=0, rawrgb_path=None, **kwargs):
        """
        :param fps: Frames per seconds (default: 16)
        :param skip_frames: Number of frames to be skipped on sensor initialization/warmup (default: 2)
        :param scale_factor: The camera outputs 24x32 pixels artifacts. Use scale_factor to scale them up to a larger
            image (default: 1)
        :param rotate: Rotation angle in degrees (default: 0)
        :param rawrgb_path: Specify it if the rawrgb executable compiled from
            https://github.com/pimoroni/mlx90640-library is in another folder than
            `<directory of this file>/lib/examples`.
        """
        from PIL import Image
        super().__init__(**kwargs)

        self._rotate_values = {
            90: Image.ROTATE_90,
            180: Image.ROTATE_180,
            270: Image.ROTATE_270,
        }

        if not rawrgb_path:
            rawrgb_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib', 'examples', 'rawrgb')
        rawrgb_path = os.path.abspath(os.path.expanduser(rawrgb_path))

        assert fps > 0
        assert skip_frames >= 0
        assert os.path.isfile(rawrgb_path)

        self.fps = fps
        self.rotate = rotate
        self.skip_frames = skip_frames
        self.scale_factor = scale_factor
        self.rawrgb_path = rawrgb_path
        self._capture_proc = None 
Example #8
Source File: util.py    From proSR with GNU General Public License v3.0 5 votes vote down vote up
def random_rot90(img, r=None):
    if r is None:
        r = random.random() * 4  # TODO Check and rewrite func
    if r < 1:
        return img.transpose(Image.ROTATE_90)
    elif r < 2:
        return img.transpose(Image.ROTATE_270)
    elif r < 3:
        return img.transpose(Image.ROTATE_180)
    else:
        return img 
Example #9
Source File: display.py    From IT8951 with MIT License 5 votes vote down vote up
def _set_rotate(self, rotate):

        methods = {
            None   : None,
            'CW'   : Image.ROTATE_270,
            'CCW'  : Image.ROTATE_90,
            'flip' : Image.ROTATE_180,
        }

        if rotate not in methods:
            raise ValueError("invalid value for 'rotate'---options are None, 'CW', 'CCW', and 'flip'")

        self._rotate_method = methods[rotate] 
Example #10
Source File: __init__.py    From core with Apache License 2.0 5 votes vote down vote up
def transpose_image(image, method):
    """"Transpose (i.e. flip or rotate in 90° multiples) an image.

    Given a PIL.Image ``image`` and a transposition mode ``method``,
    apply the respective operation:

    - ``PIL.Image.FLIP_LEFT_RIGHT``:
      all pixels get mirrored at half the width of the image
    - ``PIL.Image.FLIP_TOP_BOTTOM``:
      all pixels get mirrored at half the height of the image
    - ``PIL.Image.ROTATE_180``:
      all pixels get mirrored at both, the width and half the height
      of the image,
      i.e. the image gets rotated by 180° counter-clockwise
    - ``PIL.Image.ROTATE_90``:
      rows become columns (but counted from the right) and
      columns become rows,
      i.e. the image gets rotated by 90° counter-clockwise;
      width becomes height and vice versa
    - ``PIL.Image.ROTATE_270``:
      rows become columns and
      columns become rows (but counted from the bottom),
      i.e. the image gets rotated by 270° counter-clockwise;
      width becomes height and vice versa
    - ``PIL.Image.TRANSPOSE``:
      rows become columns and vice versa,
      i.e. all pixels get mirrored at the main diagonal;
      width becomes height and vice versa
    - ``PIL.Image.TRANSVERSE``:
      rows become columns (but counted from the right) and
      columns become rows (but counted from the bottom),
      i.e. all pixels get mirrored at the opposite diagonal;
      width becomes height and vice versa
    
    Return a new PIL.Image.
    """
    LOG.debug('transposing image with %s', membername(Image, method))
    return image.transpose(method) 
Example #11
Source File: utils.py    From DTC with MIT License 5 votes vote down vote up
def __call__(self, old_image):
        xtranslation, ytranslation = np.random.randint(-self.max_translation,
                                                       self.max_translation + 1,
                                                       size=2)
        xpad, ypad = abs(xtranslation), abs(ytranslation)
        xsize, ysize = old_image.size

        flipped_lr = old_image.transpose(Image.FLIP_LEFT_RIGHT)
        flipped_tb = old_image.transpose(Image.FLIP_TOP_BOTTOM)
        flipped_both = old_image.transpose(Image.ROTATE_180)

        new_image = Image.new("RGB", (xsize + 2 * xpad, ysize + 2 * ypad))

        new_image.paste(old_image, (xpad, ypad))

        new_image.paste(flipped_lr, (xpad + xsize - 1, ypad))
        new_image.paste(flipped_lr, (xpad - xsize + 1, ypad))

        new_image.paste(flipped_tb, (xpad, ypad + ysize - 1))
        new_image.paste(flipped_tb, (xpad, ypad - ysize + 1))

        new_image.paste(flipped_both, (xpad - xsize + 1, ypad - ysize + 1))
        new_image.paste(flipped_both, (xpad + xsize - 1, ypad - ysize + 1))
        new_image.paste(flipped_both, (xpad - xsize + 1, ypad + ysize - 1))
        new_image.paste(flipped_both, (xpad + xsize - 1, ypad + ysize - 1))

        new_image = new_image.crop((xpad - xtranslation,
                                    ypad - ytranslation,
                                    xpad + xsize - xtranslation,
                                    ypad + ysize - ytranslation))

        return new_image 
Example #12
Source File: datasets.py    From amdim-public with MIT License 5 votes vote down vote up
def __call__(self, old_image):
        xtranslation, ytranslation = np.random.randint(-self.max_translation,
                                                       self.max_translation + 1,
                                                       size=2)
        xpad, ypad = abs(xtranslation), abs(ytranslation)
        xsize, ysize = old_image.size

        flipped_lr = old_image.transpose(Image.FLIP_LEFT_RIGHT)
        flipped_tb = old_image.transpose(Image.FLIP_TOP_BOTTOM)
        flipped_both = old_image.transpose(Image.ROTATE_180)

        new_image = Image.new("RGB", (xsize + 2 * xpad, ysize + 2 * ypad))

        new_image.paste(old_image, (xpad, ypad))

        new_image.paste(flipped_lr, (xpad + xsize - 1, ypad))
        new_image.paste(flipped_lr, (xpad - xsize + 1, ypad))

        new_image.paste(flipped_tb, (xpad, ypad + ysize - 1))
        new_image.paste(flipped_tb, (xpad, ypad - ysize + 1))

        new_image.paste(flipped_both, (xpad - xsize + 1, ypad - ysize + 1))
        new_image.paste(flipped_both, (xpad + xsize - 1, ypad - ysize + 1))
        new_image.paste(flipped_both, (xpad - xsize + 1, ypad + ysize - 1))
        new_image.paste(flipped_both, (xpad + xsize - 1, ypad + ysize - 1))

        new_image = new_image.crop((xpad - xtranslation,
                                    ypad - ytranslation,
                                    xpad + xsize - xtranslation,
                                    ypad + ysize - ytranslation))
        return new_image 
Example #13
Source File: transforms.py    From robosat with MIT License 5 votes vote down vote up
def __init__(self, p, degree):
        """Creates an `JointRandomRotation` instance.

        Args:
          p: the probability for rotating.
        """

        self.p = p

        methods = {90: Image.ROTATE_90, 180: Image.ROTATE_180, 270: Image.ROTATE_270}

        if degree not in methods.keys():
            raise NotImplementedError("We only support multiple of 90 degree rotations for now")

        self.method = methods[degree] 
Example #14
Source File: test_image_paste.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def gradient_RGBa(self):
        return Image.merge('RGBa', [
            self.gradient_L,
            self.gradient_L.transpose(Image.ROTATE_90),
            self.gradient_L.transpose(Image.ROTATE_180),
            self.gradient_L.transpose(Image.ROTATE_270),
        ]) 
Example #15
Source File: test_image_paste.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def gradient_RGBA(self):
        return Image.merge('RGBA', [
            self.gradient_L,
            self.gradient_L.transpose(Image.ROTATE_90),
            self.gradient_L.transpose(Image.ROTATE_180),
            self.gradient_L.transpose(Image.ROTATE_270),
        ]) 
Example #16
Source File: test_image_paste.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def gradient_RGB(self):
        return Image.merge('RGB', [
            self.gradient_L,
            self.gradient_L.transpose(Image.ROTATE_90),
            self.gradient_L.transpose(Image.ROTATE_180),
        ]) 
Example #17
Source File: test_color_lut.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_apply(self):
        lut = ImageFilter.Color3DLUT.generate(5, lambda r, g, b: (r, g, b))

        g = Image.linear_gradient('L')
        im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
                                 g.transpose(Image.ROTATE_180)])
        self.assertEqual(im, im.filter(lut)) 
Example #18
Source File: test_color_lut.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_numpy_formats(self):
        g = Image.linear_gradient('L')
        im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
                                 g.transpose(Image.ROTATE_180)])

        lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
                                              lambda r, g, b: (r, g, b))
        lut.table = numpy.array(lut.table, dtype=numpy.float32)[:-1]
        with self.assertRaisesRegex(ValueError, "should have table_channels"):
            im.filter(lut)

        lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
                                              lambda r, g, b: (r, g, b))
        lut.table = (numpy.array(lut.table, dtype=numpy.float32)
                     .reshape((7 * 9 * 11), 3))
        with self.assertRaisesRegex(ValueError, "should have table_channels"):
            im.filter(lut)

        lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
                                              lambda r, g, b: (r, g, b))
        lut.table = numpy.array(lut.table, dtype=numpy.float16)
        self.assert_image_equal(im, im.filter(lut))

        lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
                                              lambda r, g, b: (r, g, b))
        lut.table = numpy.array(lut.table, dtype=numpy.float32)
        self.assert_image_equal(im, im.filter(lut))

        lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
                                              lambda r, g, b: (r, g, b))
        lut.table = numpy.array(lut.table, dtype=numpy.float64)
        self.assert_image_equal(im, im.filter(lut))

        lut = ImageFilter.Color3DLUT.generate((7, 9, 11),
                                              lambda r, g, b: (r, g, b))
        lut.table = numpy.array(lut.table, dtype=numpy.int32)
        im.filter(lut)
        lut.table = numpy.array(lut.table, dtype=numpy.int8)
        im.filter(lut) 
Example #19
Source File: test_color_lut.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_copy_alpha_channel(self):
        g = Image.linear_gradient('L')
        im = Image.merge('RGBA', [g, g.transpose(Image.ROTATE_90),
                                  g.transpose(Image.ROTATE_180),
                                  g.transpose(Image.ROTATE_270)])

        self.assert_image_equal(im, im._new(
            im.im.color_lut_3d('RGBA', Image.LINEAR,
                               *self.generate_identity_table(3, 17)))) 
Example #20
Source File: test_color_lut.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_identities_4_channels(self):
        g = Image.linear_gradient('L')
        im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
                                 g.transpose(Image.ROTATE_180)])

        # Red channel copied to alpha
        self.assert_image_equal(
            Image.merge('RGBA', (im.split()*2)[:4]),
            im._new(im.im.color_lut_3d('RGBA', Image.LINEAR,
                                       *self.generate_identity_table(4, 17)))) 
Example #21
Source File: test_color_lut.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_identities(self):
        g = Image.linear_gradient('L')
        im = Image.merge('RGB', [g, g.transpose(Image.ROTATE_90),
                                 g.transpose(Image.ROTATE_180)])

        # Fast test with small cubes
        for size in [2, 3, 5, 7, 11, 16, 17]:
            self.assert_image_equal(im, im._new(
                im.im.color_lut_3d('RGB', Image.LINEAR,
                                   *self.generate_identity_table(3, size))))

        # Not so fast
        self.assert_image_equal(im, im._new(
            im.im.color_lut_3d('RGB', Image.LINEAR,
                               *self.generate_identity_table(3, (2, 2, 65))))) 
Example #22
Source File: test_image_transform.py    From python3_ios with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def test_rotate_180_deg(self):
        self._test_rotate(180, Image.ROTATE_180) 
Example #23
Source File: rotate_dataset.py    From self-supervised-da with MIT License 5 votes vote down vote up
def rotate(self, img, rot):
        if rot == 0:
            img_rt = img
        elif rot == 90:
            img_rt = img.transpose(Image.ROTATE_90)
        elif rot == 180:
            img_rt = img.transpose(Image.ROTATE_180)
        elif rot == 270:
            img_rt = img.transpose(Image.ROTATE_270)
        else:
            raise ValueError('Rotation angles should be in [0, 90, 180, 270]')
        return img_rt 
Example #24
Source File: dete_loader.py    From Text-Recognition with GNU Lesser General Public License v2.1 5 votes vote down vote up
def rotate(self, image, target, link, contour, angle):

		if angle == 0:
			if link is None:
				return image, target, contour
			return image, target, link, contour

		elif angle == 90:
			image = image.transpose(Image.ROTATE_90)
			target = target.transpose(Image.ROTATE_90)
			link = np.rot90(link)

			contour_f = self.contour_rotate(contour, 90, image.size[0], image.size[1])

		elif angle == 180:

			image = image.transpose(Image.ROTATE_180)
			target = target.transpose(Image.ROTATE_180)
			link = np.rot90(np.rot90(link))
			contour_f = self.contour_rotate(contour, 180, image.size[1], image.size[0])

		elif angle == 270:
			image = image.transpose(Image.ROTATE_270)
			target = target.transpose(Image.ROTATE_270)
			link = np.rot90(np.rot90(np.rot90(link)))
			contour_f = self.contour_rotate(contour, 270, image.size[0], image.size[1])

		if link is None:
				return image, target, contour_f

		return image, target, link, contour_f 
Example #25
Source File: base.py    From django-versatileimagefield with MIT License 4 votes vote down vote up
def preprocess(self, image, image_format):
        """
        Preprocess an image.

        An API hook for image pre-processing. Calls any image format specific
        pre-processors (if defined). I.E. If `image_format` is 'JPEG', this
        method will look for a method named `preprocess_JPEG`, if found
        `image` will be passed to it.

        Arguments:
            * `image`: a PIL Image instance
            * `image_format`: str, a valid PIL format (i.e. 'JPEG' or 'GIF')

        Subclasses should return a 2-tuple:
            * [0]: A PIL Image instance.
            * [1]: A dictionary of additional keyword arguments to be used
                   when the instance is saved. If no additional keyword
                   arguments, return an empty dict ({}).
        """
        save_kwargs = {'format': image_format}

        # Ensuring image is properly rotated
        if hasattr(image, '_getexif'):
            exif_datadict = image._getexif()  # returns None if no EXIF data
            if exif_datadict is not None:
                exif = dict(exif_datadict.items())
                orientation = exif.get(EXIF_ORIENTATION_KEY, None)
                if orientation == 3:
                    image = image.transpose(Image.ROTATE_180)
                elif orientation == 6:
                    image = image.transpose(Image.ROTATE_270)
                elif orientation == 8:
                    image = image.transpose(Image.ROTATE_90)

        # Ensure any embedded ICC profile is preserved
        save_kwargs['icc_profile'] = image.info.get('icc_profile')

        if hasattr(self, 'preprocess_%s' % image_format):
            image, addl_save_kwargs = getattr(
                self,
                'preprocess_%s' % image_format
            )(image=image)
            save_kwargs.update(addl_save_kwargs)

        return image, save_kwargs 
Example #26
Source File: __init__.py    From anima with MIT License 4 votes vote down vote up
def reorient_image(cls, img):
        """re-orients rotated images by looking at EXIF data
        """
        # get the image rotation from EXIF information
        import exifread

        file_full_path = img.filename

        with open(file_full_path) as f:
            tags = exifread.process_file(f)

        orientation_string = tags.get('Image Orientation')

        from PIL import Image
        if orientation_string:
            orientation = orientation_string.values[0]
            if orientation == 1:
                # do nothing
                pass
            elif orientation == 2:  # flipped in X
                img = img.transpose(Image.FLIP_LEFT_RIGHT)
            elif orientation == 3:  # rotated 180 degree
                img = img.transpose(Image.ROTATE_180)
            elif orientation == 4:  # flipped in Y
                img = img.transpose(Image.FLIP_TOP_BOTTOM)
            elif orientation == 5:  #
                img = img.transpose(Image.ROTATE_270)
                img = img.transpose(Image.FLIP_LEFT_RIGHT)
            elif orientation == 6:
                img = img.transpose(Image.FLIP_LEFT_RIGHT)
            elif orientation == 7:
                img = img.transpose(Image.ROTATE_90)
                img = img.transpose(Image.FLIP_LEFT_RIGHT)
            elif orientation == 8:
                img = img.transpose(Image.ROTATE_90)

        return img 
Example #27
Source File: detection_utils.py    From detectron2 with Apache License 2.0 4 votes vote down vote up
def _apply_exif_orientation(image):
    """
    Applies the exif orientation correctly.

    This code exists per the bug:
      https://github.com/python-pillow/Pillow/issues/3973
    with the function `ImageOps.exif_transpose`. The Pillow source raises errors with
    various methods, especially `tobytes`

    Function based on:
      https://github.com/wkentaro/labelme/blob/v4.5.4/labelme/utils/image.py#L59
      https://github.com/python-pillow/Pillow/blob/7.1.2/src/PIL/ImageOps.py#L527

    Args:
        image (PIL.Image): a PIL image

    Returns:
        (PIL.Image): the PIL image with exif orientation applied, if applicable
    """
    if not hasattr(image, "getexif"):
        return image

    exif = image.getexif()

    if exif is None:
        return image

    orientation = exif.get(_EXIF_ORIENT)

    method = {
        2: Image.FLIP_LEFT_RIGHT,
        3: Image.ROTATE_180,
        4: Image.FLIP_TOP_BOTTOM,
        5: Image.TRANSPOSE,
        6: Image.ROTATE_270,
        7: Image.TRANSVERSE,
        8: Image.ROTATE_90,
    }.get(orientation)

    if method is not None:
        return image.transpose(method)
    return image 
Example #28
Source File: media.py    From asm3 with GNU General Public License v3.0 4 votes vote down vote up
def auto_rotate_image(dbo, imagedata):
    """
    Automatically rotate an image according to the orientation of the
    image in the EXIF data. 
    """
    EXIF_ORIENTATION = 274
    OR_TO_ROTATE = {            # Map of EXIF Orientation to image rotation
        1: 0,                   # Correct orientation, no adjustment
        3: Image.ROTATE_180,    # upside down
        6: Image.ROTATE_270,    # rotated 90 degrees clockwise
        8: Image.ROTATE_90,     # rotated 90 degrees antilockwise
        # Flipped orientations        
        2: 0,
        7: Image.ROTATE_90,     # rotated 90 degrees anticlockwise
        4: Image.ROTATE_180,    # upside down
        5: Image.ROTATE_270     # rotated 90 degrees clockwise
    }
    try:
        inputd = asm3.utils.bytesio(imagedata)
        im = Image.open(inputd)
        if not hasattr(im, "_getexif") or im._getexif() is None:
            asm3.al.warn("image has no EXIF data, abandoning rotate", "media.auto_rotate_image", dbo)
            return imagedata
        exif = dict(im._getexif().items())
        if EXIF_ORIENTATION not in exif:
            asm3.al.warn("image EXIF data has no orientation", "media.auto_rotate_image", dbo)
            return imagedata
        rotation_factor = OR_TO_ROTATE[exif[EXIF_ORIENTATION]]
        flip = exif[EXIF_ORIENTATION] in (2, 7, 4, 5)
        if rotation_factor == 0 and not flip: 
            asm3.al.debug("image is already correctly rotated/flipped (EXIF==%s)" % exif[EXIF_ORIENTATION], "media.auto_rotate_image", dbo)
            return imagedata
        asm3.al.debug("orientation=%s --> rotate=%s deg cw, flip=%s" % (exif[EXIF_ORIENTATION], (rotation_factor*90-90), flip), "media.auto_rotate_image", dbo)
        if rotation_factor != 0: im = im.transpose(rotation_factor)
        if flip: im = im.transpose(Image.FLIP_LEFT_RIGHT)
        output = asm3.utils.bytesio()
        im.save(output, "JPEG")
        transposed_data = output.getvalue()
        output.close()
        return transposed_data
    except Exception as err:
        asm3.al.error("failed rotating/flipping image: %s" % str(err), "media.auto_rotate_image", dbo)
        return imagedata