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  }