colorm.go (3730B)
1 // Copyright 2014 Hajime Hoshi 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ebiten 16 17 import ( 18 "image/color" 19 20 "github.com/hajimehoshi/ebiten/v2/internal/affine" 21 ) 22 23 // ColorMDim is a dimension of a ColorM. 24 const ColorMDim = affine.ColorMDim 25 26 // A ColorM represents a matrix to transform coloring when rendering an image. 27 // 28 // A ColorM is applied to the straight alpha color 29 // while an Image's pixels' format is alpha premultiplied. 30 // Before applying a matrix, a color is un-multiplied, and after applying the matrix, 31 // the color is multiplied again. 32 // 33 // The initial value is identity. 34 type ColorM struct { 35 impl affine.ColorM 36 37 _ [0]func() // Marks as non-comparable. 38 } 39 40 func (c *ColorM) affineColorM() affine.ColorM { 41 if c.impl != nil { 42 return c.impl 43 } 44 return affine.ColorMIdentity{} 45 } 46 47 // String returns a string representation of ColorM. 48 func (c *ColorM) String() string { 49 return affine.ColorMString(c.affineColorM()) 50 } 51 52 // Reset resets the ColorM as identity. 53 func (c *ColorM) Reset() { 54 c.impl = affine.ColorMIdentity{} 55 } 56 57 // Apply pre-multiplies a vector (r, g, b, a, 1) by the matrix 58 // where r, g, b, and a are clr's values in straight-alpha format. 59 // In other words, Apply calculates ColorM * (r, g, b, a, 1)^T. 60 func (c *ColorM) Apply(clr color.Color) color.Color { 61 return c.affineColorM().Apply(clr) 62 } 63 64 // Concat multiplies a color matrix with the other color matrix. 65 // This is same as muptiplying the matrix other and the matrix c in this order. 66 func (c *ColorM) Concat(other ColorM) { 67 o := other.impl 68 if o == nil { 69 return 70 } 71 c.impl = c.affineColorM().Concat(o) 72 } 73 74 // Scale scales the matrix by (r, g, b, a). 75 func (c *ColorM) Scale(r, g, b, a float64) { 76 c.impl = c.affineColorM().Scale(float32(r), float32(g), float32(b), float32(a)) 77 } 78 79 // Translate translates the matrix by (r, g, b, a). 80 func (c *ColorM) Translate(r, g, b, a float64) { 81 c.impl = c.affineColorM().Translate(float32(r), float32(g), float32(b), float32(a)) 82 } 83 84 // RotateHue rotates the hue. 85 // theta represents rotating angle in radian. 86 func (c *ColorM) RotateHue(theta float64) { 87 c.ChangeHSV(theta, 1, 1) 88 } 89 90 // ChangeHSV changes HSV (Hue-Saturation-Value) values. 91 // hueTheta is a radian value to rotate hue. 92 // saturationScale is a value to scale saturation. 93 // valueScale is a value to scale value (a.k.a. brightness). 94 // 95 // This conversion uses RGB to/from YCrCb conversion. 96 func (c *ColorM) ChangeHSV(hueTheta float64, saturationScale float64, valueScale float64) { 97 c.impl = affine.ChangeHSV(c.affineColorM(), hueTheta, float32(saturationScale), float32(valueScale)) 98 } 99 100 // Element returns a value of a matrix at (i, j). 101 func (c *ColorM) Element(i, j int) float64 { 102 return float64(c.affineColorM().At(i, j)) 103 } 104 105 // SetElement sets an element at (i, j). 106 func (c *ColorM) SetElement(i, j int, element float64) { 107 c.impl = affine.ColorMSetElement(c.affineColorM(), i, j, float32(element)) 108 } 109 110 // IsInvertible returns a boolean value indicating 111 // whether the matrix c is invertible or not. 112 func (c *ColorM) IsInvertible() bool { 113 return c.affineColorM().IsInvertible() 114 } 115 116 // Invert inverts the matrix. 117 // If c is not invertible, Invert panics. 118 func (c *ColorM) Invert() { 119 c.impl = c.affineColorM().Invert() 120 }