0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Goで学ぶコンピューターサイエンスAdvent Calendar 2024

Day 3

【Goで学ぶコンピューターサイエンス】データ圧縮の基本

Last updated at Posted at 2024-12-04

データ圧縮

データ圧縮とは、データのサイズを小さくする技術です。圧縮されたデータは復元可能な場合(可逆圧縮)もあれば、一部の情報が失われる場合(非可逆圧縮)もあります。

データ圧縮の種類

可逆圧縮

圧縮前のデータを完全に復元可能な方法です。正確さが求められる場合に使用されます。

  • ZIP
  • PNG
  • GIF

非可逆圧縮

データの一部を削除して圧縮する方法です。人間が気づきにくい情報を削除することでサイズを大幅に削減します。

  • JPEG
  • MP3
  • H.264

基本的な圧縮アルゴリズム

ハフマン符号化

ハフマン符号化は、データ内の文字の頻度に基づいてビット列を割り当てる方法です。頻繁に出現する文字ほど短いビット列が割り当てられるため、全体のデータ量を削減できます。

ランレングス符号化(RLE)

RLEは、連続する同じ値をカウントし、圧縮します。例えば、「AAAAABBBCCCD」は「5A3B3C1D」に変換されます。

LZ77(Lempel-Ziv 1977)

データの重複部分を検出し、参照として保存する手法です。ZIPやgzipで使用されます。

可逆圧縮のGoサンプルコード

package main

import (
	"bytes"
	"compress/gzip"
	"fmt"
	"io"
)

func compress(data []byte) ([]byte, error) {
	var buf bytes.Buffer
	gz := gzip.NewWriter(&buf)
	_, err := gz.Write(data)
	if err != nil {
		return nil, err
	}
	gz.Close()
	return buf.Bytes(), nil
}

func decompress(data []byte) ([]byte, error) {
	buf := bytes.NewReader(data)
	gz, err := gzip.NewReader(buf)
	if err != nil {
		return nil, err
	}
	defer gz.Close()

	var result bytes.Buffer
	_, err = io.Copy(&result, gz)
	if err != nil {
		return nil, err
	}
	return result.Bytes(), nil
}

func main() {
	original := []byte("Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.Go is an amazing programming language! Go is efficient and fast.")
	fmt.Println("Original Data Size:", len(original))

	// 圧縮
	compressed, err := compress(original)
	if err != nil {
		fmt.Println("Compression error:", err)
		return
	}
	fmt.Println("Compressed Data Size:", len(compressed))

	// 解凍
	decompressed, err := decompress(compressed)
	if err != nil {
		fmt.Println("Decompression error:", err)
		return
	}
	fmt.Println("Decompressed Data Size:", len(decompressed))
}
Original Data Size: 1600
Compressed Data Size: 95
Decompressed Data Size: 1600

非可逆圧縮のGoサンプルコード

package main

import (
	"fmt"
	"image"
	"image/jpeg"
	"os"
)

func compressJPEG(inputPath, outputPath string, quality int) error {
	// 入力画像を読み込む
	inputFile, err := os.Open(inputPath)
	if err != nil {
		return err
	}
	defer inputFile.Close()

	img, _, err := image.Decode(inputFile)
	if err != nil {
		return err
	}

	// 出力ファイルを作成
	outputFile, err := os.Create(outputPath)
	if err != nil {
		return err
	}
	defer outputFile.Close()

	// JPEGとして保存(品質を指定)
	options := &jpeg.Options{Quality: quality}
	err = jpeg.Encode(outputFile, img, options)
	if err != nil {
		return err
	}

	return nil
}

func main() {
	inputPath := "input.jpg"   // 入力画像のパス
	outputPath := "output.jpg" // 圧縮後画像の保存先
	quality := 10              // 圧縮品質(1-100, 数値が低いほど圧縮率が高い)

	err := compressJPEG(inputPath, outputPath, quality)
	if err != nil {
		panic(err)
	}

	fmt.Println("圧縮が完了しました。")
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?