blob: b5e6ad21baf715badbf0fd93b49644834ff39493 [file] [log] [blame]
// 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)
}