blob: 7d9cd71e393e3430885d9a0e2c469658ef9b9066 [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
Nigel Tao62833892017-06-03 17:35:29 +10008// extract-palette-indexes.go extracts the 1-byte-per-pixel indexes and, for
9// paletted images, the 3-byte-per-entry RGB palette of a paletted or gray GIF
10// and PNG image. It checks that the GIF and PNG encode equivalent images.
Nigel Tao25101a02017-06-01 10:15:32 +100011//
12// Usage: go run extract-palette-indexes.go foo.gif foo.png
13
14import (
Nigel Tao62833892017-06-03 17:35:29 +100015 "bytes"
Nigel Tao25101a02017-06-01 10:15:32 +100016 "fmt"
17 "image"
18 "image/gif"
19 "image/png"
20 "io/ioutil"
21 "os"
22 "path/filepath"
Nigel Tao25101a02017-06-01 10:15:32 +100023)
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 {
Nigel Tao62833892017-06-03 17:35:29 +100033 baseFilename, bPalette, bIndexes := "", []byte(nil), []byte(nil)
Nigel Tao25101a02017-06-01 10:15:32 +100034 for i, a := range os.Args[1:] {
35 b := a[:len(a)-len(filepath.Ext(a))]
Nigel Tao62833892017-06-03 17:35:29 +100036 palette, indexes, err := decode(a)
Nigel Tao25101a02017-06-01 10:15:32 +100037 if err != nil {
38 return err
39 }
40 if i == 0 {
Nigel Tao62833892017-06-03 17:35:29 +100041 baseFilename, bPalette, bIndexes = b, palette, indexes
Nigel Tao25101a02017-06-01 10:15:32 +100042 } else if baseFilename != b {
43 return fmt.Errorf("arguments do not have a common base path")
Nigel Tao62833892017-06-03 17:35:29 +100044 } else if !bytes.Equal(bPalette, palette) {
45 return fmt.Errorf("palettes are not equivalent")
46 } else if !bytes.Equal(bIndexes, indexes) {
47 return fmt.Errorf("indexes are not equivalent")
Nigel Tao25101a02017-06-01 10:15:32 +100048 }
49 }
Nigel Tao62833892017-06-03 17:35:29 +100050 if bPalette != nil {
51 if err := ioutil.WriteFile(baseFilename+".palette", bPalette, 0644); err != nil {
52 return err
53 }
Nigel Tao25101a02017-06-01 10:15:32 +100054 }
Nigel Tao62833892017-06-03 17:35:29 +100055 if bIndexes != nil {
56 if err := ioutil.WriteFile(baseFilename+".indexes", bIndexes, 0644); err != nil {
57 return err
58 }
Nigel Tao25101a02017-06-01 10:15:32 +100059 }
60 return nil
61}
62
Nigel Tao62833892017-06-03 17:35:29 +100063func decode(filename string) (palette []byte, indexes []byte, err error) {
Nigel Tao25101a02017-06-01 10:15:32 +100064 f, err := os.Open(filename)
65 if err != nil {
Nigel Tao62833892017-06-03 17:35:29 +100066 return nil, nil, err
Nigel Tao25101a02017-06-01 10:15:32 +100067 }
68 defer f.Close()
69
70 m, err := image.Image(nil), error(nil)
71 switch ext := filepath.Ext(filename); ext {
72 case ".gif":
73 m, err = gif.Decode(f)
74 case ".png":
75 m, err = png.Decode(f)
76 default:
Nigel Tao62833892017-06-03 17:35:29 +100077 return nil, nil, fmt.Errorf("unsupported filename extension %q", ext)
Nigel Tao25101a02017-06-01 10:15:32 +100078 }
79 if err != nil {
Nigel Tao62833892017-06-03 17:35:29 +100080 return nil, nil, err
Nigel Tao25101a02017-06-01 10:15:32 +100081 }
Nigel Tao62833892017-06-03 17:35:29 +100082 switch m := m.(type) {
83 case *image.Gray:
84 return nil, m.Pix, nil
85 case *image.Paletted:
86 palette = make([]byte, 3*256)
87 allGray := true
88 for i, c := range m.Palette {
89 r, g, b, _ := c.RGBA()
90 palette[3*i+0] = uint8(r >> 8)
91 palette[3*i+1] = uint8(g >> 8)
92 palette[3*i+2] = uint8(b >> 8)
93 if allGray {
94 y := uint32(i)
95 allGray = r>>8 == y && g>>8 == y && b>>8 == y
96 }
97 }
98 if allGray {
99 return nil, m.Pix, nil
100 }
101 return palette, m.Pix, nil
Nigel Tao25101a02017-06-01 10:15:32 +1000102 }
Nigel Tao62833892017-06-03 17:35:29 +1000103 return nil, nil, fmt.Errorf("decoded image type: got %T, want *image.Paletted", m)
Nigel Tao25101a02017-06-01 10:15:32 +1000104}