前提・実現したいこと
現在、wikipediaを参考に、ハフマン符号化のプログラムをjavaで作っていました。
しかし、画像を読み込み、符号化するとこのようになってしまいます。
first size 73736 #ファイルのサイズ size 4194304 # 符号化後
該当のソースコード
Java
1package org.jyl.base.io; 2 3import java.util.ArrayList; 4import java.util.BitSet; 5import java.util.PriorityQueue; 6 7public class Huffman 8{ 9 private BitStream bs; 10 11 public Huffman( byte[] data ) 12 { 13 bs = new BitStream(); 14 CodeInfo[] cf = createValue2Code( data ); 15 16 compress( data, cf ); 17 } 18 19 CodeInfo[] createValue2Code( byte[] data ) 20 { 21 // 各バイト値の発生回数を数える 22 TreeNode[] nodes = new TreeNode[ 256 ]; 23 for( int l = 0; l < 256; l++ ){ 24 // groovy での new TreeNode(value:l) 25 nodes[ l ] = new TreeNode(); 26 nodes[ l ].value = (byte)l; 27 } 28 29 // data の中身分繰り返す 30 for( byte v : data ) nodes[ Byte.toUnsignedInt( v ) ].occurrence++; 31 32 // ハフマン木を作成 33 // 配列をリストに変換 34 ArrayList<TreeNode> nodeslist = new ArrayList<TreeNode>( 0 ); 35 for( int l = 0; l < nodes.length; l++ ) nodeslist.add( nodes[ l ] ); 36 37 PriorityQueue<TreeNode> queue = new PriorityQueue<TreeNode>( nodeslist ); 38 39 while( queue.size() > 1 ){ 40 TreeNode n1 = queue.poll(), n2 = queue.poll(); 41 TreeNode tn = new TreeNode(); 42 tn.occurrence = n1.occurrence + n2.occurrence; 43 tn.children = new ArrayList<TreeNode>( 0 ); 44 tn.children.add( n1 ); tn.children.add( n2 ); 45 queue.add( tn ); 46 } 47 48 TreeNode root = queue.poll(); 49 50 // 深さ優先探索でバイト値->符号情報を作成 51 CodeInfo[] value2Code = new CodeInfo[ 256 ]; 52 dfs( value2Code, root, 0, 0 ); 53 54 return value2Code; 55 } 56 57 void dfs( CodeInfo[] value2Code, TreeNode node, int code, int codeSize ) 58 { 59 if( node.children == null ){ 60 CodeInfo cf = new CodeInfo(); 61 cf.code = code; cf.codeSize = codeSize; 62 value2Code[ Byte.toUnsignedInt( node.value ) ] = cf; 63 }else{ 64 dfs( value2Code, node.children.get( 0 ), code << 1, codeSize + 1 ); 65 dfs( value2Code, node.children.get( 1 ), ( code << 1 ) + 1, codeSize + 1 ); 66 } 67 } 68 69 /** 70 * 圧縮する 71 */ 72 void compress( byte[] data, CodeInfo[] value2Code ) 73 { 74 for( byte v : data ){ 75 CodeInfo codeInfo = value2Code[ Byte.toUnsignedInt( v ) ]; 76 bs.write( codeInfo.code, codeInfo.codeSize ); 77 } 78 } 79 80 public int getSize() 81 { 82 return bs.bs.size(); 83 } 84 85 /** 86 * 符号情報のクラス 87 */ 88 class CodeInfo 89 { 90 int code, codeSize; 91 } 92 93 class TreeNode implements Comparable<TreeNode> 94 { 95 byte value = 0; int occurrence = 0; 96 ArrayList<TreeNode> children; 97 98 public int compareTo( TreeNode that ) 99 { 100 return this.occurrence - that.occurrence; 101 } 102 } 103 104 class BitStream 105 { 106 BitSet bs = new BitSet(); 107 int len = 0, pos = 0; 108 109 void write( int v, int bits ) 110 { 111 for( int l = 0; l < 256; l++ ) 112 bs.set( len++, ( ( v >>> l ) & 1 ) != 0 ); 113 } 114 115 int read( int bits ) 116 { 117 int v = 0; 118 119 for( int l = 0; l < bits; l++ ){ 120 if( bs.get( pos++ ) ) v |= 1 << l; 121 } 122 123 return v; 124 } 125 } 126} 127
import java.io.FileInputStream; import java.util.ArrayList; import org.jyl.base.io.Huffman; public class Test { public static void main( String[] args ) throws java.io.IOException { ArrayList<Byte> b = new ArrayList<Byte>( 0 ); FileInputStream fis = new FileInputStream( new java.io.File( "/home/pi/Downloads/image/nc74842.png" ) ); int data = 0; for( int l = 0; ( data = fis.read() ) != -1; l++ ){ b.add( (byte)data ); } byte[] by = new byte[ b.size() ]; for( int l = 0; l < by.length; l++ ){ by[ l ] = b.get( l ); } System.out.println( "first size " + by.length ); Huffman hf = new Huffman( by ); System.out.println( "size " + hf.getSize() / 8 ); } }
試したこと
何が原因でこうなっているのか全くわかりません。
Groovyの仕様を確認した
補足情報(FW/ツールのバージョンなど)
Java8 を使っています。
回答3件
あなたの回答
tips
プレビュー