func Pixel(x, y int, img *image.RGBA64, wg *sync.WaitGroup) { var r, g, b, a uint64 for i := 0; i < *spp; i++ { for j := 0; j < *spp; j++ { X := (float64(x)+float64(i)/float64(*spp))/float64(*ppp) - float64(*ppi)/2 Y := float64(*ppi)/2 - (float64(y)+float64(j)/float64(*spp))/float64(*ppp) c := Ray(X+*basex, Y+*basey, *basez, X/float64(*ppi)*epsilon, Y/float64(*ppi)*epsilon, epsilon, farZ) r += uint64(c.R) g += uint64(c.G) b += uint64(c.B) a += uint64(c.A) } } img.SetRGBA64(x, y, color.RGBA64{ uint16(r / uint64(*spp) / uint64(*spp)), uint16(g / uint64(*spp) / uint64(*spp)), uint16(b / uint64(*spp) / uint64(*spp)), uint16(a / uint64(*spp) / uint64(*spp)), }) wg.Done() }
func resizeNRGBA64(in *image.NRGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 for x := newBounds.Min.X; x < newBounds.Max.X; x++ { row := in.Pix[x*in.Stride:] for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { var rgba [4]int64 var sum int64 start := offset[y] ci := y * filterLength for i := 0; i < filterLength; i++ { coeff := coeffs[ci+i] if coeff != 0 { xi := start + i switch { case uint(xi) < uint(maxX): xi *= 8 case xi >= maxX: xi = 8 * maxX default: xi = 0 } // Forward alpha-premultiplication a := int64(uint16(row[xi+6])<<8 | uint16(row[xi+7])) r := int64(uint16(row[xi+0])<<8|uint16(row[xi+1])) * a r /= 0xffff g := int64(uint16(row[xi+2])<<8|uint16(row[xi+3])) * a g /= 0xffff b := int64(uint16(row[xi+4])<<8|uint16(row[xi+5])) * a b /= 0xffff rgba[0] += int64(coeff) * r rgba[1] += int64(coeff) * g rgba[2] += int64(coeff) * b rgba[3] += int64(coeff) * a sum += int64(coeff) } } xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 value := clampUint16(rgba[0] / sum) out.Pix[xo+0] = uint8(value >> 8) out.Pix[xo+1] = uint8(value) value = clampUint16(rgba[1] / sum) out.Pix[xo+2] = uint8(value >> 8) out.Pix[xo+3] = uint8(value) value = clampUint16(rgba[2] / sum) out.Pix[xo+4] = uint8(value >> 8) out.Pix[xo+5] = uint8(value) value = clampUint16(rgba[3] / sum) out.Pix[xo+6] = uint8(value >> 8) out.Pix[xo+7] = uint8(value) } } }
func newAtFuncRGBA64(p *image.RGBA64) AtFunc { return func(x, y int) (r, g, b, a uint32) { i := p.PixOffset(x, y) r = uint32(p.Pix[i+0])<<8 | uint32(p.Pix[i+1]) g = uint32(p.Pix[i+2])<<8 | uint32(p.Pix[i+3]) b = uint32(p.Pix[i+4])<<8 | uint32(p.Pix[i+5]) a = uint32(p.Pix[i+6])<<8 | uint32(p.Pix[i+7]) return } }
func convertRGBA64(dest *Image, src *image.RGBA64) { var x, y, i, si int for x = dest.Rect.Min.X; x < dest.Rect.Max.X; x++ { for y = dest.Rect.Min.Y; y < dest.Rect.Max.Y; y++ { si = src.PixOffset(x, y) i = dest.PixOffset(x, y) dest.Pix[i+0] = src.Pix[si+4] dest.Pix[i+1] = src.Pix[si+2] dest.Pix[i+2] = src.Pix[si+0] dest.Pix[i+3] = src.Pix[si+6] } } }
func (s *Server) decodeRawEncoding(r io.Reader, rect *image.RGBA64) error { for y := rect.Rect.Min.Y; y < rect.Rect.Max.Y; y++ { for x := rect.Rect.Min.X; x < rect.Rect.Max.X; x++ { pixel, err := s.readPixel(r) if err != nil { log.Println("error reading pixel %d, %d", x, y) return err } rect.Set(x, y, pixel) } } return nil }
func newSetFuncRGBA64(p *image.RGBA64) SetFunc { return func(x, y int, r, g, b, a uint32) { i := p.PixOffset(x, y) r16, g16, b16, a16 := uint16(r), uint16(g), uint16(b), uint16(a) p.Pix[i+0] = uint8(r16 >> 8) p.Pix[i+1] = uint8(r16) p.Pix[i+2] = uint8(g16 >> 8) p.Pix[i+3] = uint8(g16) p.Pix[i+4] = uint8(b16 >> 8) p.Pix[i+5] = uint8(b16) p.Pix[i+6] = uint8(a16 >> 8) p.Pix[i+7] = uint8(a16) } }
func resizeGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 for x := newBounds.Min.X; x < newBounds.Max.X; x++ { for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { var rgba [4]int64 var sum int64 start := offset[y] ci := y * filterLength for i := 0; i < filterLength; i++ { coeff := coeffs[ci+i] if coeff != 0 { xi := start + i switch { case xi < 0: xi = 0 case xi >= maxX: xi = maxX } r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA() rgba[0] += int64(coeff) * int64(r) rgba[1] += int64(coeff) * int64(g) rgba[2] += int64(coeff) * int64(b) rgba[3] += int64(coeff) * int64(a) sum += int64(coeff) } } offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 value := clampUint16(rgba[0] / sum) out.Pix[offset+0] = uint8(value >> 8) out.Pix[offset+1] = uint8(value) value = clampUint16(rgba[1] / sum) out.Pix[offset+2] = uint8(value >> 8) out.Pix[offset+3] = uint8(value) value = clampUint16(rgba[2] / sum) out.Pix[offset+4] = uint8(value >> 8) out.Pix[offset+5] = uint8(value) value = clampUint16(rgba[3] / sum) out.Pix[offset+6] = uint8(value >> 8) out.Pix[offset+7] = uint8(value) } } }
func resizeRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 for x := newBounds.Min.X; x < newBounds.Max.X; x++ { row := in.Pix[x*in.Stride:] for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { var rgba [4]int64 var sum int64 start := offset[y] ci := (y - newBounds.Min.Y) * filterLength for i := 0; i < filterLength; i++ { coeff := coeffs[ci+i] if coeff != 0 { xi := start + i switch { case xi < 0: xi = 0 case xi >= maxX: xi = 8 * maxX default: xi *= 8 } rgba[0] += int64(coeff) * int64(uint16(row[xi+0])<<8|uint16(row[xi+1])) rgba[1] += int64(coeff) * int64(uint16(row[xi+2])<<8|uint16(row[xi+3])) rgba[2] += int64(coeff) * int64(uint16(row[xi+4])<<8|uint16(row[xi+5])) rgba[3] += int64(coeff) * int64(uint16(row[xi+6])<<8|uint16(row[xi+7])) sum += int64(coeff) } } xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 value := clampUint16(rgba[0] / sum) out.Pix[xo+0] = uint8(value >> 8) out.Pix[xo+1] = uint8(value) value = clampUint16(rgba[1] / sum) out.Pix[xo+2] = uint8(value >> 8) out.Pix[xo+3] = uint8(value) value = clampUint16(rgba[2] / sum) out.Pix[xo+4] = uint8(value >> 8) out.Pix[xo+5] = uint8(value) value = clampUint16(rgba[3] / sum) out.Pix[xo+6] = uint8(value >> 8) out.Pix[xo+7] = uint8(value) } } }
func nearestRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 for x := newBounds.Min.X; x < newBounds.Max.X; x++ { row := in.Pix[x*in.Stride:] for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { var rgba [4]float32 var sum float32 start := offset[y] ci := y * filterLength for i := 0; i < filterLength; i++ { if coeffs[ci+i] { xi := start + i switch { case uint(xi) < uint(maxX): xi *= 8 case xi >= maxX: xi = 8 * maxX default: xi = 0 } rgba[0] += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) rgba[1] += float32(uint16(row[xi+2])<<8 | uint16(row[xi+3])) rgba[2] += float32(uint16(row[xi+4])<<8 | uint16(row[xi+5])) rgba[3] += float32(uint16(row[xi+6])<<8 | uint16(row[xi+7])) sum++ } } xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 value := floatToUint16(rgba[0] / sum) out.Pix[xo+0] = uint8(value >> 8) out.Pix[xo+1] = uint8(value) value = floatToUint16(rgba[1] / sum) out.Pix[xo+2] = uint8(value >> 8) out.Pix[xo+3] = uint8(value) value = floatToUint16(rgba[2] / sum) out.Pix[xo+4] = uint8(value >> 8) out.Pix[xo+5] = uint8(value) value = floatToUint16(rgba[3] / sum) out.Pix[xo+6] = uint8(value >> 8) out.Pix[xo+7] = uint8(value) } } }
func nearestGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) { newBounds := out.Bounds() maxX := in.Bounds().Dx() - 1 for x := newBounds.Min.X; x < newBounds.Max.X; x++ { for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { var rgba [4]float32 var sum float32 start := offset[y] ci := (y - newBounds.Min.Y) * filterLength for i := 0; i < filterLength; i++ { if coeffs[ci+i] { xi := start + i switch { case xi < 0: xi = 0 case xi >= maxX: xi = maxX } r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA() rgba[0] += float32(r) rgba[1] += float32(g) rgba[2] += float32(b) rgba[3] += float32(a) sum++ } } offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 value := floatToUint16(rgba[0] / sum) out.Pix[offset+0] = uint8(value >> 8) out.Pix[offset+1] = uint8(value) value = floatToUint16(rgba[1] / sum) out.Pix[offset+2] = uint8(value >> 8) out.Pix[offset+3] = uint8(value) value = floatToUint16(rgba[2] / sum) out.Pix[offset+4] = uint8(value >> 8) out.Pix[offset+5] = uint8(value) value = floatToUint16(rgba[3] / sum) out.Pix[offset+6] = uint8(value >> 8) out.Pix[offset+7] = uint8(value) } } }
// Resize a rectangle image slice func resizeSlice(input image.Image, output *image.RGBA64, interp InterpolationFunction, scale, adjust, offset float32, slice image.Rectangle, c chan int) { filter := interp(input, float32(clampFactor(scale))) var u float32 var color color.RGBA64 for y := slice.Min.Y; y < slice.Max.Y; y++ { u = scale*(float32(y)+adjust) + offset filter.SetKernelWeights(u) for x := slice.Min.X; x < slice.Max.X; x++ { color = filter.Interpolate(u, x) i := output.PixOffset(x, y) output.Pix[i+0] = uint8(color.R >> 8) output.Pix[i+1] = uint8(color.R) output.Pix[i+2] = uint8(color.G >> 8) output.Pix[i+3] = uint8(color.G) output.Pix[i+4] = uint8(color.B >> 8) output.Pix[i+5] = uint8(color.B) output.Pix[i+6] = uint8(color.A >> 8) output.Pix[i+7] = uint8(color.A) } } c <- 1 }
// decode decodes the IDAT data into an image. func (d *decoder) decode() (image.Image, error) { r, err := zlib.NewReader(d) if err != nil { return nil, err } defer r.Close() bitsPerPixel := 0 pixOffset := 0 var ( gray *image.Gray rgba *image.RGBA paletted *image.Paletted nrgba *image.NRGBA gray16 *image.Gray16 rgba64 *image.RGBA64 nrgba64 *image.NRGBA64 img image.Image ) switch d.cb { case cbG1, cbG2, cbG4, cbG8: bitsPerPixel = d.depth gray = image.NewGray(image.Rect(0, 0, d.width, d.height)) img = gray case cbGA8: bitsPerPixel = 16 nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height)) img = nrgba case cbTC8: bitsPerPixel = 24 rgba = image.NewRGBA(image.Rect(0, 0, d.width, d.height)) img = rgba case cbP1, cbP2, cbP4, cbP8: bitsPerPixel = d.depth paletted = image.NewPaletted(image.Rect(0, 0, d.width, d.height), d.palette) img = paletted case cbTCA8: bitsPerPixel = 32 nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height)) img = nrgba case cbG16: bitsPerPixel = 16 gray16 = image.NewGray16(image.Rect(0, 0, d.width, d.height)) img = gray16 case cbGA16: bitsPerPixel = 32 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height)) img = nrgba64 case cbTC16: bitsPerPixel = 48 rgba64 = image.NewRGBA64(image.Rect(0, 0, d.width, d.height)) img = rgba64 case cbTCA16: bitsPerPixel = 64 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height)) img = nrgba64 } bytesPerPixel := (bitsPerPixel + 7) / 8 // cr and pr are the bytes for the current and previous row. // The +1 is for the per-row filter type, which is at cr[0]. cr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8) pr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8) for y := 0; y < d.height; y++ { // Read the decompressed bytes. _, err := io.ReadFull(r, cr) if err != nil { return nil, err } // Apply the filter. cdat := cr[1:] pdat := pr[1:] switch cr[0] { case ftNone: // No-op. case ftSub: for i := bytesPerPixel; i < len(cdat); i++ { cdat[i] += cdat[i-bytesPerPixel] } case ftUp: for i, p := range pdat { cdat[i] += p } case ftAverage: for i := 0; i < bytesPerPixel; i++ { cdat[i] += pdat[i] / 2 } for i := bytesPerPixel; i < len(cdat); i++ { cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2) } case ftPaeth: filterPaeth(cdat, pdat, bytesPerPixel) default: return nil, FormatError("bad filter type") } // Convert from bytes to colors. switch d.cb { case cbG1: for x := 0; x < d.width; x += 8 { b := cdat[x/8] for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ { gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff}) b <<= 1 } } case cbG2: for x := 0; x < d.width; x += 4 { b := cdat[x/4] for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ { gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55}) b <<= 2 } } case cbG4: for x := 0; x < d.width; x += 2 { b := cdat[x/2] for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ { gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11}) b <<= 4 } } case cbG8: copy(gray.Pix[pixOffset:], cdat) pixOffset += gray.Stride case cbGA8: for x := 0; x < d.width; x++ { ycol := cdat[2*x+0] nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]}) } case cbTC8: pix, i, j := rgba.Pix, pixOffset, 0 for x := 0; x < d.width; x++ { pix[i+0] = cdat[j+0] pix[i+1] = cdat[j+1] pix[i+2] = cdat[j+2] pix[i+3] = 0xff i += 4 j += 3 } pixOffset += rgba.Stride case cbP1: for x := 0; x < d.width; x += 8 { b := cdat[x/8] for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ { idx := b >> 7 if len(paletted.Palette) <= int(idx) { paletted.Palette = paletted.Palette[:int(idx)+1] } paletted.SetColorIndex(x+x2, y, idx) b <<= 1 } } case cbP2: for x := 0; x < d.width; x += 4 { b := cdat[x/4] for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ { idx := b >> 6 if len(paletted.Palette) <= int(idx) { paletted.Palette = paletted.Palette[:int(idx)+1] } paletted.SetColorIndex(x+x2, y, idx) b <<= 2 } } case cbP4: for x := 0; x < d.width; x += 2 { b := cdat[x/2] for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ { idx := b >> 4 if len(paletted.Palette) <= int(idx) { paletted.Palette = paletted.Palette[:int(idx)+1] } paletted.SetColorIndex(x+x2, y, idx) b <<= 4 } } case cbP8: if len(paletted.Palette) != 255 { for x := 0; x < d.width; x++ { if len(paletted.Palette) <= int(cdat[x]) { paletted.Palette = paletted.Palette[:int(cdat[x])+1] } } } copy(paletted.Pix[pixOffset:], cdat) pixOffset += paletted.Stride case cbTCA8: copy(nrgba.Pix[pixOffset:], cdat) pixOffset += nrgba.Stride case cbG16: for x := 0; x < d.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 < d.width; x++ { ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1]) acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3]) nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol}) } case cbTC16: for x := 0; x < d.width; x++ { rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff}) } case cbTCA16: for x := 0; x < d.width; x++ { rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1]) gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3]) bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5]) acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7]) nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol}) } } // The current row for y is the previous row for y+1. pr, cr = cr, pr } // Check for EOF, to verify the zlib checksum. n, err := r.Read(pr[:1]) if err != io.EOF { return nil, FormatError(err.Error()) } if n != 0 || d.idatLength != 0 { return nil, FormatError("too much pixel data") } return img, nil }
// readImagePass reads a single image pass, sized according to the pass number. func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image.Image, error) { var bitsPerPixel int = 0 pixOffset := 0 var ( gray *image.Gray rgba *image.RGBA paletted *image.Paletted nrgba *image.NRGBA gray16 *image.Gray16 rgba64 *image.RGBA64 nrgba64 *image.NRGBA64 img image.Image ) width, height := d.width, d.height if d.interlace == itAdam7 && !allocateOnly { p := interlacing[pass] // Add the multiplication factor and subtract one, effectively rounding up. width = (width - p.xOffset + p.xFactor - 1) / p.xFactor height = (height - p.yOffset + p.yFactor - 1) / p.yFactor // A PNG image can't have zero width or height, but for an interlaced // image, an individual pass might have zero width or height. If so, we // shouldn't even read a per-row filter type byte, so return early. if width == 0 || height == 0 { return nil, nil } } switch d.cb { case cbG1, cbG2, cbG4, cbG8: bitsPerPixel = d.depth gray = image.NewGray(image.Rect(0, 0, width, height)) img = gray case cbGA8: bitsPerPixel = 16 nrgba = image.NewNRGBA(image.Rect(0, 0, width, height)) img = nrgba case cbTC8: bitsPerPixel = 24 rgba = image.NewRGBA(image.Rect(0, 0, width, height)) img = rgba case cbP1, cbP2, cbP4, cbP8: bitsPerPixel = d.depth paletted = image.NewPaletted(image.Rect(0, 0, width, height), d.palette) img = paletted case cbTCA8: bitsPerPixel = 32 nrgba = image.NewNRGBA(image.Rect(0, 0, width, height)) img = nrgba case cbG16: bitsPerPixel = 16 gray16 = image.NewGray16(image.Rect(0, 0, width, height)) img = gray16 case cbGA16: bitsPerPixel = 32 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height)) img = nrgba64 case cbTC16: bitsPerPixel = 48 rgba64 = image.NewRGBA64(image.Rect(0, 0, width, height)) img = rgba64 case cbTCA16: bitsPerPixel = 64 nrgba64 = image.NewNRGBA64(image.Rect(0, 0, width, height)) img = nrgba64 } if allocateOnly { return img, nil } bytesPerPixel := (bitsPerPixel + 7) / 8 // The +1 is for the per-row filter type, which is at cr[0]. rowSize := 1 + (bitsPerPixel*width+7)/8 // cr and pr are the bytes for the current and previous row. cr := make([]uint8, rowSize) pr := make([]uint8, rowSize) for y := 0; y < height; y++ { // Read the decompressed bytes. _, err := io.ReadFull(r, cr) if err != nil { if err == io.EOF || err == io.ErrUnexpectedEOF { return nil, FormatError("not enough pixel data") } return nil, err } // Apply the filter. cdat := cr[1:] pdat := pr[1:] switch cr[0] { case ftNone: // No-op. case ftSub: for i := bytesPerPixel; i < len(cdat); i++ { cdat[i] += cdat[i-bytesPerPixel] } case ftUp: for i, p := range pdat { cdat[i] += p } case ftAverage: // The first column has no column to the left of it, so it is a // special case. We know that the first column exists because we // check above that width != 0, and so len(cdat) != 0. for i := 0; i < bytesPerPixel; i++ { cdat[i] += pdat[i] / 2 } for i := bytesPerPixel; i < len(cdat); i++ { cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2) } case ftPaeth: filterPaeth(cdat, pdat, bytesPerPixel) default: return nil, FormatError("bad filter type") } // 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 } } 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 } } 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 } } case cbG8: copy(gray.Pix[pixOffset:], cdat) pixOffset += gray.Stride case cbGA8: for x := 0; x < width; x++ { ycol := cdat[2*x+0] nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]}) } case cbTC8: pix, i, j := rgba.Pix, pixOffset, 0 for x := 0; x < width; x++ { pix[i+0] = cdat[j+0] pix[i+1] = cdat[j+1] pix[i+2] = cdat[j+2] pix[i+3] = 0xff i += 4 j += 3 } pixOffset += rgba.Stride case cbP1: for x := 0; x < width; x += 8 { b := cdat[x/8] for x2 := 0; x2 < 8 && x+x2 < width; x2++ { idx := b >> 7 if len(paletted.Palette) <= int(idx) { paletted.Palette = paletted.Palette[:int(idx)+1] } paletted.SetColorIndex(x+x2, y, idx) b <<= 1 } } case cbP2: for x := 0; x < width; x += 4 { b := cdat[x/4] for x2 := 0; x2 < 4 && x+x2 < width; x2++ { idx := b >> 6 if len(paletted.Palette) <= int(idx) { paletted.Palette = paletted.Palette[:int(idx)+1] } paletted.SetColorIndex(x+x2, y, idx) b <<= 2 } } case cbP4: for x := 0; x < width; x += 2 { b := cdat[x/2] for x2 := 0; x2 < 2 && x+x2 < width; x2++ { idx := b >> 4 if len(paletted.Palette) <= int(idx) { paletted.Palette = paletted.Palette[:int(idx)+1] } paletted.SetColorIndex(x+x2, y, idx) b <<= 4 } } case cbP8: if len(paletted.Palette) != 255 { for x := 0; x < width; x++ { if len(paletted.Palette) <= int(cdat[x]) { paletted.Palette = paletted.Palette[:int(cdat[x])+1] } } } copy(paletted.Pix[pixOffset:], cdat) pixOffset += paletted.Stride case cbTCA8: 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}) } case cbGA16: for x := 0; x < width; x++ { ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1]) acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3]) nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol}) } case cbTC16: for x := 0; x < width; x++ { rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff}) } case cbTCA16: for x := 0; x < width; x++ { rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1]) gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3]) bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5]) acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7]) nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol}) } } // The current row for y is the previous row for y+1. pr, cr = cr, pr } return img, nil }
func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) { r, err := zlib.NewReader(idat) if err != nil { return nil, err } defer r.Close() bpp := 0 // Bytes per pixel. maxPalette := uint8(0) var ( gray *image.Gray rgba *image.RGBA paletted *image.Paletted nrgba *image.NRGBA gray16 *image.Gray16 rgba64 *image.RGBA64 nrgba64 *image.NRGBA64 img image.Image ) switch d.cb { case cbG8: bpp = 1 gray = image.NewGray(d.width, d.height) img = gray case cbTC8: bpp = 3 rgba = image.NewRGBA(d.width, d.height) img = rgba case cbP8: bpp = 1 paletted = image.NewPaletted(d.width, d.height, d.palette) img = paletted maxPalette = uint8(len(d.palette) - 1) case cbTCA8: bpp = 4 nrgba = image.NewNRGBA(d.width, d.height) img = nrgba case cbG16: bpp = 2 gray16 = image.NewGray16(d.width, d.height) img = gray16 case cbTC16: bpp = 6 rgba64 = image.NewRGBA64(d.width, d.height) img = rgba64 case cbTCA16: bpp = 8 nrgba64 = image.NewNRGBA64(d.width, d.height) img = nrgba64 } // cr and pr are the bytes for the current and previous row. // The +1 is for the per-row filter type, which is at cr[0]. cr := make([]uint8, 1+bpp*d.width) pr := make([]uint8, 1+bpp*d.width) for y := 0; y < d.height; y++ { // Read the decompressed bytes. _, err := io.ReadFull(r, cr) if err != nil { return nil, err } // Apply the filter. cdat := cr[1:] pdat := pr[1:] switch cr[0] { case ftNone: // No-op. case ftSub: for i := bpp; i < len(cdat); i++ { cdat[i] += cdat[i-bpp] } case ftUp: for i := 0; i < len(cdat); i++ { cdat[i] += pdat[i] } case ftAverage: for i := 0; i < bpp; i++ { cdat[i] += pdat[i] / 2 } for i := bpp; i < len(cdat); i++ { cdat[i] += uint8((int(cdat[i-bpp]) + int(pdat[i])) / 2) } case ftPaeth: for i := 0; i < bpp; i++ { cdat[i] += paeth(0, pdat[i], 0) } for i := bpp; i < len(cdat); i++ { cdat[i] += paeth(cdat[i-bpp], pdat[i], pdat[i-bpp]) } default: return nil, FormatError("bad filter type") } // Convert from bytes to colors. switch d.cb { case cbG8: for x := 0; x < d.width; x++ { gray.Set(x, y, image.GrayColor{cdat[x]}) } case cbTC8: for x := 0; x < d.width; x++ { rgba.Set(x, y, image.RGBAColor{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff}) } case cbP8: for x := 0; x < d.width; x++ { if cdat[x] > maxPalette { return nil, FormatError("palette index out of range") } paletted.SetColorIndex(x, y, cdat[x]) } case cbTCA8: for x := 0; x < d.width; x++ { nrgba.Set(x, y, image.NRGBAColor{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]}) } case cbG16: for x := 0; x < d.width; x++ { ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) gray16.Set(x, y, image.Gray16Color{ycol}) } case cbTC16: for x := 0; x < d.width; x++ { rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) rgba64.Set(x, y, image.RGBA64Color{rcol, gcol, bcol, 0xffff}) } case cbTCA16: for x := 0; x < d.width; x++ { rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1]) gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3]) bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5]) acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7]) nrgba64.Set(x, y, image.NRGBA64Color{rcol, gcol, bcol, acol}) } } // The current row for y is the previous row for y+1. pr, cr = cr, pr } return img, nil }
// Set a pixel in img by blending c on top of whatever color is // already there func blend(pt image.Point, c color.Color, img *image.RGBA64) { cc := over(c, img.At(pt.X, pt.Y)) img.Set(pt.X, pt.Y, cc) }
func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) { r, err := zlib.NewReader(idat) if err != nil { return nil, err } defer r.Close() bitsPerPixel := 0 maxPalette := uint8(0) var ( gray *image.Gray rgba *image.RGBA paletted *image.Paletted nrgba *image.NRGBA gray16 *image.Gray16 rgba64 *image.RGBA64 nrgba64 *image.NRGBA64 img image.Image ) switch d.cb { case cbG1, cbG2, cbG4, cbG8: bitsPerPixel = d.depth gray = image.NewGray(d.width, d.height) img = gray case cbGA8: bitsPerPixel = 16 nrgba = image.NewNRGBA(d.width, d.height) img = nrgba case cbTC8: bitsPerPixel = 24 rgba = image.NewRGBA(d.width, d.height) img = rgba case cbP1, cbP2, cbP4, cbP8: bitsPerPixel = d.depth paletted = image.NewPaletted(d.width, d.height, d.palette) img = paletted maxPalette = uint8(len(d.palette) - 1) case cbTCA8: bitsPerPixel = 32 nrgba = image.NewNRGBA(d.width, d.height) img = nrgba case cbG16: bitsPerPixel = 16 gray16 = image.NewGray16(d.width, d.height) img = gray16 case cbGA16: bitsPerPixel = 32 nrgba64 = image.NewNRGBA64(d.width, d.height) img = nrgba64 case cbTC16: bitsPerPixel = 48 rgba64 = image.NewRGBA64(d.width, d.height) img = rgba64 case cbTCA16: bitsPerPixel = 64 nrgba64 = image.NewNRGBA64(d.width, d.height) img = nrgba64 } bytesPerPixel := (bitsPerPixel + 7) / 8 // cr and pr are the bytes for the current and previous row. // The +1 is for the per-row filter type, which is at cr[0]. cr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8) pr := make([]uint8, 1+(bitsPerPixel*d.width+7)/8) for y := 0; y < d.height; y++ { // Read the decompressed bytes. _, err := io.ReadFull(r, cr) if err != nil { return nil, err } // Apply the filter. cdat := cr[1:] pdat := pr[1:] switch cr[0] { case ftNone: // No-op. case ftSub: for i := bytesPerPixel; i < len(cdat); i++ { cdat[i] += cdat[i-bytesPerPixel] } case ftUp: for i := 0; i < len(cdat); i++ { cdat[i] += pdat[i] } case ftAverage: for i := 0; i < bytesPerPixel; i++ { cdat[i] += pdat[i] / 2 } for i := bytesPerPixel; i < len(cdat); i++ { cdat[i] += uint8((int(cdat[i-bytesPerPixel]) + int(pdat[i])) / 2) } case ftPaeth: for i := 0; i < bytesPerPixel; i++ { cdat[i] += paeth(0, pdat[i], 0) } for i := bytesPerPixel; i < len(cdat); i++ { cdat[i] += paeth(cdat[i-bytesPerPixel], pdat[i], pdat[i-bytesPerPixel]) } default: return nil, FormatError("bad filter type") } // Convert from bytes to colors. switch d.cb { case cbG1: for x := 0; x < d.width; x += 8 { b := cdat[x/8] for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ { gray.Set(x+x2, y, image.GrayColor{(b >> 7) * 0xff}) b <<= 1 } } case cbG2: for x := 0; x < d.width; x += 4 { b := cdat[x/4] for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ { gray.Set(x+x2, y, image.GrayColor{(b >> 6) * 0x55}) b <<= 2 } } case cbG4: for x := 0; x < d.width; x += 2 { b := cdat[x/2] for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ { gray.Set(x+x2, y, image.GrayColor{(b >> 4) * 0x11}) b <<= 4 } } case cbG8: for x := 0; x < d.width; x++ { gray.Set(x, y, image.GrayColor{cdat[x]}) } case cbGA8: for x := 0; x < d.width; x++ { ycol := cdat[2*x+0] nrgba.Set(x, y, image.NRGBAColor{ycol, ycol, ycol, cdat[2*x+1]}) } case cbTC8: for x := 0; x < d.width; x++ { rgba.Set(x, y, image.RGBAColor{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff}) } case cbP1: for x := 0; x < d.width; x += 8 { b := cdat[x/8] for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ { idx := b >> 7 if idx > maxPalette { return nil, FormatError("palette index out of range") } paletted.SetColorIndex(x+x2, y, idx) b <<= 1 } } case cbP2: for x := 0; x < d.width; x += 4 { b := cdat[x/4] for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ { idx := b >> 6 if idx > maxPalette { return nil, FormatError("palette index out of range") } paletted.SetColorIndex(x+x2, y, idx) b <<= 2 } } case cbP4: for x := 0; x < d.width; x += 2 { b := cdat[x/2] for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ { idx := b >> 4 if idx > maxPalette { return nil, FormatError("palette index out of range") } paletted.SetColorIndex(x+x2, y, idx) b <<= 4 } } case cbP8: for x := 0; x < d.width; x++ { if cdat[x] > maxPalette { return nil, FormatError("palette index out of range") } paletted.SetColorIndex(x, y, cdat[x]) } case cbTCA8: for x := 0; x < d.width; x++ { nrgba.Set(x, y, image.NRGBAColor{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]}) } case cbG16: for x := 0; x < d.width; x++ { ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1]) gray16.Set(x, y, image.Gray16Color{ycol}) } case cbGA16: for x := 0; x < d.width; x++ { ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1]) acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3]) nrgba64.Set(x, y, image.NRGBA64Color{ycol, ycol, ycol, acol}) } case cbTC16: for x := 0; x < d.width; x++ { rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1]) gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3]) bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5]) rgba64.Set(x, y, image.RGBA64Color{rcol, gcol, bcol, 0xffff}) } case cbTCA16: for x := 0; x < d.width; x++ { rcol := uint16(cdat[8*x+0])<<8 | uint16(cdat[8*x+1]) gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3]) bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5]) acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7]) nrgba64.Set(x, y, image.NRGBA64Color{rcol, gcol, bcol, acol}) } } // The current row for y is the previous row for y+1. pr, cr = cr, pr } return img, nil }