blob: a1344bfa007b335d976573c7d0aa5d3b9b4b2a20 [file] [log] [blame]
// Copyright 2025 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT
// ----------------
// handsum decodes and encodes the Handsum lossy image file format.
package main
import (
"bytes"
"errors"
"flag"
"image"
"image/png"
"os"
"github.com/google/wuffs/lib/handsum"
_ "image/gif"
_ "image/jpeg"
_ "golang.org/x/image/bmp"
_ "golang.org/x/image/tiff"
_ "golang.org/x/image/webp"
)
var (
decodeFlag = flag.Bool("decode", false, "whether to decode the input")
encodeFlag = flag.Bool("encode", false, "whether to encode the input")
roundtripFlag = flag.Bool("roundtrip", false, "whether to encode-and-decode the input")
)
const usageStr = `handsum decodes and encodes the Handsum lossy image file format.
Usage: choose one of
handsum -decode [path]
handsum -encode [path]
handsum -roundtrip [path]
The path to the input image file is optional. If omitted, stdin is read.
The output image (in Handsum or PNG format) is written to stdout.
Decode inputs Handsum and outputs PNG.
Encode inputs BMP, GIF, JPEG, PNG, TIFF or WEBP and outputs Handsum.
Roundtrip is equivalent to encode (to an ephemeral file) and then decode.
`
func main() {
if err := main1(); err != nil {
os.Stderr.WriteString(err.Error() + "\n")
os.Exit(1)
}
}
func main1() error {
flag.Usage = func() { os.Stderr.WriteString(usageStr) }
flag.Parse()
inFile := os.Stdin
switch flag.NArg() {
case 0:
// No-op.
case 1:
f, err := os.Open(flag.Arg(0))
if err != nil {
return err
}
defer f.Close()
inFile = f
default:
return errors.New("too many filenames; the maximum is one")
}
if *decodeFlag && !*encodeFlag && !*roundtripFlag {
return decode(inFile)
}
if !*decodeFlag && *encodeFlag && !*roundtripFlag {
return encode(inFile)
}
if !*decodeFlag && !*encodeFlag && *roundtripFlag {
return roundtrip(inFile)
}
return errors.New("must specify exactly one of -decode, -encode, -roundtrip or -help")
}
func decode(inFile *os.File) error {
src, err := handsum.Decode(inFile)
if err != nil {
return err
}
return png.Encode(os.Stdout, src)
}
func encode(inFile *os.File) error {
src, _, err := image.Decode(inFile)
if err != nil {
return err
}
return handsum.Encode(os.Stdout, src, nil)
}
func roundtrip(inFile *os.File) error {
src, _, err := image.Decode(inFile)
if err != nil {
return err
}
buf := &bytes.Buffer{}
err = handsum.Encode(buf, src, nil)
if err != nil {
return err
}
dst, err := handsum.Decode(buf)
if err != nil {
return err
}
return png.Encode(os.Stdout, dst)
}