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 }