...
Tawesoft Logo

Source file src/tawesoft.co.uk/go/ximage/rgb.go

Documentation: src/tawesoft.co.uk/go/ximage/rgb.go

     1  // Based on https://golang.org/src/image/image.go
     2  // Copyright 2009 The Go Authors. All rights reserved.
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package ximage
     7  
     8  import (
     9      "image"
    10      "image/color"
    11      "tawesoft.co.uk/go/ximage/xcolor"
    12  )
    13  
    14  // RGB is an in-memory image whose At method returns color.RGB values.
    15  type RGB struct {
    16  	// Pix holds the image's pixels, as Red values. The pixel at
    17  	// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*2].
    18  	Pix []uint8
    19  	// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
    20  	Stride int
    21  	// Rect is the image's bounds.
    22  	Rect image.Rectangle
    23  }
    24  
    25  func (p *RGB) ColorModel() color.Model { return xcolor.RGBModel }
    26  
    27  func (p *RGB) Bounds() image.Rectangle { return p.Rect }
    28  
    29  func (p *RGB) At(x, y int) color.Color {
    30  	return p.RGBAt(x, y)
    31  }
    32  
    33  func (p *RGB) RGBAt(x, y int) xcolor.RGB {
    34  	if !(image.Point{x, y}.In(p.Rect)) {
    35  		return xcolor.RGB{}
    36  	}
    37  	i := p.PixOffset(x, y)
    38  	return xcolor.RGB{R: p.Pix[i], G: p.Pix[i+1], B: p.Pix[i+2]}
    39  }
    40  
    41  // PixOffset returns the index of the first element of Pix that corresponds to
    42  // the pixel at (x, y).
    43  func (p *RGB) PixOffset(x, y int) int {
    44  	return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*1
    45  }
    46  
    47  func (p *RGB) Set(x, y int, c color.Color) {
    48  	if !(image.Point{x, y}.In(p.Rect)) {
    49  		return
    50  	}
    51      i := p.PixOffset(x, y)
    52      rgba := xcolor.RGBModel.Convert(c).(color.RGBA)
    53      p.Pix[i]   = rgba.R
    54      p.Pix[i+1] = rgba.G
    55      p.Pix[i+2] = rgba.B
    56  }
    57  
    58  func (p *RGB) SetRGB(x, y int, c xcolor.RGB) {
    59  	if !(image.Point{x, y}.In(p.Rect)) {
    60  		return
    61  	}
    62  	i := p.PixOffset(x, y)
    63      p.Pix[i]   = c.R
    64      p.Pix[i+1] = c.G
    65      p.Pix[i+2] = c.B
    66  }
    67  
    68  // SubImage returns an image representing the portion of the image p visible
    69  // through r. The returned value shares pixels with the original image.
    70  func (p *RGB) SubImage(r image.Rectangle) image.Image {
    71  	r = r.Intersect(p.Rect)
    72  	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
    73  	// either r1 or r2 if the intersection is empty. Without explicitly checking for
    74  	// this, the Pix[i:] expression below can panic.
    75  	if r.Empty() {
    76  		return &RGB{}
    77  	}
    78  	i := p.PixOffset(r.Min.X, r.Min.Y)
    79  	return &RGB{
    80  		Pix:    p.Pix[i:],
    81  		Stride: p.Stride,
    82  		Rect:   r,
    83  	}
    84  }
    85  
    86  // Opaque scans the entire image and reports whether it is fully opaque.
    87  func (p *RGB) Opaque() bool {
    88  	return true
    89  }
    90  
    91  // NewRGB returns a new RGB image with the given bounds.
    92  func NewRGB(r image.Rectangle) *RGB {
    93  	w, h := r.Dx(), r.Dy()
    94  	pix := make([]uint8, 3 * w * h)
    95  	return &RGB{pix, 3 * w, r}
    96  }
    97  

View as plain text