aboutsummaryrefslogtreecommitdiff
path: root/image
diff options
context:
space:
mode:
authorBen Clayton <bclayton@google.com>2015-02-19 19:05:11 +0000
committerBen Clayton <bclayton@google.com>2015-02-20 11:25:07 +0000
commit3195f9fb7bc5339f32d46282564f8d7dcb3d5f48 (patch)
tree2b5a87ddcb351eef282e165c6dca1fbc9d545c91 /image
parentd197b3a0e8a95bb9710e847b682709f8371302ca (diff)
downloadgpu-3195f9fb7bc5339f32d46282564f8d7dcb3d5f48.tar.gz
Initial drop of the image package.
Package image provides functions for converting between various image formats. Change-Id: Id98cb492414225b44a412d78385db46b9b715a22
Diffstat (limited to 'image')
-rw-r--r--image/alpha.go38
-rw-r--r--image/atc.go153
-rw-r--r--image/convert.go69
-rw-r--r--image/doc.go17
-rw-r--r--image/etc1.go108
-rw-r--r--image/format.go44
-rw-r--r--image/lum.go40
-rw-r--r--image/lum_alpha.go40
-rw-r--r--image/png.go49
-rw-r--r--image/rgb.go40
-rw-r--r--image/utils.go41
11 files changed, 639 insertions, 0 deletions
diff --git a/image/alpha.go b/image/alpha.go
new file mode 100644
index 000000000..66a3eb87a
--- /dev/null
+++ b/image/alpha.go
@@ -0,0 +1,38 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+type fmtAlpha struct{}
+
+func (fmtAlpha) String() string { return "Alpha" }
+func (fmtAlpha) Check(d []byte, w, h int) error { return checkSize(d, w, h, 8) }
+
+// Alpha returns a format containing a single 8-bit alpha channel per pixel.
+func Alpha() Format { return fmtAlpha{} }
+
+func init() {
+ RegisterConverter(Alpha(), RGBA(),
+ func(src []byte, width, height int) ([]byte, error) {
+ dst, i, j := make([]byte, width*height*4), 0, 0
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ dst[j+0], dst[j+1], dst[j+2], dst[j+3] = 255, 255, 255, src[i]
+ i++
+ j += 4
+ }
+ }
+ return dst, nil
+ })
+}
diff --git a/image/atc.go b/image/atc.go
new file mode 100644
index 000000000..fa8fcc260
--- /dev/null
+++ b/image/atc.go
@@ -0,0 +1,153 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+import "android.googlesource.com/platform/tools/gpu/binary"
+
+type fmtATC_RGB_AMD struct{}
+
+func (fmtATC_RGB_AMD) String() string { return "ATC_RGB_AMD" }
+func (fmtATC_RGB_AMD) Check(d []byte, w, h int) error {
+ return checkSize(d, max(w, 4), max(h, 4), 4)
+}
+
+type fmtATC_RGBA_EXPLICIT_ALPHA_AMD struct{}
+
+func (fmtATC_RGBA_EXPLICIT_ALPHA_AMD) String() string { return "ATC_RGBA_EXPLICIT_ALPHA_AMD" }
+func (fmtATC_RGBA_EXPLICIT_ALPHA_AMD) Check(d []byte, w, h int) error {
+ return checkSize(d, max(w, 4), max(h, 4), 8)
+}
+
+// ATC_RGB_AMD returns a format representing the texture compression format with
+// the same name.
+func ATC_RGB_AMD() Format { return fmtATC_RGB_AMD{} }
+
+// ATC_RGBA_EXPLICIT_ALPHA_AMD returns a format representing the texture
+// compression format with the same name.
+func ATC_RGBA_EXPLICIT_ALPHA_AMD() Format { return fmtATC_RGBA_EXPLICIT_ALPHA_AMD{} }
+
+func init() {
+ RegisterConverter(ATC_RGB_AMD(), RGBA(),
+ func(src []byte, width, height int) ([]byte, error) {
+ dst, j := make([]byte, width*height*4), 0
+
+ block_width := max(width/4, 1)
+ block_height := max(height/4, 1)
+
+ bs := binary.BitStream{Data: src}
+
+ c := [4][3]uint32{
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ }
+
+ for by := 0; by < block_height; by++ {
+ for bx := 0; bx < block_width; bx++ {
+ c[0][2] = bs.Read(5) << 3
+ c[0][1] = bs.Read(5) << 3
+ c[0][0] = bs.Read(5) << 3
+ alt := bs.ReadBit() != 0
+ c[3][2] = bs.Read(5) << 3
+ c[3][1] = bs.Read(6) << 2
+ c[3][0] = bs.Read(5) << 3
+ for i := 0; i < 3; i++ {
+ if alt {
+ c[2][i] = c[0][i]
+ c[1][i] = c[0][i] - c[3][i]/4
+ c[0][i] = 0
+ } else {
+ c[1][i] = (c[0][i]*2 + c[3][i]*1) / 3
+ c[2][i] = (c[0][i]*1 + c[3][i]*2) / 3
+ }
+ }
+ for y := by * 4; y < (by+1)*4; y++ {
+ for x := bx * 4; x < (bx+1)*4; x++ {
+ idx := bs.Read(2)
+ if x < width && y < height {
+ j = 4 * (y*width + x)
+ dst[j+0] = uint8(c[idx][0])
+ dst[j+1] = uint8(c[idx][1])
+ dst[j+2] = uint8(c[idx][2])
+ dst[j+3] = 255
+ }
+ }
+ }
+ }
+ }
+
+ return dst, nil
+ })
+
+ RegisterConverter(ATC_RGBA_EXPLICIT_ALPHA_AMD(), RGBA(),
+ func(src []byte, width, height int) ([]byte, error) {
+ dst, j := make([]byte, width*height*4), 0
+
+ block_width := max(width/4, 1)
+ block_height := max(height/4, 1)
+
+ bs := binary.BitStream{Data: src}
+
+ a := [16]uint8{
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ }
+
+ c := [4][3]uint32{
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ {0, 0, 0},
+ }
+
+ for by := 0; by < block_height; by++ {
+ for bx := 0; bx < block_width; bx++ {
+ for i := 0; i < 16; i++ {
+ a[i] = uint8(bs.Read(4) << 4)
+ }
+ c[0][2] = bs.Read(5) << 3
+ c[0][1] = bs.Read(5) << 3
+ c[0][0] = bs.Read(5) << 3
+ bs.ReadBit()
+ c[3][2] = bs.Read(5) << 3
+ c[3][1] = bs.Read(6) << 2
+ c[3][0] = bs.Read(5) << 3
+ for i := 0; i < 3; i++ {
+ c[1][i] = (c[0][i]*2 + c[3][i]*1) / 3
+ c[2][i] = (c[0][i]*1 + c[3][i]*2) / 3
+ }
+ p := 0
+ for y := by * 4; y < (by+1)*4; y++ {
+ for x := bx * 4; x < (bx+1)*4; x++ {
+ idx := bs.Read(2)
+ if x < width && y < height {
+ j = 4 * (y*width + x)
+ dst[j+0] = uint8(c[idx][0])
+ dst[j+1] = uint8(c[idx][1])
+ dst[j+2] = uint8(c[idx][2])
+ dst[j+3] = a[p]
+ p++
+ }
+ }
+ }
+ }
+ }
+
+ return dst, nil
+ })
+}
diff --git a/image/convert.go b/image/convert.go
new file mode 100644
index 000000000..b5e6ad21b
--- /dev/null
+++ b/image/convert.go
@@ -0,0 +1,69 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+import "fmt"
+
+// Converter is used to convert the the image formed from the parameters data,
+// width and height into another format. If the conversion succeeds then the
+// converted image data is returned, otherwise an error is returned.
+type Converter func(data []byte, width int, height int) ([]byte, error)
+
+type srcDstFmt struct{ src, dst Format }
+
+var registeredConverters = make(map[srcDstFmt]Converter)
+
+// RegisterConverter registers the Converter for converting from src to dst
+// formats. If a converter already exists for converting from src to dst, then
+// this function panics.
+func RegisterConverter(src, dst Format, c Converter) {
+ key := srcDstFmt{src, dst}
+ if _, found := registeredConverters[key]; found {
+ panic(fmt.Errorf("Converter from %s to %s already registered", src, dst))
+ }
+ registeredConverters[key] = c
+}
+
+// Convert uses the registered Converters to convert the image formed from the
+// parameters data, width and height from srcFmt to dstFmt. If the conversion
+// succeeds then the converted image data is returned, otherwise an error is
+// returned.
+// If no direct converter has been registered to convert from srcFmt to dstFmt,
+// then Convert may try converting via an intermediate format.
+func Convert(data []byte, width int, height int, srcFmt Format, dstFmt Format) ([]byte, error) {
+ if srcFmt == dstFmt {
+ return data, nil // No conversion required.
+ }
+
+ if err := srcFmt.Check(data, width, height); err != nil {
+ return nil, fmt.Errorf("Source data of format %s is invalid: %s", srcFmt, err)
+ }
+
+ if conv, found := registeredConverters[srcDstFmt{srcFmt, dstFmt}]; found {
+ return conv(data, width, height)
+ }
+
+ // Try going via RGBA
+ if convA, found := registeredConverters[srcDstFmt{srcFmt, RGBA()}]; found {
+ if convB, found := registeredConverters[srcDstFmt{RGBA(), dstFmt}]; found {
+ if data, err := convA(data, width, height); err != nil {
+ return convB(data, width, height)
+ }
+ }
+ }
+
+ return nil, fmt.Errorf("No converter registered that can convert from format '%s' to '%s'\n",
+ srcFmt, dstFmt)
+}
diff --git a/image/doc.go b/image/doc.go
new file mode 100644
index 000000000..14b17f7b6
--- /dev/null
+++ b/image/doc.go
@@ -0,0 +1,17 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image provides functions for converting between various image
+// formats.
+package image
diff --git a/image/etc1.go b/image/etc1.go
new file mode 100644
index 000000000..8c4a1bf6f
--- /dev/null
+++ b/image/etc1.go
@@ -0,0 +1,108 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+type fmtETC1_RGB8_OES struct{}
+
+func (fmtETC1_RGB8_OES) String() string { return "ETC1_RGB8_OES" }
+func (fmtETC1_RGB8_OES) Check(d []byte, w, h int) error {
+ return checkSize(d, max(w, 4), max(h, 4), 4)
+}
+
+// ETC1_RGB8_OES returns a format representing the texture compression format
+// with the same name.
+func ETC1_RGB8_OES() Format { return fmtETC1_RGB8_OES{} }
+
+func init() {
+ RegisterConverter(ETC1_RGB8_OES(), RGBA(), func(src []byte, width, height int) ([]byte, error) {
+ dst := make([]byte, width*height*4)
+
+ block_width := max(width/4, 1)
+ block_height := max(height/4, 1)
+
+ c := [2][3]int32{}
+ codes := [2][4]int32{}
+ modTbl := [8][4]int32{
+ {2, 8, -2, -8},
+ {5, 17, -5, -17},
+ {9, 29, -9, -29},
+ {13, 42, -13, -42},
+ {18, 60, -18, -60},
+ {24, 80, -24, -80},
+ {33, 106, -33, -106},
+ {47, 183, -47, -183},
+ }
+ diffTbl := [8]int32{0, 1, 2, 3, -4, -3, -2, -1}
+ flipTbl := [2][16]int32{
+ {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1},
+ {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1},
+ }
+ for by := 0; by < block_height; by++ {
+ for bx := 0; bx < block_width; bx++ {
+ u64 := uint64(src[0])
+ u64 = (u64 << 8) | uint64(src[1])
+ u64 = (u64 << 8) | uint64(src[2])
+ u64 = (u64 << 8) | uint64(src[3])
+ u64 = (u64 << 8) | uint64(src[4])
+ u64 = (u64 << 8) | uint64(src[5])
+ u64 = (u64 << 8) | uint64(src[6])
+ u64 = (u64 << 8) | uint64(src[7])
+ src = src[8:]
+ flip := (u64 >> 32) & 1
+ diff := (u64 >> 33) & 1
+
+ codes[0] = modTbl[(u64>>37)&7]
+ codes[1] = modTbl[(u64>>34)&7]
+
+ for i := uint(0); i < 3; i++ {
+ if diff == 0 {
+ a := (u64 >> (44 + i*8)) & 15
+ b := (u64 >> (40 + i*8)) & 15
+ c[0][i] = int32((a << 4) | a)
+ c[1][i] = int32((b << 4) | b)
+ } else {
+ a := (u64 >> (43 + i*8)) & 31
+ b := (u64 >> (40 + i*8)) & 7
+ d := int32(int32(a) + diffTbl[b])
+ c[0][i] = int32((a << 3) | (a >> 2))
+ c[1][i] = int32((d << 3) | (d >> 2))
+ }
+ }
+
+ blockTbl := flipTbl[flip]
+
+ i := uint(0)
+ for x := bx * 4; x < (bx+1)*4; x++ {
+ for y := by * 4; y < (by+1)*4; y++ {
+ if x < width && y < height {
+ block := blockTbl[i]
+ base := c[block]
+ k := 4 * (y*width + x)
+ idx := ((u64 >> i) & 1) | ((u64 >> (15 + i)) & 2)
+ shift := codes[block][idx]
+ dst[k+0] = toByte(base[2] + shift)
+ dst[k+1] = toByte(base[1] + shift)
+ dst[k+2] = toByte(base[0] + shift)
+ dst[k+3] = 255
+ i++
+ }
+ }
+ }
+ }
+ }
+
+ return dst, nil
+ })
+}
diff --git a/image/format.go b/image/format.go
new file mode 100644
index 000000000..279f7e11b
--- /dev/null
+++ b/image/format.go
@@ -0,0 +1,44 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+import "fmt"
+
+// Format is the interface for an image and/or pixel format.
+//
+// Check returns an error if the combination of data, image width and image
+// height is invalid for the given format, otherwise Check returns nil.
+type Format interface {
+ Check(data []byte, width, height int) error
+}
+
+func checkSize(data []byte, width, height int, bpp int) error {
+ expected := width * height * bpp / 8
+ actual := len(data)
+ if expected != actual {
+ return fmt.Errorf("Image data size (0x%x) did not match expected (0x%x) for dimensions %dx%d\n",
+ actual, expected, width, height)
+ }
+ return nil
+}
+
+type fmtRGBA struct{}
+
+func (fmtRGBA) String() string { return "RGBA" }
+func (fmtRGBA) Check(d []byte, w, h int) error { return checkSize(d, w, h, 32) }
+
+// RGBA returns a format containing an 8-bit red, green, blue and alpha channel
+// per pixel.
+func RGBA() Format { return fmtRGBA{} }
diff --git a/image/lum.go b/image/lum.go
new file mode 100644
index 000000000..2bac04343
--- /dev/null
+++ b/image/lum.go
@@ -0,0 +1,40 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+type fmtLuminance struct{}
+
+func (fmtLuminance) String() string { return "Luminance" }
+func (fmtLuminance) Check(d []byte, w, h int) error { return checkSize(d, w, h, 8) }
+
+// Luminance returns a format containing a single 8-bit luminance channel per
+// pixel.
+func Luminance() Format { return fmtLuminance{} }
+
+func init() {
+ RegisterConverter(Luminance(), RGBA(),
+ func(src []byte, width, height int) ([]byte, error) {
+ dst, i, j := make([]byte, width*height*4), 0, 0
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ dst[j+0], dst[j+1], dst[j+2], dst[j+3] = src[i], src[i], src[i], 255
+ i++
+ j += 4
+ }
+ }
+
+ return dst, nil
+ })
+}
diff --git a/image/lum_alpha.go b/image/lum_alpha.go
new file mode 100644
index 000000000..7d9686a36
--- /dev/null
+++ b/image/lum_alpha.go
@@ -0,0 +1,40 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+type fmtLuminanceAlpha struct{}
+
+func (fmtLuminanceAlpha) String() string { return "LuminanceAlpha" }
+func (fmtLuminanceAlpha) Check(d []byte, w, h int) error { return checkSize(d, w, h, 16) }
+
+// LuminanceAlpha returns a format containing an 8-bit luminance and alpha
+// channel per pixel.
+func LuminanceAlpha() Format { return fmtLuminanceAlpha{} }
+
+func init() {
+ RegisterConverter(LuminanceAlpha(), RGBA(),
+ func(src []byte, width, height int) ([]byte, error) {
+ dst, i, j := make([]byte, width*height*4), 0, 0
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ dst[j+0], dst[j+1], dst[j+2], dst[j+3] = src[i+0], src[i+0], src[i+0], src[i+1]
+ i += 2
+ j += 4
+ }
+ }
+
+ return dst, nil
+ })
+}
diff --git a/image/png.go b/image/png.go
new file mode 100644
index 000000000..b8d0f4412
--- /dev/null
+++ b/image/png.go
@@ -0,0 +1,49 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+import (
+ "bytes"
+ "image"
+ "image/color"
+ "image/png"
+)
+
+type fmtPNG struct{}
+
+func (fmtPNG) String() string { return "PNG" }
+func (fmtPNG) Check(d []byte, w, h int) error { return nil }
+
+// PNG returns a format representing the the texture compression format with the
+// same name.
+func PNG() Format { return fmtPNG{} }
+
+func init() {
+ RegisterConverter(RGBA(), PNG(),
+ func(src []byte, width, height int) ([]byte, error) {
+ img := image.NewRGBA(image.Rect(0, 0, width, height))
+ i := 0
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ img.Set(x, y, color.RGBA{src[i+0], src[i+1], src[i+2], src[i+3]})
+ i += 4
+ }
+ }
+
+ buffer := bytes.Buffer{}
+ png.Encode(&buffer, img)
+ return buffer.Bytes(), nil
+ })
+}
diff --git a/image/rgb.go b/image/rgb.go
new file mode 100644
index 000000000..3d607f20e
--- /dev/null
+++ b/image/rgb.go
@@ -0,0 +1,40 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+type fmtRGB struct{}
+
+func (fmtRGB) String() string { return "RGB" }
+func (fmtRGB) Check(d []byte, w, h int) error { return checkSize(d, w, h, 24) }
+
+// RGB returns a format containing an 8-bit red, green and blue channel per
+// pixel.
+func RGB() Format { return fmtRGB{} }
+
+func init() {
+ RegisterConverter(RGB(), RGBA(),
+ func(src []byte, width, height int) ([]byte, error) {
+ dst, i, j := make([]byte, width*height*4), 0, 0
+ for y := 0; y < height; y++ {
+ for x := 0; x < width; x++ {
+ dst[j+0], dst[j+1], dst[j+2], dst[j+3] = src[i+0], src[i+1], src[i+2], 255
+ i += 3
+ j += 4
+ }
+ }
+
+ return dst, nil
+ })
+}
diff --git a/image/utils.go b/image/utils.go
new file mode 100644
index 000000000..0b838bed8
--- /dev/null
+++ b/image/utils.go
@@ -0,0 +1,41 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// 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 image
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ } else {
+ return b
+ }
+}
+
+func max(a, b int) int {
+ if a > b {
+ return a
+ } else {
+ return b
+ }
+}
+
+func toByte(i int32) byte {
+ if i < 0 {
+ return 0
+ }
+ if i > 255 {
+ return 255
+ }
+ return byte(i)
+}