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  }