func NewRGBAM64(r image.Rectangle, m uint16) *RGBAM64 {
	w, h := r.Dx(), r.Dy()
	pix := make([]uint8, 8*w*h)
	model := npcolor.RGBAM64Model{M: m}
	return &RGBAM64{pix, 8 * w, r, model}
}
NewRGBAM64 returns a new RGBAM64 with the given bounds and maximum
channel value.
package netpbm
import (
	"bufio"
	"errors"
	"fmt"
	"image"
	"image/color"
	"io"
	"strconv"
	"strings"
	"github.com/spakin/netpbm/npcolor"
)
type pamTupleType int
const (
	pamBlackAndWhite pamTupleType = iota
	pamBlackAndWhiteAlpha
	pamGrayscale
	pamGrayscaleAlpha
	pamColor
	pamColorAlpha
)
var ttToInt = map[string]pamTupleType{
	"BLACKANDWHITE":       pamBlackAndWhite,
	"BLACKANDWHITE_ALPHA": pamBlackAndWhiteAlpha,
	"GRAYSCALE":           pamGrayscale,
	"GRAYSCALE_ALPHA":     pamGrayscaleAlpha,
	"RGB":                 pamColor,
	"RGB_ALPHA":           pamColorAlpha,
}
type RGBAM struct {
	Pix []uint8
	Stride int
	Rect image.Rectangle
	Model npcolor.RGBAMModel
}
func (p *RGBAM) ColorModel() color.Model { return p.Model }
func (p *RGBAM) Bounds() image.Rectangle { return p.Rect }
func (p *RGBAM) At(x, y int) color.Color {
	return p.RGBAMAt(x, y)
}
func (p *RGBAM) RGBAMAt(x, y int) npcolor.RGBAM {
	if !(image.Point{x, y}.In(p.Rect)) {
		return npcolor.RGBAM{}
	}
	i := p.PixOffset(x, y)
	return npcolor.RGBAM{
		R: p.Pix[i+0],
		G: p.Pix[i+1],
		B: p.Pix[i+2],
		A: p.Pix[i+3],
		M: p.Model.M,
	}
}
func (p *RGBAM) PixOffset(x, y int) int {
	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
}
func (p *RGBAM) Set(x, y int, c color.Color) {
	if !(image.Point{x, y}.In(p.Rect)) {
		return
	}
	i := p.PixOffset(x, y)
	c1 := p.Model.Convert(c).(npcolor.RGBAM)
	p.Pix[i+0] = c1.R
	p.Pix[i+1] = c1.G
	p.Pix[i+2] = c1.B
	p.Pix[i+3] = c1.A
}
func (p *RGBAM) SetRGBAM(x, y int, c npcolor.RGBAM) {
	if !(image.Point{x, y}.In(p.Rect)) {
		return
	}
	i := p.PixOffset(x, y)
	if c.M == p.Model.M {
		p.Pix[i+0] = c.R
		p.Pix[i+1] = c.G
		p.Pix[i+2] = c.B
		p.Pix[i+3] = c.A
	} else {
		p.Set(x, y, c)
	}
}
func (p *RGBAM) SubImage(r image.Rectangle) image.Image {
	r = r.Intersect(p.Rect)
	if r.Empty() {
		return &RGBAM{}
	}
	i := p.PixOffset(r.Min.X, r.Min.Y)
	return &RGBAM{
		Pix:    p.Pix[i:],
		Stride: p.Stride,
		Rect:   r,
	}
}
func (p *RGBAM) Opaque() bool {
	if p.Rect.Empty() {
		return true
	}
	i0, i1 := 3, p.Rect.Dx()*4
	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
		for i := i0; i < i1; i += 4 {
			if p.Pix[i] != 0xff {
				return false
			}
		}
		i0 += p.Stride
		i1 += p.Stride
	}
	return true
}
func (p *RGBAM) MaxValue() uint16 {
	return uint16(p.Model.M)
}
func (p *RGBAM) Format() Format {
	return PPM
}
func (p *RGBAM) HasAlpha() bool {
	return true
}
func NewRGBAM(r image.Rectangle, m uint8) *RGBAM {
	w, h := r.Dx(), r.Dy()
	pix := make([]uint8, 4*w*h)
	model := npcolor.RGBAMModel{M: m}
	return &RGBAM{pix, 4 * w, r, model}
}
type RGBAM64 struct {
	Pix []uint8
	Stride int
	Rect image.Rectangle
	Model npcolor.RGBAM64Model
}
func (p *RGBAM64) ColorModel() color.Model { return p.Model }
func (p *RGBAM64) Bounds() image.Rectangle { return p.Rect }
func (p *RGBAM64) At(x, y int) color.Color {
	return p.RGBAM64At(x, y)
}
func (p *RGBAM64) RGBAM64At(x, y int) npcolor.RGBAM64 {
	if !(image.Point{x, y}.In(p.Rect)) {
		return npcolor.RGBAM64{}
	}
	i := p.PixOffset(x, y)
	return npcolor.RGBAM64{
		R: uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
		G: uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
		B: uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
		A: uint16(p.Pix[i+6])<<8 | uint16(p.Pix[i+7]),
		M: p.Model.M,
	}
}
func (p *RGBAM64) PixOffset(x, y int) int {
	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
}
func (p *RGBAM64) Set(x, y int, c color.Color) {
	if !(image.Point{x, y}.In(p.Rect)) {
		return
	}
	i := p.PixOffset(x, y)
	c1 := p.Model.Convert(c).(npcolor.RGBAM64)
	p.Pix[i+0] = uint8(c1.R >> 8)
	p.Pix[i+1] = uint8(c1.R)
	p.Pix[i+2] = uint8(c1.G >> 8)
	p.Pix[i+3] = uint8(c1.G)
	p.Pix[i+4] = uint8(c1.B >> 8)
	p.Pix[i+5] = uint8(c1.B)
	p.Pix[i+6] = uint8(c1.A >> 8)
	p.Pix[i+7] = uint8(c1.A)
}
func (p *RGBAM64) SetRGBAM64(x, y int, c npcolor.RGBAM64) {
	if !(image.Point{x, y}.In(p.Rect)) {
		return
	}
	i := p.PixOffset(x, y)
	if c.M == p.Model.M {
		p.Pix[i+0] = uint8(c.R >> 8)
		p.Pix[i+1] = uint8(c.R)
		p.Pix[i+2] = uint8(c.G >> 8)
		p.Pix[i+3] = uint8(c.G)
		p.Pix[i+4] = uint8(c.B >> 8)
		p.Pix[i+5] = uint8(c.B)
		p.Pix[i+6] = uint8(c.A >> 8)
		p.Pix[i+7] = uint8(c.A)
	} else {
		p.Set(x, y, c)
	}
}
func (p *RGBAM64) SubImage(r image.Rectangle) image.Image {
	r = r.Intersect(p.Rect)
	if r.Empty() {
		return &RGBAM64{}
	}
	i := p.PixOffset(r.Min.X, r.Min.Y)
	return &RGBAM64{
		Pix:    p.Pix[i:],
		Stride: p.Stride,
		Rect:   r,
	}
}
func (p *RGBAM64) Opaque() bool {
	if p.Rect.Empty() {
		return true
	}
	i0, i1 := 6, p.Rect.Dx()*8
	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
		for i := i0; i < i1; i += 8 {
			if p.Pix[i+0] != 0xff || p.Pix[i+1] != 0xff {
				return false
			}
		}
		i0 += p.Stride
		i1 += p.Stride
	}
	return true
}
func (p *RGBAM64) MaxValue() uint16 {
	return uint16(p.Model.M)
}
func (p *RGBAM64) Format() Format {
	return PPM
}
func (p *RGBAM64) HasAlpha() bool {
	return true
}