1
0
mirror of https://github.com/golang/go synced 2024-11-18 04:04:49 -07:00

image/png: implement grayscale transparency.

Change-Id: Ib9309ee499fc51be2662d778430ee30089822e57
Reviewed-on: https://go-review.googlesource.com/32143
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Nigel Tao 2016-10-28 10:26:44 +11:00
parent bba1ac4fd9
commit caba0bd189
7 changed files with 350 additions and 43 deletions

View File

@ -259,7 +259,25 @@ func (d *decoder) parsePLTE(length uint32) error {
func (d *decoder) parsetRNS(length uint32) error {
switch d.cb {
case cbG1, cbG2, cbG4, cbG8, cbG16:
return UnsupportedError("grayscale transparency")
if length != 2 {
return FormatError("bad tRNS length")
}
n, err := io.ReadFull(d.r, d.tmp[:length])
if err != nil {
return err
}
d.crc.Write(d.tmp[:n])
copy(d.transparent[:], d.tmp[:length])
switch d.cb {
case cbG1:
d.transparent[1] *= 0xff
case cbG2:
d.transparent[1] *= 0x55
case cbG4:
d.transparent[1] *= 0x11
}
d.useTransparent = true
case cbTC8, cbTC16:
if length != 6 {
@ -413,8 +431,13 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
switch d.cb {
case cbG1, cbG2, cbG4, cbG8:
bitsPerPixel = d.depth
gray = image.NewGray(image.Rect(0, 0, width, height))
img = gray
if d.useTransparent {
nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
img = nrgba
} else {
gray = image.NewGray(image.Rect(0, 0, width, height))
img = gray
}
case cbGA8:
bitsPerPixel = 16
nrgba = image.NewNRGBA(image.Rect(0, 0, width, height))
@ -438,8 +461,13 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
img = nrgba
case cbG16:
bitsPerPixel = 16
gray16 = image.NewGray16(image.Rect(0, 0, width, height))
img = gray16
if d.useTransparent {
nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
img = nrgba64
} else {
gray16 = image.NewGray16(image.Rect(0, 0, width, height))
img = gray16
}
case cbGA16:
bitsPerPixel = 32
nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height))
@ -512,27 +540,75 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
// Convert from bytes to colors.
switch d.cb {
case cbG1:
for x := 0; x < width; x += 8 {
b := cdat[x/8]
for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
b <<= 1
if d.useTransparent {
ty := d.transparent[1]
for x := 0; x < width; x += 8 {
b := cdat[x/8]
for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
ycol := (b >> 7) * 0xff
acol := uint8(0xff)
if ycol == ty {
acol = 0x00
}
nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
b <<= 1
}
}
} else {
for x := 0; x < width; x += 8 {
b := cdat[x/8]
for x2 := 0; x2 < 8 && x+x2 < width; x2++ {
gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
b <<= 1
}
}
}
case cbG2:
for x := 0; x < width; x += 4 {
b := cdat[x/4]
for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
b <<= 2
if d.useTransparent {
ty := d.transparent[1]
for x := 0; x < width; x += 4 {
b := cdat[x/4]
for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
ycol := (b >> 6) * 0x55
acol := uint8(0xff)
if ycol == ty {
acol = 0x00
}
nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
b <<= 2
}
}
} else {
for x := 0; x < width; x += 4 {
b := cdat[x/4]
for x2 := 0; x2 < 4 && x+x2 < width; x2++ {
gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
b <<= 2
}
}
}
case cbG4:
for x := 0; x < width; x += 2 {
b := cdat[x/2]
for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
b <<= 4
if d.useTransparent {
ty := d.transparent[1]
for x := 0; x < width; x += 2 {
b := cdat[x/2]
for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
ycol := (b >> 4) * 0x11
acol := uint8(0xff)
if ycol == ty {
acol = 0x00
}
nrgba.SetNRGBA(x+x2, y, color.NRGBA{ycol, ycol, ycol, acol})
b <<= 4
}
}
} else {
for x := 0; x < width; x += 2 {
b := cdat[x/2]
for x2 := 0; x2 < 2 && x+x2 < width; x2++ {
gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
b <<= 4
}
}
}
case cbG8:
@ -551,7 +627,7 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
r := cdat[j+0]
g := cdat[j+1]
b := cdat[j+2]
a := byte(0xff)
a := uint8(0xff)
if r == tr && g == tg && b == tb {
a = 0x00
}
@ -625,9 +701,21 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image
copy(nrgba.Pix[pixOffset:], cdat)
pixOffset += nrgba.Stride
case cbG16:
for x := 0; x < width; x++ {
ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
gray16.SetGray16(x, y, color.Gray16{ycol})
if d.useTransparent {
ty := uint16(d.transparent[0])<<8 | uint16(d.transparent[1])
for x := 0; x < width; x++ {
ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
acol := uint16(0xffff)
if ycol == ty {
acol = 0x0000
}
nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
}
} else {
for x := 0; x < width; x++ {
ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
gray16.SetGray16(x, y, color.Gray16{ycol})
}
}
case cbGA16:
for x := 0; x < width; x++ {

View File

@ -39,15 +39,15 @@ var filenames = []string{
"basn4a16",
"basn6a08",
"basn6a16",
//"ftbbn0g01", // TODO: grayscale transparency.
//"ftbbn0g02", // TODO: grayscale transparency.
//"ftbbn0g04", // TODO: grayscale transparency.
"ftbbn0g01",
"ftbbn0g02",
"ftbbn0g04",
"ftbbn2c16",
"ftbbn3p08",
"ftbgn2c16",
"ftbgn3p08",
"ftbrn2c08",
//"ftbwn0g16", // TODO: grayscale transparency.
"ftbwn0g16",
"ftbwn3p08",
"ftbyn3p08",
"ftp0n0g08",
@ -96,6 +96,14 @@ var fakebKGDs = map[string]string{
"ftbyn3p08": "bKGD {index: 245}\n",
}
// fakegAMAs maps from filenames to fake gAMA chunks for our approximation to
// the sng command-line tool. Package png doesn't keep that metadata when
// png.Decode returns an image.Image.
var fakegAMAs = map[string]string{
"ftbbn0g01": "",
"ftbbn0g02": "gAMA {0.45455}\n",
}
// fakeIHDRUsings maps from filenames to fake IHDR "using" lines for our
// approximation to the sng command-line tool. The PNG model is that
// transparency (in the tRNS chunk) is separate to the color/grayscale/palette
@ -106,9 +114,13 @@ var fakebKGDs = map[string]string{
// can't otherwise discriminate PNG's "IHDR says color (with no alpha) but tRNS
// says alpha" and "IHDR says color with alpha".
var fakeIHDRUsings = map[string]string{
"ftbbn0g01": " using grayscale;\n",
"ftbbn0g02": " using grayscale;\n",
"ftbbn0g04": " using grayscale;\n",
"ftbbn2c16": " using color;\n",
"ftbgn2c16": " using color;\n",
"ftbrn2c08": " using color;\n",
"ftbwn0g16": " using grayscale;\n",
}
// An approximation of the sng command-line tool.
@ -163,7 +175,11 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
// We fake a gAMA chunk. The test files have a gAMA chunk but the go PNG
// parser ignores it (the PNG spec section 11.3 says "Ancillary chunks may
// be ignored by a decoder").
io.WriteString(w, "gAMA {1.0000}\n")
if s, ok := fakegAMAs[filename]; ok {
io.WriteString(w, s)
} else {
io.WriteString(w, "gAMA {1.0000}\n")
}
// Write the PLTE and tRNS (if applicable).
useTransparent := false
@ -209,14 +225,28 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
if c.A == 0 {
useTransparent = true
io.WriteString(w, "tRNS {\n")
fmt.Fprintf(w, " red: %d; green: %d; blue: %d;\n", c.R, c.G, c.B)
switch filename {
case "ftbbn0g01", "ftbbn0g02", "ftbbn0g04":
// The standard image package doesn't have a "gray with
// alpha" type. Instead, we use an image.NRGBA.
fmt.Fprintf(w, " gray: %d;\n", c.R)
default:
fmt.Fprintf(w, " red: %d; green: %d; blue: %d;\n", c.R, c.G, c.B)
}
io.WriteString(w, "}\n")
}
case color.NRGBA64:
if c.A == 0 {
useTransparent = true
io.WriteString(w, "tRNS {\n")
fmt.Fprintf(w, " red: %d; green: %d; blue: %d;\n", c.R, c.G, c.B)
switch filename {
case "ftbwn0g16":
// The standard image package doesn't have a "gray16 with
// alpha" type. Instead, we use an image.NRGBA64.
fmt.Fprintf(w, " gray: %d;\n", c.R)
default:
fmt.Fprintf(w, " red: %d; green: %d; blue: %d;\n", c.R, c.G, c.B)
}
io.WriteString(w, "}\n")
}
}
@ -249,19 +279,29 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
case cm == color.NRGBAModel:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
nrgba := png.At(x, y).(color.NRGBA)
if useTransparent {
fmt.Fprintf(w, "%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B)
} else {
fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
switch filename {
case "ftbbn0g01", "ftbbn0g02", "ftbbn0g04":
fmt.Fprintf(w, "%02x", nrgba.R)
default:
if useTransparent {
fmt.Fprintf(w, "%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B)
} else {
fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
}
}
}
case cm == color.NRGBA64Model:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
nrgba64 := png.At(x, y).(color.NRGBA64)
if useTransparent {
fmt.Fprintf(w, "%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B)
} else {
fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
switch filename {
case "ftbwn0g16":
fmt.Fprintf(w, "%04x ", nrgba64.R)
default:
if useTransparent {
fmt.Fprintf(w, "%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B)
} else {
fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
}
}
}
case cpm != nil:

View File

@ -14,7 +14,7 @@ basn3a08.png was generated from basn6a08.png using the pngnq tool, which
converted it to the 8-bit paletted image with alpha values in tRNS chunk.
The *.sng files in this directory were generated from the *.png files by the
sng command-line tool and some hand editing. The files basn0g0{1,2,4}.sng were
actually generated by first converting the PNG to a bitdepth of 8 and then
running sng on them. basn4a08.sng was generated from a 16-bit rgba version of
basn4a08.png rather than the original gray + alpha.
sng command-line tool and some hand editing. The files basn0g0{1,2,4}.sng and
ftbbn0g0{1,2,4}.sng were actually generated by first converting the PNG to a
bitdepth of 8 and then running sng on them. basn4a08.sng was generated from a
16-bit rgba version of basn4a08.png rather than the original gray + alpha.

View File

@ -0,0 +1,44 @@
#SNG: from ftbbn0g01.png
IHDR {
width: 32; height: 32; bitdepth: 8;
using grayscale;
}
bKGD {gray: 0;}
tRNS {
gray: 0;
}
IMAGE {
pixels hex
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00ffffffffffffff000000000000000000000000000000000000000000000000
00ffffffffffffffff0000000000000000000000000000000000000000000000
00ffffffffffffffffff00000000000000000000000000000000000000000000
00ffffff0000ffffffff00000000000000000000000000000000000000000000
00ffffff000000ffffff00000000000000000000000000000000000000000000
00ffffff000000ffffff00ffffff000000ffffff000000000000000000000000
00ffffff00ffffffffff00ffffff000000ffffff000000000000000000000000
00ffffffffffffffffff00ffffffff0000ffffff000000000000000000000000
00ffffffffffffffff0000ffffffff0000ffffff000000000000000000000000
00ffffffffff0000000000ffffffffff00ffffff000000000000000000000000
00ffffff00000000000000ffffffffff00ffffff0000000000ffffffffff0000
00ffffff00000000000000ffffffffffffffffff000000ffffffffffffffff00
00ffffff00000000000000ffffffffffffffffff000000ffffffffffffffff00
00ffffff00000000000000ffffffffffffffffff0000ffffffffff00ffffff00
0000000000000000000000ffffff00ffffffffff0000ffffffff000000000000
0000000000000000000000ffffff00ffffffffff0000ffffff00000000000000
0000000000000000000000ffffff0000ffffffff0000ffffff0000ffffff0000
0000000000000000000000ffffff000000ffffff0000ffffff00ffffffffff00
0000000000000000000000ffffff000000ffffff0000ffffff0000ffffffff00
00000000000000000000000000000000000000000000ffffff00000000ffff00
00000000000000000000000000000000000000000000ffffffff0000ffffff00
00000000000000000000000000000000000000000000ffffffffffffffffff00
0000000000000000000000000000000000000000000000ffffffffffffffff00
000000000000000000000000000000000000000000000000ffffffffffff0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
}

View File

@ -0,0 +1,45 @@
#SNG: from ftbbn0g02.png
IHDR {
width: 32; height: 32; bitdepth: 8;
using grayscale;
}
gAMA {0.45455}
bKGD {gray: 0;}
tRNS {
gray: 0;
}
IMAGE {
pixels hex
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00aaaaaaaaaaaaaa000000000000000000000000000000000000000000000000
00aaaaaaaaaaaaaaaa0000000000000000000000000000000000000000000000
00aaaaaaaaaaaaaaaaaa00000000000000000000000000000000000000000000
00aaaaaa0000aaaaaaaa00000000000000000000000000000000000000000000
00aaaaaa000000aaaaaa00000000000000000000000000000000000000000000
00aaaaaa000000aaaaaa00aaaaaa000000aaaaaa000000000000000000000000
00aaaaaa00aaaaaaaaaa00aaaaaa000000aaaaaa000000000000000000000000
00aaaaaaaaaaaaaaaaaa00aaaaaaaa0000aaaaaa000000000000000000000000
00aaaaaaaaaaaaaaaa0000aaaaaaaa0000aaaaaa000000000000000000000000
00aaaaaaaaaa0000000000aaaaaaaaaa00aaaaaa000000000000000000000000
00aaaaaa00000000000000aaaaaaaaaa00aaaaaa0000000000aaaaaaaaaa0000
00aaaaaa00000000000000aaaaaaaaaaaaaaaaaa000000aaaaaaaaaaaaaaaa00
00aaaaaa00000000000000aaaaaaaaaaaaaaaaaa000000aaaaaaaaaaaaaaaa00
00aaaaaa00000000000000aaaaaaaaaaaaaaaaaa0000aaaaaaaaaa00aaaaaa00
0000000000000000000000aaaaaa00aaaaaaaaaa0000aaaaaaaa000000000000
0000000000000000000000aaaaaa00aaaaaaaaaa0000aaaaaa00000000000000
0000000000000000000000aaaaaa0000aaaaaaaa0000aaaaaa0000aaaaaa0000
0000000000000000000000aaaaaa000000aaaaaa0000aaaaaa00aaaaaaaaaa00
0000000000000000000000aaaaaa000000aaaaaa0000aaaaaa0000aaaaaaaa00
00000000000000000000000000000000000000000000aaaaaa00000000aaaa00
00000000000000000000000000000000000000000000aaaaaaaa0000aaaaaa00
00000000000000000000000000000000000000000000aaaaaaaaaaaaaaaaaa00
0000000000000000000000000000000000000000000000aaaaaaaaaaaaaaaa00
000000000000000000000000000000000000000000000000aaaaaaaaaaaa0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
}

View File

@ -0,0 +1,45 @@
#SNG: from ftbbn0g04.png
IHDR {
width: 32; height: 32; bitdepth: 8;
using grayscale;
}
gAMA {1.0000}
bKGD {gray: 0;}
tRNS {
gray: 255;
}
IMAGE {
pixels hex
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffddcceeffffffffffffffffffffffffffffff
ffffffffffffffffffffffeebb776655446699ddffffffffffffffffffffffff
ffffffffffffffffeebb886666553322222222335599ccffffffffffffffffff
ffffffffffeecc997766554433333322334422112222336699ccffffffffffff
ffffffcc997777664433333333444433334444332233335566777799cceeffff
ffffcc777777775533333344556655444444444444332266777777776699ffff
ffffdd8888887766444466777777777766555555445566777777775555bbffff
ffffee8888888888777777777777777777777777777777777766555544eeffff
ffffff8866667788998888777777777777777777777777665555444455ffffff
ffffff8866778888999999998877777777777777777755331111334488ffffff
ffffff99667788889999999999998877777777776655221111111133aaffffff
ffffff99666688888899997777999999887766555533221111001122ddffffff
ffffffaa666677888899886666669999997755554422111122111144ffffffff
ffffffbb666666888888777755669999997755552222113344223377ffffffff
ffffffcc666655778877777755779999996655332211334422111199ffffffff
ffffffdd6666446688557777557799999966552222113311111111ccffffffff
ffffffee6666555588666677557799999966442211222211111122eeffffffff
ffffffff6666555577775577557799999955332211332211111155ffffffffff
ffffffff6666665566775577557799999955331111443311111188ffffffffff
ffffffff88666655667755665577999988552211114433111111ccffffffffff
ffffffffffaa66666666666655779999885522111133111122bbffffffffffff
ffffffffffffcc6666666666557788998855221111111122ccffffffffffffff
ffffffffffffffee886666665577888877553311111133ddffffffffffffffff
ffffffffffffffffffaa666655778888775544221144eeffffffffffffffffff
ffffffffffffffffffffcc77557788886655553377ffffffffffffffffffffff
ffffffffffffffffffffffee9988888866555599ffffffffffffffffffffffff
ffffffffffffffffffffffffffbb88886655bbffffffffffffffffffffffffff
ffffffffffffffffffffffffffffdd8866ccffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffeeddffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
}

View File

@ -0,0 +1,45 @@
#SNG: from ftbwn0g16.png
IHDR {
width: 32; height: 32; bitdepth: 16;
using grayscale;
}
gAMA {1.0000}
bKGD {gray: 65535;}
tRNS {
gray: 65535;
}
IMAGE {
pixels hex
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff e3e3 c9c9 f1f1 ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff e8e8 b5b5 7e7e 6565 5ab9 462f 60f8 a111 e210 ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff eeee bfbf 8989 6767 6190 4cba 3614 2a50 27e9 23b5 279c 2eea 5049 914b d4b7 fcfc ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff f2f2 c4c4 9595 7272 6c9e 5392 3da0 2d6a 2fb7 2b83 2669 2aa7 3cc7 22c2 1801 1ab5 27e9 3008 6c66 a0a0 cfcf f8f8 ffff ffff ffff ffff ffff
ffff ffff f7f7 caca 9a9a 7676 7373 66aa 48e3 3109 2f6a 32b6 34d0 3c50 3e1d 3784 3151 3b9b 4578 337b 26b6 2d03 2ae9 5a87 6e6e 7373 7676 9b9b c4c4 eeee ffff ffff
ffff ffff cccc 7f7f 7676 7575 7575 4e17 3737 3603 369d 3c5c 553c 641e 5026 419f 43d1 47b7 4551 416a 3e1e 37d0 2636 6c9e 7575 7575 7575 7575 6a6a 9a9a ffff ffff
ffff ffff dcdc 8585 8888 8484 7b7b 6308 4449 471f 61ea 765b 7777 7777 7777 7205 60c3 56bd 5214 4e5d 4b15 4daa 62d9 7777 7777 7777 7070 5c5c 5252 bdbd ffff ffff
ffff ffff eaea 8484 8181 8749 8e8e 8989 7f7f 7979 7979 7979 7979 7979 7979 7979 7979 7979 7979 7979 7979 7979 7979 7979 7676 6363 5454 5050 4c4c e6e6 ffff ffff
ffff ffff f8f8 8271 6847 62d4 783c 90d8 9393 8f8f 8383 7b7b 7b7b 7b7b 7b7b 7b7b 7b7b 7b7b 7b7b 7b7b 7a7a 7a7a 7979 6a6a 5757 5050 4c4c 4949 5959 ffff ffff ffff
ffff ffff ffff 8a8a 69d4 749a 8e83 901d 9292 9595 9797 9494 8787 7c7c 7c7c 7c7c 7c7c 7c7c 7c7c 7c7c 7c7c 7171 5b0b 32d9 1474 1876 2dac 46bc 8282 ffff ffff ffff
ffff ffff ffff 9292 69ae 6f4d 8fb1 8f6d 9191 9494 9797 9999 9b9b 9999 8b8b 7f7f 7e7e 7e7e 7d7d 7777 6262 54d2 25d7 1773 10c8 0c12 0bd7 2f1b acac ffff ffff ffff
ffff ffff ffff 9494 67f1 6a00 8517 8fb1 905f 9393 9371 7a19 7f65 97fa 9e9e 9c9c 8e8e 7e7e 6a6a 5a5a 57af 2ce6 1b97 1264 0cd0 07e7 0b27 2403 d6d6 ffff ffff ffff
ffff ffff ffff a4a4 6735 641d 75c7 8fb1 8f71 9292 8400 6eb6 6386 6e32 9d9d 9f9f a0a0 7a7a 5a5a 5959 3e11 1d50 16c2 0d21 1a5d 0d15 1470 3dfd fbfb ffff ffff ffff
ffff ffff ffff b6b6 660f 5f67 65e1 8a64 8e79 909a 7e27 765e 5a1a 6efc 9c9c 9e9e 9f9f 7474 5959 52f5 209b 1b97 0f8a 39d4 4848 1a1c 2fff 7272 ffff ffff ffff ffff
ffff ffff ffff c7c7 647e 683c 5309 7bab 8f1a 7ad2 7588 7531 5983 7079 9b9b 9d9d 9e9e 6e6e 5959 3a1c 1d50 1315 2b1f 44a4 220a 1247 1136 9d2f ffff ffff ffff ffff
ffff ffff ffff d8d8 6358 683c 486f 6c5b 8dec 5b67 745a 749a 58ec 6fe2 9a9a 9b9b 9d9d 6767 5792 235c 1b97 0fdb 37af 16c6 1229 0e41 163f c7c7 ffff ffff ffff ffff
ffff ffff ffff eaea 61c7 65e1 4e53 5d3f 818e 6258 6809 72d6 5855 7020 9898 9a9a 9c9c 6161 4945 1d50 1544 21ce 1bf3 0e23 0c4d 0c4d 22c7 f4f4 ffff ffff ffff ffff
ffff ffff ffff fcfc 60cd 6386 57bf 58c1 71a8 7403 56fb 71a8 54cd 7484 9797 9999 9a9a 5a5a 3914 1c47 0f68 3352 1bbe 0d28 0d38 11d2 5153 ffff ffff ffff ffff ffff
ffff ffff ffff ffff 6ee2 6094 6094 5535 6978 7cd8 51db 707a 539f 7383 9595 9797 9696 5757 2beb 1985 0bf5 40a0 2b2b 1732 1493 0c4d 87e7 ffff ffff ffff ffff ffff
ffff ffff ffff ffff 8c8c 5f1f 67a5 51a6 68e2 76f5 58ec 6eb6 5272 71eb 9393 9595 8f8f 5656 225f 1544 0e64 4747 3547 129f 120c 121e c5c5 ffff ffff ffff ffff ffff
ffff ffff ffff ffff fafa a368 63e7 6325 6782 698c 6678 6cf2 51db 757b 9191 9393 8989 5555 1c33 120c 119a 38cd 155f 1459 1ff7 b666 ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff d0d0 6d6d 6565 66e3 68d3 6b2e 50ae 7522 8f8f 9191 8181 5555 2127 0f2d 0c80 1010 10ab 2589 cf09 ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ecec 8686 667a 670e 6969 5017 7320 8d8d 8f8f 7a7a 5454 2f81 0e14 0b7f 0b61 31c8 e090 ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff fcfc aaaa 6735 67a5 4ee9 739b 8b8b 8d8d 7474 5353 3d3d 1b23 1342 4c38 ee28 ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff d4c3 7285 58c1 7fd8 8888 8b8b 6d6d 5252 4f4f 3737 7777 fafa ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff efef a0a0 8383 8686 8888 6767 5151 5050 a0a0 fdfd ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff fefe c0c0 8585 8686 6161 5252 b7b7 ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff dede 9090 6565 cccc ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff f5f5 e3e3 ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
}