Beispiel #1
0
    def open(cls, fp, mode="rb"):
        i = cls()

        if isinstance(fp, basestring):
            try:
                i._image = JAI.create("fileload", fp)
            except:
                # JAI uses "IllegalArgumentException" for problems like "File
                # does not exist" and we'd like to return a more appropriate
                # exception where possible:

                e = sys.exc_info()[1]

                raise IOError("Unable to open %s: %s" % (fp, e))

        elif not hasattr(fp, "read"):
            raise TypeError("Don't know how to open a %r" % fp)

        else:

            try:
                byte_array = array("b")
                # array.fromfile() is documented as not supporting file-like
                # objects and we'd like to support both:
                byte_array.fromstring(fp.read())

                bs = ByteArraySeekableStream(byte_array)

                i._image = JAI.create("stream", bs)
            except:
                # See above
                e = sys.exc_info()[1]
                raise IOError("Unable to open %r: %s" % (fp, e))

        return i
Beispiel #2
0
    def save(self, fp, format="JPEG", **kwargs):
        if isinstance(fp, basestring):
            fp = open(fp, mode="wb")
        elif not hasattr(fp, "write"):
            raise ValueError("Don't know how to write to a %r" % fp)

        bos = ByteArrayOutputStream()

        JAI.create("encode", self._image, bos, format.lower())

        fp.write(bos.toByteArray())
        fp.flush()
Beispiel #3
0
    def crop(self, box):
        x0, y0, x1, y1 = box
        width = x1 - x0
        height = y1 - y0

        im = self.copy()

        pb = ParameterBlock()
        pb.addSource(self._image)
        pb.add(Float(x0))
        pb.add(Float(y0))
        pb.add(Float(width))
        pb.add(Float(height))

        im._image = JAI.create("crop", pb)

        return im
Beispiel #4
0
    def _resize(self, size, resample=ANTIALIAS):
        width, height = int(size[0]), int(size[1])

        pb = ParameterBlock()
        pb.addSource(self._image)
        # Since the scale & translate factors are passed using a generic-type
        # method we have to explicitly wrap them in java.lang.Float as the
        # default auto-bridged Double is not supported:
        pb.add(Float(width / self._image.getWidth()))    # x scale factor
        pb.add(Float(height / self._image.getHeight()))  # y scale factor
        pb.add(Float(0.0))                               # x translation
        pb.add(Float(0.0))                               # y translation
        pb.add(Interpolation.getInstance(resample))

        # Possible quality tweaks we might want to expose:
        # RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_RENDERING,
        #     RenderingHints.VALUE_RENDER_QUALITY)
        #
        # RenderedOp resizedImage = JAI.create("SubsampleAverage",
        #     image, scale, scale, qualityHints)

        return JAI.create("scale", pb)
Beispiel #5
0
    def rotate(self, angle, filter=NEAREST, expand=False):
        """
        Returns a rotated copy of this image.  This method returns a
        copy of this image, rotated the given number of degrees counter
        clockwise around its centre.

        :param angle: In degrees counter clockwise.
        :param filter: An optional resampling filter.  This can be
           one of NEAREST (use nearest neighbour), BILINEAR
           (linear interpolation in a 2x2 environment), or BICUBIC
           (cubic spline interpolation in a 4x4 environment).
           If omitted, or if the image has mode "1" or "P", it is
           set NEAREST.
        :param expand: Optional expansion flag.  If true, expands the output
           image to make it large enough to hold the entire rotated image.
           If false or omitted, make the output image the same size as the
           input image.
        :rtype: :class:Image object
        """

        radians = angle * (math.pi / 180.0)

        im = self.copy()

        pb = ParameterBlock()
        pb.addSource(self._image)

        transpose = None

        # In many cases we can simply transpose the image:
        if angle == 90:
            transpose = TransposeDescriptor.ROTATE_90
        elif angle == 180:
            transpose = TransposeDescriptor.ROTATE_180
        elif angle == 270:
            transpose = TransposeDescriptor.ROTATE_270

        if transpose:
            pb.add(transpose)
            im._image = JAI.create("transpose", pb)
            return im

        # looks like we have to do this the slow way:
        pb.add(Float(0.0))
        pb.add(Float(0.0))
        pb.add(Float(radians))
        pb.add(Interpolation.getInstance(filter))

        im._image = JAI.create("rotate", pb)

        # Rotate can leave the origin negative; we'll bump it back so our
        # future operations don't need to worry about this:
        if im._image.minX < 0 or im._image.minY < 0:
            pb = ParameterBlock()
            pb.addSource(im._image)
            pb.add(Float(im._image.minX * -1))
            pb.add(Float(im._image.minY * -1))
            im._image = JAI.create("translate", pb)

        if not expand:
            pb = ParameterBlock()
            pb.addSource(im._image)
            pb.add(Float(0))
            pb.add(Float(0))
            pb.add(Float(self._image.getWidth()))
            pb.add(Float(self._image.getHeight()))

            im._image = JAI.create("crop", pb)

        return im