Example #1
0
class Texture():

    default_filtering = 'bilinear'

    def __init__(self, path):
        if 'Image' in str(type(path)):
            # print('passing pil image!')
            image = path
            self._texture = PandaTexture()
            self._texture.setup2dTexture(image.width, image.height, PandaTexture.TUnsignedByte, PandaTexture.FRgba)
            self._texture.setRamImageAs(image.transpose(Image.FLIP_TOP_BOTTOM).tobytes(), image.mode)
            self._cached_image = image.transpose(Image.FLIP_TOP_BOTTOM)
            self.path = None

        elif type(path) == PandaTexture:
            self._texture = path

        else:
            self.path = Path(path)
            self._texture = loader.loadTexture(Filename.fromOsSpecific(path))

            self._cached_image = None   # for get_pixel() method

        self.filtering = Texture.default_filtering


    @property
    def name(self):
        try:
            return self.path.name
        except:
            return f'PIL_texture_{self.size}'

    @property
    def size(self):
        return Vec2(self.width, self.height)

    @property
    def width(self):
        if self._texture.getOrigFileXSize() > 0:
            return self._texture.getOrigFileXSize()
        elif self._cached_image:
            return self._cached_image.size[0]
        return 0

    @property
    def height(self):
        if self._texture.getOrigFileYSize() > 0:
            return self._texture.getOrigFileYSize()
        elif self._cached_image:
            return self._cached_image.size[1]
        return 0

    @property
    def pixels(self):
        from numpy import asarray
        from PIL import Image

        if self._cached_image:
            return asarray(self._cached_image)

        return asarray(Image.open(self.path))

    @property
    def filtering(self):
        return self._filtering

    @filtering.setter
    def filtering(self, value):
        # print('setting filtering:', value)
        if value in (None, False, 'nearest', 'nearest neighbor'):
            self._texture.setMagfilter(SamplerState.FT_nearest)
            self._texture.setMinfilter(SamplerState.FT_nearest)
            self._filtering = False
        elif value in (True, 'linear', 'bilinear'):
            self._texture.setMagfilter(SamplerState.FT_linear)
            self._texture.setMinfilter(SamplerState.FT_linear)
            self._filtering = True


    def get_pixel(self, x, y):
        try:
            if not self._cached_image:
                self._cached_image = Image.open(self.path)

            col = self._cached_image.getpixel((x, self.height-y-1))
            if len(col) == 3:
                return (col[0], col[1], col[2], 255)
            else:
                return (col[0], col[1], col[2], col[3])
        except:
            return None


    def get_pixels(self, start, end):
        start = (clamp(start[0], 0, self.width), clamp(start[1], 0, self.width))
        end = (clamp(end[0], 0, self.width), clamp(end[1], 0, self.width))
        pixels = list()

        for y in range(start[1], end[1]):
            for x in range(start[0], end[0]):
                pixels.append(self.get_pixel(x,y))

        return pixels

    def set_pixel(self, x, y, color):
        if not self._cached_image:
            self._cached_image = Image.open(self.path)

        self._cached_image.putpixel((x, self.height-y-1), tuple([int(e*255) for e in color]))

    def apply(self):
        if not self._cached_image:
            self._cached_image = Image.open(self.path)

        self._texture.setRamImageAs(self._cached_image.transpose(Image.FLIP_TOP_BOTTOM).tobytes(), self._cached_image.mode)
        # self._texture.setRamImageAs(self._cached_image.tobytes(), self._cached_image.mode)

    def save(self, path):
        if not self._cached_image:
            self._cached_image = Image.open(self.path)

        self._cached_image.save(path)
