mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
colorm: Add ColorM.ChangeHSV and an example
This commit is contained in:
parent
05f52b5e57
commit
723876feba
71
colorm.go
71
colorm.go
@ -104,19 +104,57 @@ func (c *ColorM) Translate(r, g, b, a float64) {
|
||||
|
||||
// RotateHue rotates the hue.
|
||||
func (c *ColorM) RotateHue(theta float64) {
|
||||
sin, cos := math.Sincos(theta)
|
||||
v1 := cos + (1.0-cos)/3.0
|
||||
v2 := (1.0/3.0)*(1.0-cos) - math.Sqrt(1.0/3.0)*sin
|
||||
v3 := (1.0/3.0)*(1.0-cos) + math.Sqrt(1.0/3.0)*sin
|
||||
c.ChangeHSV(theta, 1, 1)
|
||||
}
|
||||
|
||||
var (
|
||||
// The YCbCr value ranges are:
|
||||
// Y: [ 0 - 1 ]
|
||||
// Cb: [-0.5 - 0.5]
|
||||
// Cr: [-0.5 - 0.5]
|
||||
|
||||
rgbToYCbCr = ColorM{
|
||||
initialized: true,
|
||||
es: [ColorMDim - 1][ColorMDim]float64{
|
||||
{0.2990, 0.5870, 0.1140, 0, 0},
|
||||
{-0.1687, -0.3313, 0.5000, 0, 0},
|
||||
{0.5000, -0.4187, -0.0813, 0, 0},
|
||||
{0, 0, 0, 1, 0},
|
||||
},
|
||||
}
|
||||
yCbCrToRgb = ColorM{
|
||||
initialized: true,
|
||||
es: [ColorMDim - 1][ColorMDim]float64{
|
||||
{1, 0, 1.40200, 0, 0},
|
||||
{1, -0.34414, -0.71414, 0, 0},
|
||||
{1, 1.77200, 0, 0, 0},
|
||||
{0, 0, 0, 1, 0},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// ChangeHSV changes HSV (Hue-Saturation-Value) values.
|
||||
// hueTheta is a radian value to ratate hue.
|
||||
// saturationScale is a value to scale saturation.
|
||||
// valueScale is a value to scale value (a.k.a. brightness).
|
||||
//
|
||||
// This conversion uses RGB to/from YCrCb conversion.
|
||||
func (c *ColorM) ChangeHSV(hueTheta float64, saturationScale float64, valueScale float64) {
|
||||
sin, cos := math.Sincos(hueTheta)
|
||||
c.Concat(rgbToYCbCr)
|
||||
c.Concat(ColorM{
|
||||
initialized: true,
|
||||
es: [ColorMDim - 1][ColorMDim]float64{
|
||||
{v1, v2, v3, 0, 0},
|
||||
{v3, v1, v2, 0, 0},
|
||||
{v2, v3, v1, 0, 0},
|
||||
{1, 0, 0, 0, 0},
|
||||
{0, cos, -sin, 0, 0},
|
||||
{0, sin, cos, 0, 0},
|
||||
{0, 0, 0, 1, 0},
|
||||
},
|
||||
})
|
||||
s := saturationScale
|
||||
v := valueScale
|
||||
c.Scale(v, s*v, s*v, 1)
|
||||
c.Concat(yCbCrToRgb)
|
||||
}
|
||||
|
||||
// SetElement sets an element at (i, j).
|
||||
@ -127,20 +165,15 @@ func (c *ColorM) SetElement(i, j int, element float64) {
|
||||
c.es[i][j] = element
|
||||
}
|
||||
|
||||
var monochrome ColorM
|
||||
|
||||
func init() {
|
||||
monochrome.ChangeHSV(0, 0, 1)
|
||||
}
|
||||
|
||||
// Monochrome returns a color matrix to make an image monochrome.
|
||||
func Monochrome() ColorM {
|
||||
const r = 6968.0 / 32768.0
|
||||
const g = 23434.0 / 32768.0
|
||||
const b = 2366.0 / 32768.0
|
||||
return ColorM{
|
||||
initialized: true,
|
||||
es: [ColorMDim - 1][ColorMDim]float64{
|
||||
{r, g, b, 0, 0},
|
||||
{r, g, b, 0, 0},
|
||||
{r, g, b, 0, 0},
|
||||
{0, 0, 0, 1, 0},
|
||||
},
|
||||
}
|
||||
return monochrome
|
||||
}
|
||||
|
||||
// Deprecated as of 1.2.0-alpha. Use Scale instead.
|
||||
|
104
examples/hsv/main.go
Normal file
104
examples/hsv/main.go
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2016 Hajime Hoshi
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
_ "image/jpeg"
|
||||
"log"
|
||||
"math"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
)
|
||||
|
||||
const (
|
||||
screenWidth = 320
|
||||
screenHeight = 240
|
||||
)
|
||||
|
||||
var (
|
||||
hueInt = 0
|
||||
saturationInt = 128
|
||||
valueInt = 128
|
||||
gophersImage *ebiten.Image
|
||||
)
|
||||
|
||||
func clamp(v, min, max int) int {
|
||||
if min > max {
|
||||
panic("min must <= max")
|
||||
}
|
||||
if v < min {
|
||||
return min
|
||||
}
|
||||
if max < v {
|
||||
return max
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func update(screen *ebiten.Image) error {
|
||||
if ebiten.IsKeyPressed(ebiten.KeyQ) {
|
||||
hueInt--
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyW) {
|
||||
hueInt++
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyA) {
|
||||
saturationInt--
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyS) {
|
||||
saturationInt++
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyZ) {
|
||||
valueInt--
|
||||
}
|
||||
if ebiten.IsKeyPressed(ebiten.KeyX) {
|
||||
valueInt++
|
||||
}
|
||||
hueInt = clamp(hueInt, -256, 256)
|
||||
saturationInt = clamp(saturationInt, 0, 256)
|
||||
valueInt = clamp(valueInt, 0, 256)
|
||||
|
||||
w, h := gophersImage.Size()
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(float64(screenWidth-w)/2, float64(screenHeight-h)/2)
|
||||
hue := float64(hueInt) * 2 * math.Pi / 128
|
||||
saturation := float64(saturationInt) / 128
|
||||
value := float64(valueInt) / 128
|
||||
op.ColorM.ChangeHSV(hue, saturation, value)
|
||||
if err := screen.DrawImage(gophersImage, op); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf(`Hue: %0.2f [Q][W]
|
||||
Saturation: %0.2f [A][S]
|
||||
Value: %0.2f [Z][X]`, hue, saturation, value)
|
||||
if err := ebitenutil.DebugPrint(screen, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
gophersImage, _, err = ebitenutil.NewImageFromFile("_resources/images/gophers.jpg", ebiten.FilterNearest)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "HSV (Ebiten Demo)"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user