예제 #1
0
    def __init__(self, mode=None, size=None, color=None, source=None):
        """
        ``mode`` must be one of the constants in the ``MODES`` set,

        ``size`` is a sequence of two integers (width and height of the new image);
        
        ``color`` is a sequence of integers, one for each
        component of the image, used to initialize all the pixels to the
        same value;
        
        ``source`` can be a sequence of integers of the appropriate size and format
        that is copied as-is in the buffer of the new image or an existing image;
        
        in Python 2.x ``source`` can also be an instance of ``str`` and is interpreted
        as a sequence of bytes.
        
        ``color`` and ``source`` are mutually exclusive and if
        they are both omitted the image is initialized to transparent
        black (all the bytes in the buffer have value 16 in the ``YV12``
        mode, 255 in the ``CMYK*`` modes and 0 for everything else). 
        
        If ``source`` is present and is an image, ``mode`` and/or ``size``
        can be omitted; if they are specified and are different from the
        source mode and/or size, the source image is converted.
        """
        self._mode = None
        self._size = None
        self._buffer = None
        self.info = {}

        if mode is not None:
            if mode not in MODES:
                raise ValueError("{} is not a valid mode.".format(mode))
            self._mode = mode

        if size is not None:
            try:
                self._size = ImageSize(*size)
            except:
                raise ValueError("size must be an iterable returning 2 " "elements, not {}".format(size))

        if source:
            # TODO: deal with source having a value
            if color:
                warnings.warn("color is disregarded when source is not None.")
            if isinstance(source, ImageMixin):
                if size:
                    if size != source.size:
                        # deal with resizing
                        pass
                    else:
                        pass
                else:
                    self._size = source.size
                if mode is None:
                    self._mode = source.mode
                else:
                    # deal with converting color
                    pass
            else:
                # source had better be an iterable that we can stuff
                # into a buffer
                # python2 supports a byte string
                if util.py27 and isinstance(source, str):
                    pass
        elif size and mode:

            assert self.size.width % self.mode.x_divisor == 0
            assert self.size.height % self.mode.y_divisor == 0

            if color and len(color) != self.components:
                raise ValueError(
                    "color must be an iterable with {} values, "
                    "one for each component in {}.".format(self.components, self.mode)
                )
            # initialize buffer to the correct size and color
            _buffer = util.initialize_buffer(mode, size, color)

            # TODO: externalize this structure building stuff
            line_struct = type(
                "LineBuffer",
                (Line,),
                {
                    "_fields_": [("pixels", mode.pixel_cls * self.size.width)],
                    "image_cls": self.__class__,
                    "mode": self.mode,
                },
            )

            image_struct = type("ImageBuffer", (_Image,), {"_fields_": [("lines", line_struct * self.size.height)]})

            self._image_data = image_struct.from_buffer(_buffer)
            self._buffer = memoryview(_buffer)

        else:
            raise ValueError(
                "You must minimally specify a source from "
                "which to build the image or a mode and size "
                "with which to initialize the buffer."
            )
예제 #2
0
 def setUpClass(cls):
     cls.pixels = {}
     for mode in MODES:
         buffer = util.initialize_buffer(mode, (1, 1))
         cls.pixels[mode] = mode.pixel_cls.from_buffer(buffer)