Ejemplo n.º 1
0
func TestEncode(t *testing.T) {
	// Prepare data
	// x := []int{1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0}
	contents, err := ioutil.ReadFile("gettysburg.txt")
	if err != nil {
		t.Fatalf("%v", err)
	}
	x := []int{}
	for _, bt := range contents {
		for i := uint(0); i < 8; i++ {
			x = append(x, int(bt)&(1<<i)>>i)
		}
	}

	// Encode
	src := make(chan int)
	go func() {
		for _, b := range x {
			src <- b
		}
		close(src)
	}()

	encoded := []int{}
	dst := make(chan int)
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		for b := range dst {
			encoded = append(encoded, b)
		}
	}()

	witten.Encode(dst, src, NewCTW(make([]int, 48)))
	wg.Wait()
	t.Logf("encoded bits: %d, original bits: %d", len(encoded), len(x))

	// Decode
	dsrc := make(chan int)
	go func() {
		for i := range encoded {
			dsrc <- encoded[i]
		}
		close(dsrc)
	}()

	decoded := []int{}
	ddst := make(chan int)
	wg = sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		for b := range ddst {
			decoded = append(decoded, b)
		}
	}()

	if err := witten.Decode(ddst, dsrc, NewCTW(make([]int, 48)), int64(len(x))); err != nil {
		t.Fatalf("%v", err)
	}
	wg.Wait()

	// Check that the decoded result is correct.
	if len(x) != len(decoded) {
		t.Fatalf("%d != %d", len(x), len(decoded))
	}
	for i, b := range x {
		if decoded[i] != b {
			t.Errorf("%d: %d != %d", i, b, decoded[i])
		}
	}
}
Ejemplo n.º 2
0
Archivo: cmd.go Proyecto: fumin/ctw
// Compress compresses the named file using arithmetic coding supplied with a Context Tree Weighting probabilistic model of depth depth.
// The compressed result is written to w.
func Compress(w io.Writer, name string, depth int) error {
	// Write file size
	fi, err := os.Stat(name)
	if err != nil {
		return err
	}
	buf := new(bytes.Buffer)
	err = binary.Write(buf, binary.BigEndian, fi.Size())
	if err != nil {
		return err
	}
	if _, err = w.Write(buf.Bytes()); err != nil {
		return err
	}

	// Send file contents to encoder through the src channel.
	f, err := os.Open(name)
	if err != nil {
		return err
	}
	defer f.Close()
	src := make(chan int)
	errc := make(chan error, 1)
	// We allow the reader to terminate early via a stopReader channel,
	// in case for example, a downstream error occured when writing to w.
	stopReader := make(chan struct{}, 1)
	go func() {
		defer close(src)
		errc <- func() error {
			scanner := bufio.NewScanner(f)
			scanner.Split(bufio.ScanBytes)
			for scanner.Scan() {
				var bt byte = scanner.Bytes()[0]
				for i := uint(0); i < 8; i++ {
					select {
					case src <- ((int(bt) & (1 << i)) >> i):
					case <-stopReader:
					}
				}
			}
			if err := scanner.Err(); err != nil {
				return err
			}
			return nil
		}()
	}()

	// Collect encoded bits into bytes and write to w
	dst := make(chan int)
	dsterrc := make(chan error, 1)
	go func() {
		dsterrc <- func() error {
			defer func() { stopReader <- struct{}{} }()
			buf := []byte{0}
			var bt *byte = &buf[0]
			var i uint = 0
			for b := range dst {
				if b == 1 {
					*bt |= (1 << i)
				}
				i += 1

				if i == 8 {
					if _, err := w.Write(buf); err != nil {
						return err
					}
					*bt = 0
					i = 0
				}
			}
			if i > 0 {
				if _, err := w.Write(buf); err != nil {
					return err
				}
			}
			return nil
		}()
	}()

	model := NewCTW(make([]int, depth))
	witten.Encode(dst, src, model)

	if err := <-errc; err != nil {
		return err
	}
	if err := <-dsterrc; err != nil {
		return err
	}
	return nil
}