Ejemplo n.º 1
0
 def ac_comp_fun(k, v):
     utils.debug_msg("Determining AC components for: " + k)
     splits = transform.split_matrix(v, settings.JPEG_BLOCK_SIZE)
     acs = transform.ac_components(splits)
     utils.debug_msg("Calculating RLE for: " + k)
     out = run_length_coding(acs)
     return out
Ejemplo n.º 2
0
 def test_split_singleton(self):
     square = np.array([
         [1, 2],
         [3, 4]
     ])
     splits = trans.split_matrix(square, 2)
     self.assertEqual(len(splits), 1)
     self.assertTrue(np.array_equiv(square, splits[0]))
Ejemplo n.º 3
0
 def test_block_must_pad(self):
     square = np.array([
         [1, 2, 3],
         [4, 5, 6],
         [7, 8, 9]
     ])
     splits = trans.split_matrix(square, 2)
     self.assertEqual(len(splits), 4)
     self.assertEqual(splits[0].shape, (2, 2))
     self.assertEqual(np.sum(splits[0]), 12)
     self.assertEqual(np.sum(splits[3]), 9)
Ejemplo n.º 4
0
 def test_block_nicely(self):
     square = np.array([
         [1, 2],
         [3, 4]
     ])
     splits = trans.split_matrix(square, 1)
     self.assertEqual(len(splits), 4)
     self.assertEqual((1, 1), splits[0].shape)
     self.assertEqual(1, splits[0][0][0])
     self.assertEqual(2, splits[1][0][0])
     self.assertEqual(3, splits[2][0][0])
     self.assertEqual(4, splits[3][0][0])
Ejemplo n.º 5
0
def jpeg_encode(compressed: model.CompressedImage) -> hic.HicImage:
    """
    Generally follow JPEG encoding. Since for the wavelet work I am don't have some standard huffman tree to work with
    I might as well be consistent between the two implementations and just encode the entire array with custom
    Huffman trees. To attempt to be honest with the implementation though, I'll still treat the DC components
    separately by doing the differences and again applying a custom Huffman. A main feature of DCT on each block is the
    meaning of the DC component.

    For RL it's also easier implementation-wise to split up the length from the value and not try to optimize and weave
    them together. Yes, the encoding will suffer bloat, but we are trying to highlight the transforms anyway.
    """
    utils.debug_msg("Starting JPEG encoding")
    dc_comps = utils.dict_map(
        compressed.as_dict, lambda _, v: differential_coding(
            transform.split_matrix(v, settings.JPEG_BLOCK_SIZE)))

    utils.debug_msg("Determined differences DC components")

    def ac_comp_fun(k, v):
        utils.debug_msg("Determining AC components for: " + k)
        splits = transform.split_matrix(v, settings.JPEG_BLOCK_SIZE)
        acs = transform.ac_components(splits)
        utils.debug_msg("Calculating RLE for: " + k)
        out = run_length_coding(acs)
        return out

    # on each transformed channel, run RLE on the AC components of each block
    ac_comps = utils.dict_map(compressed.as_dict, ac_comp_fun)

    utils.debug_msg("Determined RLEs for AC components")
    dc_huffs = utils.dict_map(
        dc_comps, lambda _, v: huffman.HuffmanTree.construct_from_data(v))
    ac_value_huffs = utils.dict_map(
        ac_comps, lambda _, v: huffman.HuffmanTree.construct_from_data(
            v, key_func=lambda s: s.value))
    ac_length_huffs = utils.dict_map(
        ac_comps, lambda _, v: huffman.HuffmanTree.construct_from_data(
            v, key_func=lambda s: s.length))

    def encode_huff(d):
        huffs = [t[1] for t in d.items()]
        return [huffman_encode(h) for h in huffs]

    def encode_data(d):
        huffs = [t[1] for t in d.items()]
        return [huffman_data_encode(h) for h in huffs]

    payloads = utils.flatten([
        encode_huff(dc_huffs),
        encode_huff(ac_value_huffs),
        encode_huff(ac_length_huffs),
        encode_data(dc_huffs),
        encode_data(ac_value_huffs),
        encode_data(ac_length_huffs),
        [
            hic.TupP(compressed.shape[0][0], compressed.shape[0][1]),
            hic.TupP(compressed.shape[1][0], compressed.shape[1][1])
        ]
    ])

    return hic.HicImage.jpeg_image(payloads)
Ejemplo n.º 6
0
 def test_differential_coding(self):
     matrix = np.array([[i + k for k in range(8)] for i in range(8)])
     blocks = transform.split_matrix(matrix, 4)
     dc = codec.differential_coding(blocks)
     self.assertEqual([0, 4, 0, 4], dc)
Ejemplo n.º 7
0
 def test_split_merge(self):
     matrix = np.random.randint(0, 256, (8, 12))
     blocks = trans.split_matrix(matrix, 4)
     merged = trans.merge_blocks(blocks, matrix.shape)
     self.assertTrue(np.array_equiv(matrix, merged))
Ejemplo n.º 8
0
 def test_merge_rect(self):
     mat = np.ones((3, 4))
     blocks = trans.split_matrix(mat, 2)
     merged = trans.merge_blocks(blocks, mat.shape)
     self.assertEqual(mat.shape, merged.shape)
     self.assertEqual(blocks.shape, (4, 2, 2))