...

Source file src/github.com/dsoprea/go-exif/v3/undefined/exif_8828_oecf.go

Documentation: github.com/dsoprea/go-exif/v3/undefined

     1  package exifundefined
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  
     7  	"encoding/binary"
     8  
     9  	"github.com/dsoprea/go-logging"
    10  
    11  	"github.com/dsoprea/go-exif/v3/common"
    12  )
    13  
    14  type Tag8828Oecf struct {
    15  	Columns     uint16
    16  	Rows        uint16
    17  	ColumnNames []string
    18  	Values      []exifcommon.SignedRational
    19  }
    20  
    21  func (oecf Tag8828Oecf) String() string {
    22  	return fmt.Sprintf("Tag8828Oecf<COLUMNS=(%d) ROWS=(%d)>", oecf.Columns, oecf.Rows)
    23  }
    24  
    25  func (oecf Tag8828Oecf) EncoderName() string {
    26  	return "Codec8828Oecf"
    27  }
    28  
    29  type Codec8828Oecf struct {
    30  }
    31  
    32  func (Codec8828Oecf) Encode(value interface{}, byteOrder binary.ByteOrder) (encoded []byte, unitCount uint32, err error) {
    33  	defer func() {
    34  		if state := recover(); state != nil {
    35  			err = log.Wrap(state.(error))
    36  		}
    37  	}()
    38  
    39  	// TODO(dustin): Add test
    40  
    41  	oecf, ok := value.(Tag8828Oecf)
    42  	if ok == false {
    43  		log.Panicf("can only encode a Tag8828Oecf")
    44  	}
    45  
    46  	b := new(bytes.Buffer)
    47  
    48  	err = binary.Write(b, byteOrder, oecf.Columns)
    49  	log.PanicIf(err)
    50  
    51  	err = binary.Write(b, byteOrder, oecf.Rows)
    52  	log.PanicIf(err)
    53  
    54  	for _, name := range oecf.ColumnNames {
    55  		_, err := b.Write([]byte(name))
    56  		log.PanicIf(err)
    57  
    58  		_, err = b.Write([]byte{0})
    59  		log.PanicIf(err)
    60  	}
    61  
    62  	ve := exifcommon.NewValueEncoder(byteOrder)
    63  
    64  	ed, err := ve.Encode(oecf.Values)
    65  	log.PanicIf(err)
    66  
    67  	_, err = b.Write(ed.Encoded)
    68  	log.PanicIf(err)
    69  
    70  	return b.Bytes(), uint32(b.Len()), nil
    71  }
    72  
    73  func (Codec8828Oecf) Decode(valueContext *exifcommon.ValueContext) (value EncodeableValue, err error) {
    74  	defer func() {
    75  		if state := recover(); state != nil {
    76  			err = log.Wrap(state.(error))
    77  		}
    78  	}()
    79  
    80  	// TODO(dustin): Add test using known good data.
    81  
    82  	valueContext.SetUndefinedValueType(exifcommon.TypeByte)
    83  
    84  	valueBytes, err := valueContext.ReadBytes()
    85  	log.PanicIf(err)
    86  
    87  	oecf := Tag8828Oecf{}
    88  
    89  	oecf.Columns = valueContext.ByteOrder().Uint16(valueBytes[0:2])
    90  	oecf.Rows = valueContext.ByteOrder().Uint16(valueBytes[2:4])
    91  
    92  	columnNames := make([]string, oecf.Columns)
    93  
    94  	// startAt is where the current column name starts.
    95  	startAt := 4
    96  
    97  	// offset is our current position.
    98  	offset := startAt
    99  
   100  	currentColumnNumber := uint16(0)
   101  
   102  	for currentColumnNumber < oecf.Columns {
   103  		if valueBytes[offset] == 0 {
   104  			columnName := string(valueBytes[startAt:offset])
   105  			if len(columnName) == 0 {
   106  				log.Panicf("SFR column (%d) has zero length", currentColumnNumber)
   107  			}
   108  
   109  			columnNames[currentColumnNumber] = columnName
   110  			currentColumnNumber++
   111  
   112  			offset++
   113  			startAt = offset
   114  			continue
   115  		}
   116  
   117  		offset++
   118  	}
   119  
   120  	oecf.ColumnNames = columnNames
   121  
   122  	rawRationalBytes := valueBytes[offset:]
   123  
   124  	rationalSize := exifcommon.TypeSignedRational.Size()
   125  	if len(rawRationalBytes)%rationalSize > 0 {
   126  		log.Panicf("OECF signed-rationals not aligned: (%d) %% (%d) > 0", len(rawRationalBytes), rationalSize)
   127  	}
   128  
   129  	rationalCount := len(rawRationalBytes) / rationalSize
   130  
   131  	parser := new(exifcommon.Parser)
   132  
   133  	byteOrder := valueContext.ByteOrder()
   134  
   135  	items, err := parser.ParseSignedRationals(rawRationalBytes, uint32(rationalCount), byteOrder)
   136  	log.PanicIf(err)
   137  
   138  	oecf.Values = items
   139  
   140  	return oecf, nil
   141  }
   142  
   143  func init() {
   144  	registerDecoder(
   145  		exifcommon.IfdExifStandardIfdIdentity.UnindexedString(),
   146  		0x8828,
   147  		Codec8828Oecf{})
   148  }
   149  

View as plain text