github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/image/webp/nycbcra/nycbcra.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package nycbcra provides non-alpha-premultiplied Y'CbCr-with-alpha image and 6 // color types. 7 package nycbcra // import "golang.org/x/image/webp/nycbcra" 8 9 import ( 10 "image" 11 "image/color" 12 ) 13 14 // TODO: move this to the standard image and image/color packages, so that the 15 // image/draw package can have fast-path code. Moving would rename: 16 // nycbcra.Color to color.NYCbCrA 17 // nycbcra.ColorModel to color.NYCbCrAModel 18 // nycbcra.Image to image.NYCbCrA 19 20 // Color represents a non-alpha-premultiplied Y'CbCr-with-alpha color, having 21 // 8 bits each for one luma, two chroma and one alpha component. 22 type Color struct { 23 color.YCbCr 24 A uint8 25 } 26 27 func (c Color) RGBA() (r, g, b, a uint32) { 28 r8, g8, b8 := color.YCbCrToRGB(c.Y, c.Cb, c.Cr) 29 a = uint32(c.A) * 0x101 30 r = uint32(r8) * 0x101 * a / 0xffff 31 g = uint32(g8) * 0x101 * a / 0xffff 32 b = uint32(b8) * 0x101 * a / 0xffff 33 return 34 } 35 36 // ColorModel is the Model for non-alpha-premultiplied Y'CbCr-with-alpha colors. 37 var ColorModel color.Model = color.ModelFunc(nYCbCrAModel) 38 39 func nYCbCrAModel(c color.Color) color.Color { 40 switch c := c.(type) { 41 case Color: 42 return c 43 case color.YCbCr: 44 return Color{c, 0xff} 45 } 46 r, g, b, a := c.RGBA() 47 48 // Convert from alpha-premultiplied to non-alpha-premultiplied. 49 if a != 0 { 50 r = (r * 0xffff) / a 51 g = (g * 0xffff) / a 52 b = (b * 0xffff) / a 53 } 54 55 y, u, v := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8)) 56 return Color{color.YCbCr{Y: y, Cb: u, Cr: v}, uint8(a >> 8)} 57 } 58 59 // Image is an in-memory image of non-alpha-premultiplied Y'CbCr-with-alpha 60 // colors. A and AStride are analogous to the Y and YStride fields of the 61 // embedded YCbCr. 62 type Image struct { 63 image.YCbCr 64 A []uint8 65 AStride int 66 } 67 68 func (p *Image) ColorModel() color.Model { 69 return ColorModel 70 } 71 72 func (p *Image) At(x, y int) color.Color { 73 return p.NYCbCrAAt(x, y) 74 } 75 76 func (p *Image) NYCbCrAAt(x, y int) Color { 77 if !(image.Point{X: x, Y: y}.In(p.Rect)) { 78 return Color{} 79 } 80 yi := p.YOffset(x, y) 81 ci := p.COffset(x, y) 82 ai := p.AOffset(x, y) 83 return Color{ 84 color.YCbCr{ 85 Y: p.Y[yi], 86 Cb: p.Cb[ci], 87 Cr: p.Cr[ci], 88 }, 89 p.A[ai], 90 } 91 } 92 93 // AOffset returns the index of the first element of A that corresponds to 94 // the pixel at (x, y). 95 func (p *Image) AOffset(x, y int) int { 96 return (y-p.Rect.Min.Y)*p.AStride + (x - p.Rect.Min.X) 97 } 98 99 // SubImage returns an image representing the portion of the image p visible 100 // through r. The returned value shares pixels with the original image. 101 func (p *Image) SubImage(r image.Rectangle) image.Image { 102 // TODO: share code with image.NewYCbCr when this type moves into the 103 // standard image package. 104 r = r.Intersect(p.Rect) 105 // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside 106 // either r1 or r2 if the intersection is empty. Without explicitly checking for 107 // this, the Pix[i:] expression below can panic. 108 if r.Empty() { 109 return &Image{ 110 YCbCr: image.YCbCr{ 111 SubsampleRatio: p.SubsampleRatio, 112 }, 113 } 114 } 115 yi := p.YOffset(r.Min.X, r.Min.Y) 116 ci := p.COffset(r.Min.X, r.Min.Y) 117 ai := p.AOffset(r.Min.X, r.Min.Y) 118 return &Image{ 119 YCbCr: image.YCbCr{ 120 Y: p.Y[yi:], 121 Cb: p.Cb[ci:], 122 Cr: p.Cr[ci:], 123 SubsampleRatio: p.SubsampleRatio, 124 YStride: p.YStride, 125 CStride: p.CStride, 126 Rect: r, 127 }, 128 A: p.A[ai:], 129 AStride: p.AStride, 130 } 131 } 132 133 // Opaque scans the entire image and reports whether it is fully opaque. 134 func (p *Image) Opaque() bool { 135 if p.Rect.Empty() { 136 return true 137 } 138 i0, i1 := 0, p.Rect.Dx() 139 for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ { 140 for _, a := range p.A[i0:i1] { 141 if a != 0xff { 142 return false 143 } 144 } 145 i0 += p.AStride 146 i1 += p.AStride 147 } 148 return true 149 } 150 151 // New returns a new Image with the given bounds and subsample ratio. 152 func New(r image.Rectangle, subsampleRatio image.YCbCrSubsampleRatio) *Image { 153 // TODO: share code with image.NewYCbCr when this type moves into the 154 // standard image package. 155 w, h, cw, ch := r.Dx(), r.Dy(), 0, 0 156 switch subsampleRatio { 157 case image.YCbCrSubsampleRatio422: 158 cw = (r.Max.X+1)/2 - r.Min.X/2 159 ch = h 160 case image.YCbCrSubsampleRatio420: 161 cw = (r.Max.X+1)/2 - r.Min.X/2 162 ch = (r.Max.Y+1)/2 - r.Min.Y/2 163 case image.YCbCrSubsampleRatio440: 164 cw = w 165 ch = (r.Max.Y+1)/2 - r.Min.Y/2 166 default: 167 // Default to 4:4:4 subsampling. 168 cw = w 169 ch = h 170 } 171 b := make([]byte, 2*w*h+2*cw*ch) 172 // TODO: use s[i:j:k] notation to set the cap. 173 return &Image{ 174 YCbCr: image.YCbCr{ 175 Y: b[:w*h], 176 Cb: b[w*h+0*cw*ch : w*h+1*cw*ch], 177 Cr: b[w*h+1*cw*ch : w*h+2*cw*ch], 178 SubsampleRatio: subsampleRatio, 179 YStride: w, 180 CStride: cw, 181 Rect: r, 182 }, 183 A: b[w*h+2*cw*ch:], 184 AStride: w, 185 } 186 }