1
1
mirror of https://github.com/wader/fq.git synced 2024-09-19 07:47:14 +03:00

png: Decode PLTE and tRNS chunks and cleanup syms a bit

This commit is contained in:
Mattias Wadman 2022-01-07 14:29:16 +01:00
parent 2c3e41111d
commit bfc977b810
12 changed files with 139 additions and 52 deletions

View File

@ -97,10 +97,10 @@ $ fq -d flac verbose /picture_seek_gain.flac
0x0160| 00 00 00 04| ....| width: 4 0x16c-0x16f.7 (4)
0x0170|00 00 00 04 |.... | height: 4 0x170-0x173.7 (4)
0x0170| 01 | . | bit_depth: 1 0x174-0x174.7 (1)
0x0170| 00 | . | color_type: "g" (0) (Grayscale) 0x175-0x175.7 (1)
0x0170| 00 | . | color_type: "grayscale" (0) 0x175-0x175.7 (1)
0x0170| 00 | . | compression_method: "deflate" (0) 0x176-0x176.7 (1)
0x0170| 00 | . | filter_method: "Adaptive filtering" (0) 0x177-0x177.7 (1)
0x0170| 00 | . | interlace_method: "No interlace" (0) 0x178-0x178.7 (1)
0x0170| 00 | . | filter_method: "adaptive_filtering" (0) 0x177-0x177.7 (1)
0x0170| 00 | . | interlace_method: "none" (0) 0x178-0x178.7 (1)
0x0170| 81 8a a3 d3 | .... | crc: 0x818aa3d3 (valid) 0x179-0x17c.7 (4)
| | | [1]{}: chunk 0x17d-0x18c.7 (16)
0x0170| 00 00 00| ...| length: 4 0x17d-0x180.7 (4)

View File

@ -66,10 +66,10 @@ $ fq -d id3v2 verbose /apic
0x40| 00 00| ..| height: 4 0x4e-0x51.7 (4)
0x50|00 04 |.. |
0x50| 08 | . | bit_depth: 8 0x52-0x52.7 (1)
0x50| 02 | . | color_type: "rgb" (2) (RGB) 0x53-0x53.7 (1)
0x50| 02 | . | color_type: "rgb" (2) 0x53-0x53.7 (1)
0x50| 00 | . | compression_method: "deflate" (0) 0x54-0x54.7 (1)
0x50| 00 | . | filter_method: "Adaptive filtering" (0) 0x55-0x55.7 (1)
0x50| 00 | . | interlace_method: "No interlace" (0) 0x56-0x56.7 (1)
0x50| 00 | . | filter_method: "adaptive_filtering" (0) 0x55-0x55.7 (1)
0x50| 00 | . | interlace_method: "none" (0) 0x56-0x56.7 (1)
0x50| 26 93 09 29 | &..) | crc: 0x26930929 (valid) 0x57-0x5a.7 (4)
| | | [1]{}: chunk 0x5b-0x6f.7 (21)
0x50| 00 00 00 09 | .... | length: 9 0x5b-0x5e.7 (4)

View File

@ -48,10 +48,10 @@ $ fq -d id3v2 verbose /utf16-apic
0x030| 00 00 00 04| ....| width: 4 0x3c-0x3f.7 (4)
0x040|00 00 00 04 |.... | height: 4 0x40-0x43.7 (4)
0x040| 01 | . | bit_depth: 1 0x44-0x44.7 (1)
0x040| 00 | . | color_type: "g" (0) (Grayscale) 0x45-0x45.7 (1)
0x040| 00 | . | color_type: "grayscale" (0) 0x45-0x45.7 (1)
0x040| 00 | . | compression_method: "deflate" (0) 0x46-0x46.7 (1)
0x040| 00 | . | filter_method: "Adaptive filtering" (0) 0x47-0x47.7 (1)
0x040| 00 | . | interlace_method: "No interlace" (0) 0x48-0x48.7 (1)
0x040| 00 | . | filter_method: "adaptive_filtering" (0) 0x47-0x47.7 (1)
0x040| 00 | . | interlace_method: "none" (0) 0x48-0x48.7 (1)
0x040| 81 8a a3 d3 | .... | crc: 0x818aa3d3 (valid) 0x49-0x4c.7 (4)
| | | [1]{}: chunk 0x4d-0x5c.7 (16)
0x040| 00 00 00| ...| length: 4 0x4d-0x50.7 (4)

