123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- package imaging
- import (
- "image"
- "image/color"
- )
- // Clone returns a copy of the given image.
- func Clone(img image.Image) *image.NRGBA {
- dstBounds := img.Bounds().Sub(img.Bounds().Min)
- dst := image.NewNRGBA(dstBounds)
- switch src := img.(type) {
- case *image.NRGBA:
- copyNRGBA(dst, src)
- case *image.NRGBA64:
- copyNRGBA64(dst, src)
- case *image.RGBA:
- copyRGBA(dst, src)
- case *image.RGBA64:
- copyRGBA64(dst, src)
- case *image.Gray:
- copyGray(dst, src)
- case *image.Gray16:
- copyGray16(dst, src)
- case *image.YCbCr:
- copyYCbCr(dst, src)
- case *image.Paletted:
- copyPaletted(dst, src)
- default:
- copyImage(dst, src)
- }
- return dst
- }
- func copyNRGBA(dst *image.NRGBA, src *image.NRGBA) {
- srcMinX := src.Rect.Min.X
- srcMinY := src.Rect.Min.Y
- dstW := dst.Rect.Dx()
- dstH := dst.Rect.Dy()
- rowSize := dstW * 4
- parallel(dstH, func(partStart, partEnd int) {
- for dstY := partStart; dstY < partEnd; dstY++ {
- di := dst.PixOffset(0, dstY)
- si := src.PixOffset(srcMinX, srcMinY+dstY)
- copy(dst.Pix[di:di+rowSize], src.Pix[si:si+rowSize])
- }
- })
- }
- func copyNRGBA64(dst *image.NRGBA, src *image.NRGBA64) {
- srcMinX := src.Rect.Min.X
- srcMinY := src.Rect.Min.Y
- dstW := dst.Rect.Dx()
- dstH := dst.Rect.Dy()
- parallel(dstH, func(partStart, partEnd int) {
- for dstY := partStart; dstY < partEnd; dstY++ {
- di := dst.PixOffset(0, dstY)
- si := src.PixOffset(srcMinX, srcMinY+dstY)
- for dstX := 0; dstX < dstW; dstX++ {
- dst.Pix[di+0] = src.Pix[si+0]
- dst.Pix[di+1] = src.Pix[si+2]
- dst.Pix[di+2] = src.Pix[si+4]
- dst.Pix[di+3] = src.Pix[si+6]
- di += 4
- si += 8
- }
- }
- })
- }
- func copyRGBA(dst *image.NRGBA, src *image.RGBA) {
- srcMinX := src.Rect.Min.X
- srcMinY := src.Rect.Min.Y
- dstW := dst.Rect.Dx()
- dstH := dst.Rect.Dy()
- parallel(dstH, func(partStart, partEnd int) {
- for dstY := partStart; dstY < partEnd; dstY++ {
- di := dst.PixOffset(0, dstY)
- si := src.PixOffset(srcMinX, srcMinY+dstY)
- for dstX := 0; dstX < dstW; dstX++ {
- a := src.Pix[si+3]
- dst.Pix[di+3] = a
- switch a {
- case 0:
- dst.Pix[di+0] = 0
- dst.Pix[di+1] = 0
- dst.Pix[di+2] = 0
- case 0xff:
- dst.Pix[di+0] = src.Pix[si+0]
- dst.Pix[di+1] = src.Pix[si+1]
- dst.Pix[di+2] = src.Pix[si+2]
- default:
- var tmp uint16
- tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
- dst.Pix[di+0] = uint8(tmp)
- tmp = uint16(src.Pix[si+1]) * 0xff / uint16(a)
- dst.Pix[di+1] = uint8(tmp)
- tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
- dst.Pix[di+2] = uint8(tmp)
- }
- di += 4
- si += 4
- }
- }
- })
- }
- func copyRGBA64(dst *image.NRGBA, src *image.RGBA64) {
- srcMinX := src.Rect.Min.X
- srcMinY := src.Rect.Min.Y
- dstW := dst.Rect.Dx()
- dstH := dst.Rect.Dy()
- parallel(dstH, func(partStart, partEnd int) {
- for dstY := partStart; dstY < partEnd; dstY++ {
- di := dst.PixOffset(0, dstY)
- si := src.PixOffset(srcMinX, srcMinY+dstY)
- for dstX := 0; dstX < dstW; dstX++ {
- a := src.Pix[si+6]
- dst.Pix[di+3] = a
- switch a {
- case 0:
- dst.Pix[di+0] = 0
- dst.Pix[di+1] = 0
- dst.Pix[di+2] = 0
- case 0xff:
- dst.Pix[di+0] = src.Pix[si+0]
- dst.Pix[di+1] = src.Pix[si+2]
- dst.Pix[di+2] = src.Pix[si+4]
- default:
- var tmp uint16
- tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a)
- dst.Pix[di+0] = uint8(tmp)
- tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a)
- dst.Pix[di+1] = uint8(tmp)
- tmp = uint16(src.Pix[si+4]) * 0xff / uint16(a)
- dst.Pix[di+2] = uint8(tmp)
- }
- di += 4
- si += 8
- }
- }
- })
- }
- func copyGray(dst *image.NRGBA, src *image.Gray) {
- srcMinX := src.Rect.Min.X
- srcMinY := src.Rect.Min.Y
- dstW := dst.Rect.Dx()
- dstH := dst.Rect.Dy()
- parallel(dstH, func(partStart, partEnd int) {
- for dstY := partStart; dstY < partEnd; dstY++ {
- di := dst.PixOffset(0, dstY)
- si := src.PixOffset(srcMinX, srcMinY+dstY)
- for dstX := 0; dstX < dstW; dstX++ {
- c := src.Pix[si]
- dst.Pix[di+0] = c
- dst.Pix[di+1] = c
- dst.Pix[di+2] = c
- dst.Pix[di+3] = 0xff
- di += 4
- si++
- }
- }
- })
- }
- func copyGray16(dst *image.NRGBA, src *image.Gray16) {
- srcMinX := src.Rect.Min.X
- srcMinY := src.Rect.Min.Y
- dstW := dst.Rect.Dx()
- dstH := dst.Rect.Dy()
- parallel(dstH, func(partStart, partEnd int) {
- for dstY := partStart; dstY < partEnd; dstY++ {
- di := dst.PixOffset(0, dstY)
- si := src.PixOffset(srcMinX, srcMinY+dstY)
- for dstX := 0; dstX < dstW; dstX++ {
- c := src.Pix[si]
- dst.Pix[di+0] = c
- dst.Pix[di+1] = c
- dst.Pix[di+2] = c
- dst.Pix[di+3] = 0xff
- di += 4
- si += 2
- }
- }
- })
- }
- func copyYCbCr(dst *image.NRGBA, src *image.YCbCr) {
- srcMinX := src.Rect.Min.X
- srcMinY := src.Rect.Min.Y
- dstW := dst.Rect.Dx()
- dstH := dst.Rect.Dy()
- parallel(dstH, func(partStart, partEnd int) {
- for dstY := partStart; dstY < partEnd; dstY++ {
- srcY := srcMinY + dstY
- di := dst.PixOffset(0, dstY)
- for dstX := 0; dstX < dstW; dstX++ {
- srcX := srcMinX + dstX
- siy := (srcY-srcMinY)*src.YStride + (srcX - srcMinX)
- var sic int
- switch src.SubsampleRatio {
- case image.YCbCrSubsampleRatio444:
- sic = (srcY-srcMinY)*src.CStride + (srcX - srcMinX)
- case image.YCbCrSubsampleRatio422:
- sic = (srcY-srcMinY)*src.CStride + (srcX/2 - srcMinX/2)
- case image.YCbCrSubsampleRatio420:
- sic = (srcY/2-srcMinY/2)*src.CStride + (srcX/2 - srcMinX/2)
- case image.YCbCrSubsampleRatio440:
- sic = (srcY/2-srcMinY/2)*src.CStride + (srcX - srcMinX)
- default:
- sic = src.COffset(srcX, srcY)
- }
- y := int32(src.Y[siy])
- cb := int32(src.Cb[sic]) - 128
- cr := int32(src.Cr[sic]) - 128
- r := (y<<16 + 91881*cr + 1<<15) >> 16
- if r > 255 {
- r = 255
- } else if r < 0 {
- r = 0
- }
- g := (y<<16 - 22554*cb - 46802*cr + 1<<15) >> 16
- if g > 255 {
- g = 255
- } else if g < 0 {
- g = 0
- }
- b := (y<<16 + 116130*cb + 1<<15) >> 16
- if b > 255 {
- b = 255
- } else if b < 0 {
- b = 0
- }
- dst.Pix[di+0] = uint8(r)
- dst.Pix[di+1] = uint8(g)
- dst.Pix[di+2] = uint8(b)
- dst.Pix[di+3] = 255
- di += 4
- }
- }
- })
- }
- func copyPaletted(dst *image.NRGBA, src *image.Paletted) {
- srcMinX := src.Rect.Min.X
- srcMinY := src.Rect.Min.Y
- dstW := dst.Rect.Dx()
- dstH := dst.Rect.Dy()
- plen := len(src.Palette)
- pnew := make([]color.NRGBA, plen)
- for i := 0; i < plen; i++ {
- pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA)
- }
- parallel(dstH, func(partStart, partEnd int) {
- for dstY := partStart; dstY < partEnd; dstY++ {
- di := dst.PixOffset(0, dstY)
- si := src.PixOffset(srcMinX, srcMinY+dstY)
- for dstX := 0; dstX < dstW; dstX++ {
- c := pnew[src.Pix[si]]
- dst.Pix[di+0] = c.R
- dst.Pix[di+1] = c.G
- dst.Pix[di+2] = c.B
- dst.Pix[di+3] = c.A
- di += 4
- si++
- }
- }
- })
- }
- func copyImage(dst *image.NRGBA, src image.Image) {
- srcMinX := src.Bounds().Min.X
- srcMinY := src.Bounds().Min.Y
- dstW := dst.Bounds().Dx()
- dstH := dst.Bounds().Dy()
- parallel(dstH, func(partStart, partEnd int) {
- for dstY := partStart; dstY < partEnd; dstY++ {
- di := dst.PixOffset(0, dstY)
- for dstX := 0; dstX < dstW; dstX++ {
- c := color.NRGBAModel.Convert(src.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA)
- dst.Pix[di+0] = c.R
- dst.Pix[di+1] = c.G
- dst.Pix[di+2] = c.B
- dst.Pix[di+3] = c.A
- di += 4
- }
- }
- })
- }
- // toNRGBA converts any image type to *image.NRGBA with min-point at (0, 0).
- func toNRGBA(img image.Image) *image.NRGBA {
- if img, ok := img.(*image.NRGBA); ok && img.Bounds().Min.Eq(image.ZP) {
- return img
- }
- return Clone(img)
- }
|