blob: 7d0ad63a0ff33078db8576c9f0e732942fcaac22 [file] [log] [blame]
Nigel Tao25101a02017-06-01 10:15:32 +10001// Use of this source code is governed by a BSD-style license that can be found
2// in the LICENSE file.
3
4// +build ignore
5
6package main
7
8// extract-palette-indexes.go extracts the 1-byte-per-pixel indexes and the
9// 3-byte-per-entry RGB palette of a paletted GIF and PNG image. It checks that
10// the GIF and PNG encode equivalent images.
11//
12// Usage: go run extract-palette-indexes.go foo.gif foo.png
13
14import (
15 "fmt"
16 "image"
17 "image/gif"
18 "image/png"
19 "io/ioutil"
20 "os"
21 "path/filepath"
22 "reflect"
23)
24
25func main() {
26 if err := main1(); err != nil {
27 os.Stderr.WriteString(err.Error() + "\n")
28 os.Exit(1)
29 }
30}
31
32func main1() error {
33 baseFilename, img := "", (*image.Paletted)(nil)
34 for i, a := range os.Args[1:] {
35 b := a[:len(a)-len(filepath.Ext(a))]
36 m, err := decode(a)
37 if err != nil {
38 return err
39 }
40 if i == 0 {
41 baseFilename, img = b, m
42 } else if baseFilename != b {
43 return fmt.Errorf("arguments do not have a common base path")
44 } else if !reflect.DeepEqual(img, m) {
45 return fmt.Errorf("images are not equivalent")
46 }
47 }
48 palette := make([]byte, 3*256)
49 for i, c := range img.Palette {
50 r, g, b, _ := c.RGBA()
51 palette[3*i+0] = uint8(r >> 8)
52 palette[3*i+1] = uint8(g >> 8)
53 palette[3*i+2] = uint8(b >> 8)
54 }
55 if err := ioutil.WriteFile(baseFilename+".indexes", img.Pix, 0644); err != nil {
56 return err
57 }
58 if err := ioutil.WriteFile(baseFilename+".palette", palette, 0644); err != nil {
59 return err
60 }
61 return nil
62}
63
64func decode(filename string) (*image.Paletted, error) {
65 f, err := os.Open(filename)
66 if err != nil {
67 return nil, err
68 }
69 defer f.Close()
70
71 m, err := image.Image(nil), error(nil)
72 switch ext := filepath.Ext(filename); ext {
73 case ".gif":
74 m, err = gif.Decode(f)
75 case ".png":
76 m, err = png.Decode(f)
77 default:
78 return nil, fmt.Errorf("unsupported filename extension %q", ext)
79 }
80 if err != nil {
81 return nil, err
82 }
83 if p, ok := m.(*image.Paletted); ok {
84 return p, nil
85 }
86 return nil, fmt.Errorf("decoded image type: got %T, want *image.Paletted", m)
87}