blob: 3306144189982ce3f79d5aac65c802a90985b9f3 [file] [log] [blame]
// Copyright 2017 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build ignore
package main
// extract-palette-indexes.go extracts the 1-byte-per-pixel indexes and, for
// paletted images, the 4-byte-per-entry BGRA (premultiplied alpha) palette of
// a paletted or gray GIF and PNG image. It checks that the GIF and PNG encode
// equivalent images.
//
// Usage: go run extract-palette-indexes.go foo.gif foo.png
import (
"bytes"
"fmt"
"image"
"image/gif"
"image/png"
"io/ioutil"
"os"
"path/filepath"
)
func main() {
if err := main1(); err != nil {
os.Stderr.WriteString(err.Error() + "\n")
os.Exit(1)
}
}
func main1() error {
baseFilename, bPalette, bIndexes := "", []byte(nil), []byte(nil)
for i, a := range os.Args[1:] {
b := a[:len(a)-len(filepath.Ext(a))]
palette, indexes, err := decode(a)
if err != nil {
return err
}
if i == 0 {
baseFilename, bPalette, bIndexes = b, palette, indexes
} else if baseFilename != b {
return fmt.Errorf("arguments do not have a common base path")
} else if !bytes.Equal(bPalette, palette) {
return fmt.Errorf("palettes are not equivalent")
} else if !bytes.Equal(bIndexes, indexes) {
return fmt.Errorf("indexes are not equivalent")
}
}
if bPalette != nil {
if err := ioutil.WriteFile(baseFilename+".palette", bPalette, 0644); err != nil {
return err
}
}
if bIndexes != nil {
if err := ioutil.WriteFile(baseFilename+".indexes", bIndexes, 0644); err != nil {
return err
}
}
return nil
}
func decode(filename string) (palette []byte, indexes []byte, err error) {
f, err := os.Open(filename)
if err != nil {
return nil, nil, err
}
defer f.Close()
m, err := image.Image(nil), error(nil)
switch ext := filepath.Ext(filename); ext {
case ".gif":
m, err = gif.Decode(f)
case ".png":
m, err = png.Decode(f)
default:
return nil, nil, fmt.Errorf("unsupported filename extension %q", ext)
}
if err != nil {
return nil, nil, err
}
switch m := m.(type) {
case *image.Gray:
return nil, m.Pix, nil
case *image.Paletted:
palette = make([]byte, 4*256)
allGray := true
for i, c := range m.Palette {
r, g, b, a := c.RGBA()
palette[4*i+0] = uint8(b >> 8)
palette[4*i+1] = uint8(g >> 8)
palette[4*i+2] = uint8(r >> 8)
palette[4*i+3] = uint8(a >> 8)
if allGray {
y := uint32(i)
allGray = r>>8 == y && g>>8 == y && b>>8 == y
}
}
if allGray {
return nil, m.Pix, nil
}
return palette, m.Pix, nil
}
return nil, nil, fmt.Errorf("decoded image type: got %T, want *image.Paletted", m)
}