Example #2
0
class Texture():

    default_filtering = 'bilinear'      # None/'bilinear'/'mipmap' default: 'bilinear'

    def __init__(self, value):

        if isinstance(value, str):
            value = Path(value)

        if isinstance(value, Path):
            self.path = Path(value)
            self._texture = loader.loadTexture(Filename.fromOsSpecific(str(value)))
            self._cached_image = None   # for get_pixel() method

        elif isinstance(value, PandaTexture):
            self._texture = value

        else:
            from PIL import Image
            image = value
            self._texture = PandaTexture()
            self._texture.setup2dTexture(image.width, image.height, PandaTexture.TUnsignedByte, PandaTexture.FRgba)
            self._texture.setRamImageAs(image.transpose(Image.FLIP_TOP_BOTTOM).tobytes(), image.mode)
            self._cached_image = image.transpose(Image.FLIP_TOP_BOTTOM)
            self.path = None



        self.filtering = Texture.default_filtering      # None/'bilinear'/'mipmap' default: 'bilinear'


    @property
    def name(self):
        try:
            return self.path.name
        except:
            return f'PIL_texture_{self.size}'

    @property
    def size(self):
        return Vec2(self.width, self.height)

    @property
    def width(self):
        if self._cached_image:
            return self._cached_image.size[0]
        elif self._texture.getOrigFileXSize() > 0:
            return self._texture.getOrigFileXSize()
        return 0

    @property
    def height(self):
        if self._cached_image:
            return self._cached_image.size[1]
        elif self._texture.getOrigFileYSize() > 0:
            return self._texture.getOrigFileYSize()
        return 0

    @property
    def pixels(self):
        from numpy import asarray, flip
        from PIL import Image

        if self._cached_image:
            return asarray(self._cached_image)

        pixels = asarray(Image.open(self.path))
        pixels = flip(pixels, axis=0)
        return pixels


    @property
    def filtering(self):
        return self._filtering

    @filtering.setter
    def filtering(self, value):
        # print('setting filtering:', value)
        if value in (None, False, 'nearest', 'nearest neighbor'):
            self._texture.setMagfilter(SamplerState.FT_nearest)
            self._texture.setMinfilter(SamplerState.FT_nearest)
            self._filtering = False
        elif value in (True, 'linear', 'bilinear'):
            self._texture.setMagfilter(SamplerState.FT_linear)
            self._texture.setMinfilter(SamplerState.FT_linear)
            self._filtering = True
        elif value == 'mipmap':
            self._texture.setMinfilter(SamplerState.FT_linear_mipmap_linear)
            self._filtering = 'mipmap'



    def get_pixel(self, x, y):
        try:
            if not self._cached_image:
                from PIL import Image
                self._cached_image = Image.open(self.path)


            col = self._cached_image.getpixel((x, self.height-y-1))
            if self._cached_image.mode == 'LA':
                col = (col[0], col[0], col[0], col[1])

            if self._cached_image.mode == 'L':
                col = (col[0], col[0], col[0])

            return color.rgba(*col)
        except Exception as e:
            print(e)
            return None


    def get_pixels(self, start, end):
        start = (clamp(start[0], 0, self.width), clamp(start[1], 0, self.width))
        end = (clamp(end[0], 0, self.width), clamp(end[1], 0, self.width))
        pixels = list()

        for y in range(start[1], end[1]):
            for x in range(start[0], end[0]):
                pixels.append(self.get_pixel(x,y))

        return pixels

    def set_pixel(self, x, y, color):
        if not self._cached_image:
            from PIL import Image
            self._cached_image = Image.open(self.path)

        self._cached_image.putpixel((x, self.height-y-1), tuple([int(e*255) for e in color]))

    def apply(self):
        from PIL import Image
        if not self._cached_image:
            self._cached_image = Image.open(self.path)

        self._texture.setRamImageAs(self._cached_image.transpose(Image.FLIP_TOP_BOTTOM).tobytes(), self._cached_image.mode)
        # self._texture.setRamImageAs(self._cached_image.tobytes(), self._cached_image.mode)

    def save(self, path):
        if not self._cached_image:
            from PIL import Image
            self._cached_image = Image.open(self.path)

        self._cached_image.save(path)