View File

@ -68,12 +68,12 @@ const (
colorTypeRGBA = 6
)
var colorTypeMap = scalar.UToScalar{
colorTypeGrayscale: {Sym: "g", Description: "Grayscale"},
colorTypeRGB: {Sym: "rgb", Description: "RGB"},
colorTypePalette: {Sym: "p", Description: "Palette"},
colorTypeGrayscaleWithAlpha: {Sym: "ga", Description: "Grayscale with alpha"},
colorTypeRGBA: {Sym: "rgba", Description: "RGBA"},
var colorTypeMap = scalar.UToSymStr{
colorTypeGrayscale: "grayscale",
colorTypeRGB: "rgb",
colorTypePalette: "palette",
colorTypeGrayscaleWithAlpha: "grayscale_alpha",
colorTypeRGBA: "rgba",
}
func pngDecode(d *decode.D, in interface{}) interface{} {
@ -84,22 +84,18 @@ func pngDecode(d *decode.D, in interface{}) interface{} {
d.FieldStructArrayLoop("chunks", "chunk", func() bool { return d.NotEnd() && !iEndFound }, func(d *decode.D) {
chunkLength := d.FieldU32("length")
crcStartPos := d.Pos()
// TODO: this is a bit weird, use struct?
chunkType := d.FieldStrFn("type", func(d *decode.D) string {
chunkType := d.UTF8(4)
// upper/lower case in chunk type is used to set flags
d.SeekRel(-4 * 8)
d.SeekRel(3)
d.FieldBool("ancillary")
d.SeekRel(7)
d.FieldBool("private")
d.SeekRel(7)
d.FieldBool("reserved")
d.SeekRel(7)
d.FieldBool("safe_to_copy")
d.SeekRel(4)
return chunkType
})
chunkType := d.FieldUTF8("type", 4)
// upper/lower case in chunk type is used for flags
d.SeekRel(-4 * 8)
d.SeekRel(3)
d.FieldBool("ancillary")
d.SeekRel(7)
d.FieldBool("private")
d.SeekRel(7)
d.FieldBool("reserved")
d.SeekRel(7)
d.FieldBool("safe_to_copy")
d.SeekRel(4)
d.LenFn(int64(chunkLength)*8, func(d *decode.D) {
switch chunkType {
@ -110,11 +106,11 @@ func pngDecode(d *decode.D, in interface{}) interface{} {
colorType = d.FieldU8("color_type", colorTypeMap)
d.FieldU8("compression_method", compressionNames)
d.FieldU8("filter_method", scalar.UToSymStr{
0: "Adaptive filtering",
0: "adaptive_filtering",
})
d.FieldU8("interlace_method", scalar.UToSymStr{
0: "No interlace",
1: "Adam7 interlace",
0: "none",
1: "adam7",
})
case "tEXt":
d.FieldUTF8Null("keyword")
@ -196,6 +192,31 @@ func pngDecode(d *decode.D, in interface{}) interface{} {
case "fdAT":
d.FieldU32("sequence_number")
d.FieldRawLen("data", d.BitsLeft()-32)
case "PLTE":
d.FieldArray("palette", func(d *decode.D) {
for !d.End() {
d.FieldStruct("color", func(d *decode.D) {
d.FieldU8("r")
d.FieldU8("g")
d.FieldU8("b")
})
}
})
case "tRNS":
switch colorType {
case colorTypeGrayscale:
d.FieldU16("alpha")
case colorTypeRGB:
d.FieldU16("r")
d.FieldU16("g")
d.FieldU16("b")
case colorTypePalette:
d.FieldArray("alphas", func(d *decode.D) {
for !d.End() {
d.FieldU8("alpha")
}
})
}
default:
if chunkType == "IEND" {
iEndFound = true

View File

@ -15,10 +15,10 @@ $ fq -d png verbose /4x4.png
0x010|00 00 00 04 |.... | width: 4 0x10-0x13.7 (4)
0x010| 00 00 00 04 | .... | height: 4 0x14-0x17.7 (4)
0x010| 01 | . | bit_depth: 1 0x18-0x18.7 (1)
0x010| 00 | . | color_type: "g" (0) (Grayscale) 0x19-0x19.7 (1)
0x010| 00 | . | color_type: "grayscale" (0) 0x19-0x19.7 (1)
0x010| 00 | . | compression_method: "deflate" (0) 0x1a-0x1a.7 (1)
0x010| 00 | . | filter_method: "Adaptive filtering" (0) 0x1b-0x1b.7 (1)
0x010| 00 | . | interlace_method: "No interlace" (0) 0x1c-0x1c.7 (1)
0x010| 00 | . | filter_method: "adaptive_filtering" (0) 0x1b-0x1b.7 (1)
0x010| 00 | . | interlace_method: "none" (0) 0x1c-0x1c.7 (1)
0x010| 81 8a a3| ...| crc: 0x818aa3d3 (valid) 0x1d-0x20.7 (4)
0x020|d3 |. |
| | | [1]{}: chunk 0x21-0x30.7 (16)

66
format/png/testdata/4x4_palette.fqtest vendored Normal file
View File

@ -0,0 +1,66 @@
# gm convert -size 4x4 'gradient:#ff00ff-#00ff00' -colors 254 4x4_palette.png
$ fq verbose 4x4_palette.png
|00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f|0123456789abcdef|.{}: 4x4_palette.png (png) 0x0-0x60.7 (97)
0x00|89 50 4e 47 0d 0a 1a 0a |.PNG.... | signature: raw bits (valid) 0x0-0x7.7 (8)
| | | chunks[0:4]: 0x8-0x60.7 (89)
| | | [0]{}: chunk 0x8-0x20.7 (25)
0x00| 00 00 00 0d | .... | length: 13 0x8-0xb.7 (4)
0x00| 49 48 44 52| IHDR| type: "IHDR" 0xc-0xf.7 (4)
0x00| 49 | I | ancillary: false 0xc.3-0xc.3 (0.1)
0x00| 48 | H | private: false 0xd.3-0xd.3 (0.1)
0x00| 44 | D | reserved: false 0xe.3-0xe.3 (0.1)
0x00| 52| R| safe_to_copy: true 0xf.3-0xf.3 (0.1)
0x10|00 00 00 04 |.... | width: 4 0x10-0x13.7 (4)
0x10| 00 00 00 04 | .... | height: 4 0x14-0x17.7 (4)
0x10| 02 | . | bit_depth: 2 0x18-0x18.7 (1)
0x10| 03 | . | color_type: "palette" (3) 0x19-0x19.7 (1)
0x10| 00 | . | compression_method: "deflate" (0) 0x1a-0x1a.7 (1)
0x10| 00 | . | filter_method: "adaptive_filtering" (0) 0x1b-0x1b.7 (1)
0x10| 00 | . | interlace_method: "none" (0) 0x1c-0x1c.7 (1)
0x10| d4 9f 76| ..v| crc: 0xd49f76ed (valid) 0x1d-0x20.7 (4)
0x20|ed |. |
| | | [1]{}: chunk 0x21-0x38.7 (24)
0x20| 00 00 00 0c | .... | length: 12 0x21-0x24.7 (4)
0x20| 50 4c 54 45 | PLTE | type: "PLTE" 0x25-0x28.7 (4)
0x20| 50 | P | ancillary: true 0x25.3-0x25.3 (0.1)
0x20| 4c | L | private: false 0x26.3-0x26.3 (0.1)
0x20| 54 | T | reserved: true 0x27.3-0x27.3 (0.1)
0x20| 45 | E | safe_to_copy: false 0x28.3-0x28.3 (0.1)
| | | palette[0:4]: 0x29-0x34.7 (12)
| | | [0]{}: color 0x29-0x2b.7 (3)
0x20| ff | . | r: 255 0x29-0x29.7 (1)
0x20| 00 | . | g: 0 0x2a-0x2a.7 (1)
0x20| ff | . | b: 255 0x2b-0x2b.7 (1)
| | | [1]{}: color 0x2c-0x2e.7 (3)
0x20| aa | . | r: 170 0x2c-0x2c.7 (1)
0x20| 55 | U | g: 85 0x2d-0x2d.7 (1)
0x20| aa | . | b: 170 0x2e-0x2e.7 (1)
| | | [2]{}: color 0x2f-0x31.7 (3)
0x20| 55| U| r: 85 0x2f-0x2f.7 (1)
0x30|aa |. | g: 170 0x30-0x30.7 (1)
0x30| 55 | U | b: 85 0x31-0x31.7 (1)
| | | [3]{}: color 0x32-0x34.7 (3)
0x30| 00 | . | r: 0 0x32-0x32.7 (1)
0x30| ff | . | g: 255 0x33-0x33.7 (1)
0x30| 00 | . | b: 0 0x34-0x34.7 (1)
0x30| 64 03 f4 86 | d... | crc: 0x6403f486 (valid) 0x35-0x38.7 (4)
| | | [2]{}: chunk 0x39-0x54.7 (28)
0x30| 00 00 00 10 | .... | length: 16 0x39-0x3c.7 (4)
0x30| 49 44 41| IDA| type: "IDAT" 0x3d-0x40.7 (4)
0x40|54 |T |
0x30| 49 | I | ancillary: false 0x3d.3-0x3d.3 (0.1)
0x30| 44 | D | private: false 0x3e.3-0x3e.3 (0.1)
0x30| 41| A| reserved: false 0x3f.3-0x3f.3 (0.1)
0x40|54 |T | safe_to_copy: true 0x40.3-0x40.3 (0.1)
0x40| 08 d7 63 60 60 08 65 58 c5 f0 1f 00 04 ae 01| ..c``.eX.......| data: raw bits 0x41-0x50.7 (16)
0x50|ff |. |
0x50| 7c 82 85 30 | |..0 | crc: 0x7c828530 (valid) 0x51-0x54.7 (4)
| | | [3]{}: chunk 0x55-0x60.7 (12)
0x50| 00 00 00 00 | .... | length: 0 0x55-0x58.7 (4)
0x50| 49 45 4e 44 | IEND | type: "IEND" 0x59-0x5c.7 (4)
0x50| 49 | I | ancillary: false 0x59.3-0x59.3 (0.1)
0x50| 45 | E | private: false 0x5a.3-0x5a.3 (0.1)
0x50| 4e | N | reserved: false 0x5b.3-0x5b.3 (0.1)
0x50| 44 | D | safe_to_copy: false 0x5c.3-0x5c.3 (0.1)
0x50| ae 42 60| .B`| crc: 0xae426082 (valid) 0x5d-0x60.7 (4)
0x60|82| |.| |

BIN
format/png/testdata/4x4_palette.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 B

View File

@ -13,10 +13,10 @@ $ fq -d png verbose /4x4a.apng
0x10|00 00 00 04 |.... | width: 4 0x10-0x13.7 (4)
0x10| 00 00 00 04 | .... | height: 4 0x14-0x17.7 (4)
0x10| 08 | . | bit_depth: 8 0x18-0x18.7 (1)
0x10| 02 | . | color_type: "rgb" (2) (RGB) 0x19-0x19.7 (1)
0x10| 02 | . | color_type: "rgb" (2) 0x19-0x19.7 (1)
0x10| 00 | . | compression_method: "deflate" (0) 0x1a-0x1a.7 (1)
0x10| 00 | . | filter_method: "Adaptive filtering" (0) 0x1b-0x1b.7 (1)
0x10| 00 | . | interlace_method: "No interlace" (0) 0x1c-0x1c.7 (1)
0x10| 00 | . | filter_method: "adaptive_filtering" (0) 0x1b-0x1b.7 (1)
0x10| 00 | . | interlace_method: "none" (0) 0x1c-0x1c.7 (1)
0x10| 26 93 09| &..| crc: 0x26930929 (valid) 0x1d-0x20.7 (4)
0x20|29 |) |
| | | [1]{}: chunk 0x21-0x35.7 (21)

View File

@ -47,10 +47,10 @@ $ fq -d vorbis_comment verbose /vorbis-comment-picture
0x30| 00 00 00| ...| height: 4 0x3d-0x40.7 (4)
0x40|04 |. |
0x40| 08 | . | bit_depth: 8 0x41-0x41.7 (1)
0x40| 02 | . | color_type: "rgb" (2) (RGB) 0x42-0x42.7 (1)
0x40| 02 | . | color_type: "rgb" (2) 0x42-0x42.7 (1)
0x40| 00 | . | compression_method: "deflate" (0) 0x43-0x43.7 (1)
0x40| 00 | . | filter_method: "Adaptive filtering" (0) 0x44-0x44.7 (1)
0x40| 00 | . | interlace_method: "No interlace" (0) 0x45-0x45.7 (1)
0x40| 00 | . | filter_method: "adaptive_filtering" (0) 0x44-0x44.7 (1)
0x40| 00 | . | interlace_method: "none" (0) 0x45-0x45.7 (1)
0x40| 26 93 09 29 | &..) | crc: 0x26930929 (valid) 0x46-0x49.7 (4)
| | | [1]{}: chunk 0x4a-0x5e.7 (21)
0x40| 00 00 00 09 | .... | length: 9 0x4a-0x4d.7 (4)

View File

@ -200,10 +200,10 @@ $ fq -d zip verbose /test-macos.zip
0x010|00 00 00 04 |.... | width: 4 0x10-0x13.7 (4)
0x010| 00 00 00 04 | .... | height: 4 0x14-0x17.7 (4)
0x010| 01 | . | bit_depth: 1 0x18-0x18.7 (1)
0x010| 00 | . | color_type: "g" (0) (Grayscale) 0x19-0x19.7 (1)
0x010| 00 | . | color_type: "grayscale" (0) 0x19-0x19.7 (1)
0x010| 00 | . | compression_method: "deflate" (0) 0x1a-0x1a.7 (1)
0x010| 00 | . | filter_method: "Adaptive filtering" (0) 0x1b-0x1b.7 (1)
0x010| 00 | . | interlace_method: "No interlace" (0) 0x1c-0x1c.7 (1)
0x010| 00 | . | filter_method: "adaptive_filtering" (0) 0x1b-0x1b.7 (1)
0x010| 00 | . | interlace_method: "none" (0) 0x1c-0x1c.7 (1)
0x010| 81 8a a3| ...| crc: 0x818aa3d3 (valid) 0x1d-0x20.7 (4)
0x020|d3 |. |
| | | [1]{}: chunk 0x21-0x30.7 (16)

View File

@ -239,10 +239,10 @@ $ fq -d zip verbose /test0.zip
0x010|00 00 00 04 |.... | width: 4 0x10-0x13.7 (4)
0x010| 00 00 00 04 | .... | height: 4 0x14-0x17.7 (4)
0x010| 01 | . | bit_depth: 1 0x18-0x18.7 (1)
0x010| 00 | . | color_type: "g" (0) (Grayscale) 0x19-0x19.7 (1)
0x010| 00 | . | color_type: "grayscale" (0) 0x19-0x19.7 (1)
0x010| 00 | . | compression_method: "deflate" (0) 0x1a-0x1a.7 (1)
0x010| 00 | . | filter_method: "Adaptive filtering" (0) 0x1b-0x1b.7 (1)
0x010| 00 | . | interlace_method: "No interlace" (0) 0x1c-0x1c.7 (1)
0x010| 00 | . | filter_method: "adaptive_filtering" (0) 0x1b-0x1b.7 (1)
0x010| 00 | . | interlace_method: "none" (0) 0x1c-0x1c.7 (1)
0x010| 81 8a a3| ...| crc: 0x818aa3d3 (valid) 0x1d-0x20.7 (4)
0x020|d3 |. |
| | | [1]{}: chunk 0x21-0x30.7 (16)

View File

@ -239,10 +239,10 @@ $ fq -d zip verbose /test9.zip
0x010|00 00 00 04 |.... | width: 4 0x10-0x13.7 (4)
0x010| 00 00 00 04 | .... | height: 4 0x14-0x17.7 (4)
0x010| 01 | . | bit_depth: 1 0x18-0x18.7 (1)
0x010| 00 | . | color_type: "g" (0) (Grayscale) 0x19-0x19.7 (1)
0x010| 00 | . | color_type: "grayscale" (0) 0x19-0x19.7 (1)
0x010| 00 | . | compression_method: "deflate" (0) 0x1a-0x1a.7 (1)
0x010| 00 | . | filter_method: "Adaptive filtering" (0) 0x1b-0x1b.7 (1)
0x010| 00 | . | interlace_method: "No interlace" (0) 0x1c-0x1c.7 (1)
0x010| 00 | . | filter_method: "adaptive_filtering" (0) 0x1b-0x1b.7 (1)
0x010| 00 | . | interlace_method: "none" (0) 0x1c-0x1c.7 (1)
0x010| 81 8a a3| ...| crc: 0x818aa3d3 (valid) 0x1d-0x20.7 (4)
0x020|d3 |. |
| | | [1]{}: chunk 0x21-0x30.7 (16)