github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/jxr/reader.go (about) 1 // Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package jxr 6 7 import "C" 8 import ( 9 "fmt" 10 "image" 11 "image/color" 12 "io" 13 "io/ioutil" 14 15 "github.com/chai2010/gopkg/builtin" 16 image_ext "github.com/chai2010/gopkg/image" 17 color_ext "github.com/chai2010/gopkg/image/color" 18 "github.com/chai2010/gopkg/image/convert" 19 ) 20 21 const ( 22 leHeader = "II\xBC\x00" // Header for little-endian files. 23 beHeader = "MM\xBC\x2A" // Header for big-endian files. 24 25 ifdLen = 12 // Length of an IFD entry in bytes. 26 ) 27 28 func decodeConfig(data []byte) (config image.Config, err error) { 29 width, height, channels, depth, data_type, err := jxr_decode_config(data) 30 if err != nil { 31 return 32 } 33 34 if data_type != jxr_unsigned { 35 err = fmt.Errorf("jxr: unsupported data type: %v", data_type) 36 return 37 } 38 39 config.Width = int(width) 40 config.Height = int(height) 41 42 switch data_type { 43 case jxr_unsigned: 44 switch { 45 case channels == 1 && depth == 8: 46 config.ColorModel = color.GrayModel 47 case channels == 1 && depth == 16: 48 config.ColorModel = color.Gray16Model 49 case channels == 3 && depth == 8: 50 config.ColorModel = color.RGBAModel 51 case channels == 3 && depth == 16: 52 config.ColorModel = color.RGBA64Model 53 case channels == 4 && depth == 8: 54 config.ColorModel = color.RGBAModel 55 case channels == 4 && depth == 16: 56 config.ColorModel = color.RGBA64Model 57 } 58 case jxr_float: 59 switch { 60 case channels == 1 && depth == 32: 61 config.ColorModel = color_ext.Gray32fModel 62 case channels == 3 && depth == 32: 63 config.ColorModel = color_ext.RGBA128fModel 64 case channels == 4 && depth == 32: 65 config.ColorModel = color_ext.RGBA128fModel 66 } 67 } 68 if config.ColorModel == nil { 69 err = fmt.Errorf("jxr: unsupported data type: %v", data_type) 70 return 71 } 72 return 73 } 74 75 // Options are the encoding and decoding parameters. 76 type Options struct { 77 ColorModel color.Model 78 } 79 80 // DecodeConfig returns the color model and dimensions of a JPEG/XR image without 81 // decoding the entire image. 82 func DecodeConfig(r io.Reader) (config image.Config, err error) { 83 data, err := ioutil.ReadAll(r) 84 if err != nil { 85 return 86 } 87 return decodeConfig(data) 88 } 89 90 // Decode reads a JPEG/XR image from r and returns it as an image.Image. 91 func Decode(r io.Reader, opt *Options) (m image.Image, err error) { 92 data, err := ioutil.ReadAll(r) 93 if err != nil { 94 return 95 } 96 97 var config image.Config 98 if config, err = decodeConfig(data); err != nil { 99 return 100 } 101 102 var channels C.int 103 switch config.ColorModel { 104 case color.GrayModel: 105 gray := image.NewGray(image.Rect(0, 0, config.Width, config.Height)) 106 if _, _, _, _, _, err = jxr_decode(data, gray.Pix, gray.Stride); err != nil { 107 return 108 } 109 m = gray 110 case color.Gray16Model: 111 gray16 := image.NewGray16(image.Rect(0, 0, config.Width, config.Height)) 112 if _, _, _, _, _, err = jxr_decode(data, gray16.Pix, gray16.Stride); err != nil { 113 return 114 } 115 m = gray16 116 case color_ext.Gray32fModel: 117 gray32f := image_ext.NewGray32f(image.Rect(0, 0, config.Width, config.Height)) 118 if _, _, _, _, _, err = jxr_decode(data, gray32f.Pix, gray32f.Stride); err != nil { 119 return 120 } 121 m = gray32f 122 case color.RGBAModel: 123 rgba := image.NewRGBA(image.Rect(0, 0, config.Width, config.Height)) 124 if _, _, channels, _, _, err = jxr_decode(data, rgba.Pix, rgba.Stride); err != nil { 125 return 126 } 127 if channels == 3 { 128 b := rgba.Bounds() 129 for y := 0; y < b.Max.Y; y++ { 130 d := rgba.Pix[y*rgba.Stride:] 131 for x := b.Max.X - 1; x >= 0; x-- { 132 copy(d[x*4:][:3], d[x*3:]) 133 d[x*4+3] = 0xff 134 } 135 } 136 } 137 m = rgba 138 case color.RGBA64Model: 139 rgba64 := image.NewRGBA64(image.Rect(0, 0, config.Width, config.Height)) 140 if _, _, channels, _, _, err = jxr_decode(data, rgba64.Pix, rgba64.Stride); err != nil { 141 return 142 } 143 if channels == 3 { 144 b := rgba64.Bounds() 145 for y := 0; y < b.Max.Y; y++ { 146 d := rgba64.Pix[y*rgba64.Stride:] 147 for x := b.Max.X - 1; x >= 0; x-- { 148 copy(d[x*8:][:6], d[x*6:]) 149 d[x*8+7] = 0xff 150 d[x*8+6] = 0xff 151 } 152 } 153 } 154 m = rgba64 155 case color_ext.RGBA128fModel: 156 rgba128f := image_ext.NewRGBA128f(image.Rect(0, 0, config.Width, config.Height)) 157 if _, _, channels, _, _, err = jxr_decode(data, rgba128f.Pix, rgba128f.Stride); err != nil { 158 return 159 } 160 if channels == 3 { 161 b := rgba128f.Bounds() 162 for y := 0; y < b.Max.Y; y++ { 163 d := rgba128f.Pix[y*rgba128f.Stride:] 164 for x := b.Max.X - 1; x >= 0; x-- { 165 copy(d[x*8:][:6], d[x*6:]) 166 builtin.PutFloat32(d[x*8+6:], 0xffff) 167 } 168 } 169 } 170 m = rgba128f 171 } 172 if m == nil { 173 err = fmt.Errorf("jxr: Decode, unsupported colot model: %T", config.ColorModel) 174 return 175 } 176 if opt != nil && opt.ColorModel != nil { 177 m = convert.ColorModel(m, opt.ColorModel) 178 } 179 return 180 } 181 182 func imageDecode(r io.Reader) (image.Image, error) { 183 return Decode(r, nil) 184 } 185 186 func imageExtDecode(r io.Reader, opt interface{}) (image.Image, error) { 187 if opt, ok := opt.(*Options); ok { 188 return Decode(r, opt) 189 } else { 190 return Decode(r, nil) 191 } 192 } 193 194 func imageExtEncode(w io.Writer, m image.Image, opt interface{}) error { 195 if opt, ok := opt.(*Options); ok { 196 return Encode(w, m, opt) 197 } else { 198 return Encode(w, m, nil) 199 } 200 } 201 202 func init() { 203 image.RegisterFormat("jxr", "II\xBC\x00", imageDecode, DecodeConfig) 204 image.RegisterFormat("jxr", "II\xBC\x01", imageDecode, DecodeConfig) 205 206 image_ext.RegisterFormat(image_ext.Format{ 207 Name: "jxr", 208 Extensions: []string{".jxr", ".wdp"}, 209 Magics: []string{"II\xBC\x00", "II\xBC\x01"}, 210 DecodeConfig: DecodeConfig, 211 Decode: imageExtDecode, 212 Encode: imageExtEncode, 213 }) 214 }