1# Copyright (c) 2013-2016 Jeffrey Pfau
2#
3# This Source Code Form is subject to the terms of the Mozilla Public
4# License, v. 2.0. If a copy of the MPL was not distributed with this
5# file, You can obtain one at http://mozilla.org/MPL/2.0/.
6from ._pylib import ffi  # pylint: disable=no-name-in-module
7from . import png
8
9try:
10    import PIL.Image as PImage
11except ImportError:
12    pass
13
14
15class Image:
16    def __init__(self, width, height, stride=0, alpha=False):
17        self.width = width
18        self.height = height
19        self.stride = stride
20        self.alpha = alpha
21        self.constitute()
22
23    def constitute(self):
24        if self.stride <= 0:
25            self.stride = self.width
26        self.buffer = ffi.new("color_t[{}]".format(self.stride * self.height))
27
28    def save_png(self, fileobj):
29        png_file = png.PNG(fileobj, mode=png.MODE_RGBA if self.alpha else png.MODE_RGB)
30        success = png_file.write_header(self)
31        success = success and png_file.write_pixels(self)
32        png_file.write_close()
33        return success
34
35    if 'PImage' in globals():
36        def to_pil(self):
37            colorspace = "RGBA" if self.alpha else "RGBX"
38            return PImage.frombytes(colorspace, (self.width, self.height), ffi.buffer(self.buffer), "raw",
39                                    colorspace, self.stride * 4)
40
41
42def u16_to_u32(color):
43    # pylint: disable=invalid-name
44    r = color & 0x1F
45    g = (color >> 5) & 0x1F
46    b = (color >> 10) & 0x1F
47    a = (color >> 15) & 1
48    abgr = r << 3
49    abgr |= g << 11
50    abgr |= b << 19
51    abgr |= (a * 0xFF) << 24
52    return abgr
53
54
55def u32_to_u16(color):
56    # pylint: disable=invalid-name
57    r = (color >> 3) & 0x1F
58    g = (color >> 11) & 0x1F
59    b = (color >> 19) & 0x1F
60    a = color >> 31
61    abgr = r
62    abgr |= g << 5
63    abgr |= b << 10
64    abgr |= a << 15
65    return abgr
66
67
68if ffi.sizeof("color_t") == 2:
69    def color_to_u16(color):
70        return color
71
72    color_to_u32 = u16_to_u32  # pylint: disable=invalid-name
73
74    def u16_to_color(color):
75        return color
76
77    u32_to_color = u32_to_u16  # pylint: disable=invalid-name
78else:
79    def color_to_u32(color):
80        return color
81
82    color_to_u16 = u32_to_u16  # pylint: disable=invalid-name
83
84    def u32_to_color(color):
85        return color
86
87    u16_to_color = u16_to_u32  # pylint: disable=invalid-name
88