def rotate(self,
               degrees,
               clockwise=False,
               resample_algorithm=nearest,
               resize_canvas=True):
        """
        Returns the image obtained by rotating this image by the
        given number of degrees.
        Anticlockwise unless clockwise=True is given.
        """
        # translate to the origin first, then rotate, then translate back
        transform = AffineTransform()
        transform = transform.translate(self.width * -0.5, self.height * -0.5)
        transform = transform.rotate(degrees, clockwise=clockwise)

        width, height = self.width, self.height
        if resize_canvas:
            # determine new width
            width, height = get_transformed_dimensions(transform,
                                                       (0, 0, width, height))

        transform = transform.translate(width * 0.5, height * 0.5)

        pixels = resample_algorithm.affine(self,
                                           transform,
                                           resize_canvas=resize_canvas)

        return self._copy(pixels)
Beispiel #2
0
    def affine(self, source, transform, resize_canvas=True):
        if resize_canvas:
            # get image dimensions
            width, height = get_transformed_dimensions(
                transform,
                (0, 0, source.width, source.height)
            )
        else:
            width = source.width
            height = source.height

        pixelsize = source.pixelsize

        # transparent or black background
        background = [0] * pixelsize

        # we want to go from dest coords to src coords:
        transform = transform.inverse()

        # Optimisation:
        # Because affine transforms have no perspective component,
        # the *gradient* of each source row/column must be constant.
        # So, we can calculate the source coordinates for each corner,
        # and then interpolate for each pixel, instead of doing a
        # matrix multiplication for each pixel.

        x_range = range(width)
        y_range = range(height)
        new_array = source.pixels.copy()

        for y in y_range:
            line = array.array('B')  # initialize a new line

            # the 0.5's mean we use the center of each pixel
            row_x0, row_y0 = transform * (0.5, y + 0.5)
            row_x1, row_y1 = transform * (width + 0.5, y + 0.5)

            dx = float(row_x1 - row_x0) / source.width
            dy = float(row_y1 - row_y0) / source.width

            for x in x_range:
                source_x = int(row_x0 + dx * x)
                source_y = int(row_y0 + dy * x)

                new_array.set(x, y,
                    self._get_value(source, source_x, source_y, dx, dy)
                    or background
                )
        return new_array
Beispiel #3
0
    def affine(self, source, transform, resize_canvas=True):
        if resize_canvas:
            # get image dimensions
            width, height = get_transformed_dimensions(
                transform,
                (0, 0, source.width, source.height)
            )
        else:
            width = source.width
            height = source.height

        pixelsize = source.pixelsize

        # transparent or black background
        background = [0] * pixelsize

        # we want to go from dest coords to src coords:
        transform = transform.inverse()

        # Optimisation:
        # Because affine transforms have no perspective component,
        # the *gradient* of each source row/column must be constant.
        # So, we can calculate the source coordinates for each corner,
        # and then interpolate for each pixel, instead of doing a
        # matrix multiplication for each pixel.

        x_range = range(width)
        y_range = range(height)
        new_array = source.pixels.copy()

        for y in y_range:
            # the 0.5's mean we use the center of each pixel
            row_x0, row_y0 = transform * (0.5, y + 0.5)
            row_x1, row_y1 = transform * (width + 0.5, y + 0.5)

            dx = float(row_x1 - row_x0) / source.width
            dy = float(row_y1 - row_y0) / source.width

            for x in x_range:
                source_x = int(row_x0 + dx * x)
                source_y = int(row_y0 + dy * x)

                new_array.set(x, y,
                    self._get_value(source, source_x, source_y, dx, dy)
                    or background
                )
        return new_array
Beispiel #4
0
    def rotate(self, degrees, clockwise=False, resample_algorithm=nearest, resize_canvas=True):
        """
        Returns the image obtained by rotating this image by the
        given number of degrees.
        Anticlockwise unless clockwise=True is given.
        """
        # translate to the origin first, then rotate, then translate back
        transform = AffineTransform()
        transform = transform.translate(self.width * -0.5, self.height * -0.5)
        transform = transform.rotate(degrees, clockwise=clockwise)

        width, height = self.width, self.height
        if resize_canvas:
            # determine new width
            width, height = get_transformed_dimensions(transform, (0, 0, width, height))

        transform = transform.translate(width * 0.5, height * 0.5)

        pixels = resample_algorithm.affine(self, transform, resize_canvas=resize_canvas)

        return self._copy(pixels)