zorldo

Goofing around with Ebiten
git clone git://bsandro.tech/zorldo
Log | Files | Refs | README

imagetobytes.go (2288B)


      1 // Copyright 2017 The Ebiten Authors
      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"
     19 	"image/color"
     20 	"image/draw"
     21 )
     22 
     23 // imageToBytes gets RGBA bytes from img.
     24 //
     25 // Basically imageToBytes just calls draw.Draw.
     26 // If img is a paletted image, an optimized copying method is used.
     27 //
     28 // If img is *image.RGBA and its length is same as 4*width*height, imageToBytes returns its Pix.
     29 func imageToBytes(img image.Image) []byte {
     30 	size := img.Bounds().Size()
     31 	w, h := size.X, size.Y
     32 
     33 	switch img := img.(type) {
     34 	case *image.Paletted:
     35 		bs := make([]byte, 4*w*h)
     36 
     37 		b := img.Bounds()
     38 		x0 := b.Min.X
     39 		y0 := b.Min.Y
     40 		x1 := b.Max.X
     41 		y1 := b.Max.Y
     42 
     43 		palette := make([]uint8, len(img.Palette)*4)
     44 		for i, c := range img.Palette {
     45 			rgba := color.RGBAModel.Convert(c).(color.RGBA)
     46 			palette[4*i] = rgba.R
     47 			palette[4*i+1] = rgba.G
     48 			palette[4*i+2] = rgba.B
     49 			palette[4*i+3] = rgba.A
     50 		}
     51 		// Even img is a subimage of another image, Pix starts with 0-th index.
     52 		idx0 := 0
     53 		idx1 := 0
     54 		d := img.Stride - (x1 - x0)
     55 		for j := 0; j < y1-y0; j++ {
     56 			for i := 0; i < x1-x0; i++ {
     57 				p := int(img.Pix[idx0])
     58 				bs[idx1] = palette[4*p]
     59 				bs[idx1+1] = palette[4*p+1]
     60 				bs[idx1+2] = palette[4*p+2]
     61 				bs[idx1+3] = palette[4*p+3]
     62 				idx0++
     63 				idx1 += 4
     64 			}
     65 			idx0 += d
     66 		}
     67 		return bs
     68 	case *image.RGBA:
     69 		if len(img.Pix) == 4*w*h {
     70 			return img.Pix
     71 		}
     72 		return imageToBytesSlow(img)
     73 	default:
     74 		return imageToBytesSlow(img)
     75 	}
     76 }
     77 
     78 func imageToBytesSlow(img image.Image) []byte {
     79 	size := img.Bounds().Size()
     80 	w, h := size.X, size.Y
     81 	bs := make([]byte, 4*w*h)
     82 
     83 	dstImg := &image.RGBA{
     84 		Pix:    bs,
     85 		Stride: 4 * w,
     86 		Rect:   image.Rect(0, 0, w, h),
     87 	}
     88 	draw.Draw(dstImg, image.Rect(0, 0, w, h), img, img.Bounds().Min, draw.Src)
     89 	return bs
     90 }