Exemplo n.º 1
0
def test_pnmimage_quantize():
    img = PNMImage(32, 32, 3)

    for x in range(32):
        for y in range(32):
            img.set_xel_val(x, y, randint(0, 100), randint(50, 100), randint(0, 1))

    hist = PNMImage.Histogram()
    img.make_histogram(hist)
    num_colors = hist.get_num_pixels()
    assert num_colors > 100

    img2 = PNMImage(img)
    img2.quantize(100)
    hist = PNMImage.Histogram()
    img2.make_histogram(hist)
    assert hist.get_num_pixels() <= 100

    # Make sure that this is reasonably close
    max_dist = 0
    for x in range(32):
        for y in range(32):
            diff = img.get_xel(x, y) - img2.get_xel(x, y)
            max_dist = max(max_dist, diff.length_squared())

            # Also make sure that they are not out of range of the original
            col = img2.get_xel_val(x, y)
            assert col.r <= 100
            assert col.g >= 50 and col.g <= 100
            assert col.b in (0, 1)

    assert max_dist < 0.1 ** 2
Exemplo n.º 2
0
    def _write_bitmap(self, fp, image, size, bpp):
        """ Writes the bitmap header and data of an .ico file. """

        fp.write(
            struct.pack('<IiiHHIIiiII', 40, size, size * 2, 1, bpp, 0, 0, 0, 0,
                        0, 0))

        # XOR mask
        if bpp == 24:
            # Align rows to 4-byte boundary
            rowalign = b'\0' * (-(size * 3) & 3)
            for y in xrange(size):
                for x in xrange(size):
                    r, g, b = image.getXel(x, size - y - 1)
                    fp.write(
                        struct.pack('<BBB', int(b * 255), int(g * 255),
                                    int(r * 255)))
                fp.write(rowalign)

        elif bpp == 32:
            for y in xrange(size):
                for x in xrange(size):
                    r, g, b, a = image.getXelA(x, size - y - 1)
                    fp.write(
                        struct.pack('<BBBB', int(b * 255), int(g * 255),
                                    int(r * 255), int(a * 255)))

        elif bpp == 8:
            # We'll have to generate a palette of 256 colors.
            hist = PNMImage.Histogram()
            image2 = PNMImage(image)
            if image2.hasAlpha():
                image2.premultiplyAlpha()
                image2.removeAlpha()
            image2.quantize(256)
            image2.make_histogram(hist)
            colors = list(hist.get_pixels())
            assert len(colors) <= 256

            # Write the palette.
            i = 0
            while i < 256 and i < len(colors):
                r, g, b, a = colors[i]
                fp.write(struct.pack('<BBBB', b, g, r, 0))
                i += 1
            if i < 256:
                # Fill the rest with zeroes.
                fp.write(b'\x00' * (4 * (256 - i)))

            # Write indices.  Align rows to 4-byte boundary.
            rowalign = b'\0' * (-size & 3)
            for y in xrange(size):
                for x in xrange(size):
                    pixel = image2.get_pixel(x, size - y - 1)
                    index = colors.index(pixel)
                    if index >= 256:
                        # Find closest pixel instead.
                        index = closest_indices[index - 256]
                    fp.write(struct.pack('<B', index))
                fp.write(rowalign)
        else:
            raise ValueError("Invalid bpp %d" % (bpp))

        # Create an AND mask, aligned to 4-byte boundary
        if image.hasAlpha() and bpp <= 8:
            rowalign = b'\0' * (-((size + 7) >> 3) & 3)
            for y in xrange(size):
                mask = 0
                num_bits = 7
                for x in xrange(size):
                    a = image.get_alpha_val(x, size - y - 1)
                    if a <= 1:
                        mask |= (1 << num_bits)
                    num_bits -= 1
                    if num_bits < 0:
                        fp.write(struct.pack('<B', mask))
                        mask = 0
                        num_bits = 7
                if num_bits < 7:
                    fp.write(struct.pack('<B', mask))
                fp.write(rowalign)
        else:
            andsize = (size + 7) >> 3
            if andsize % 4 != 0:
                andsize += 4 - (andsize % 4)
            fp.write(b'\x00' * (andsize * size))