gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

info.go (2606B)


      1 package photoshopinfo
      2 
      3 import (
      4 	"fmt"
      5 	"io"
      6 
      7 	"encoding/binary"
      8 
      9 	"github.com/dsoprea/go-logging"
     10 )
     11 
     12 var (
     13 	defaultByteOrder = binary.BigEndian
     14 )
     15 
     16 // Photoshop30InfoRecord is the data for one parsed Photoshop-info record.
     17 type Photoshop30InfoRecord struct {
     18 	// RecordType is the record-type.
     19 	RecordType string
     20 
     21 	// ImageResourceId is the image resource-ID.
     22 	ImageResourceId uint16
     23 
     24 	// Name is the name of the record. It is optional and will be an empty-
     25 	// string if not present.
     26 	Name string
     27 
     28 	// Data is the raw record data.
     29 	Data []byte
     30 }
     31 
     32 // String returns a descriptive string.
     33 func (pir Photoshop30InfoRecord) String() string {
     34 	return fmt.Sprintf("RECORD-TYPE=[%s] IMAGE-RESOURCE-ID=[0x%04x] NAME=[%s] DATA-SIZE=(%d)", pir.RecordType, pir.ImageResourceId, pir.Name, len(pir.Data))
     35 }
     36 
     37 // ReadPhotoshop30InfoRecord parses a single photoshop-info record.
     38 func ReadPhotoshop30InfoRecord(r io.Reader) (pir Photoshop30InfoRecord, err error) {
     39 	defer func() {
     40 		if state := recover(); state != nil {
     41 			err = log.Wrap(state.(error))
     42 		}
     43 	}()
     44 
     45 	recordType := make([]byte, 4)
     46 	_, err = io.ReadFull(r, recordType)
     47 	if err != nil {
     48 		if err == io.EOF {
     49 			return pir, err
     50 		}
     51 
     52 		log.Panic(err)
     53 	}
     54 
     55 	// TODO(dustin): Move BigEndian to constant/config.
     56 
     57 	irId := uint16(0)
     58 	err = binary.Read(r, defaultByteOrder, &irId)
     59 	log.PanicIf(err)
     60 
     61 	nameSize := uint8(0)
     62 	err = binary.Read(r, defaultByteOrder, &nameSize)
     63 	log.PanicIf(err)
     64 
     65 	// Add an extra byte if the two length+data size is odd to make the total
     66 	// bytes read even.
     67 	doAddPadding := (1+nameSize)%2 == 1
     68 	if doAddPadding == true {
     69 		nameSize++
     70 	}
     71 
     72 	name := make([]byte, nameSize)
     73 	_, err = io.ReadFull(r, name)
     74 	log.PanicIf(err)
     75 
     76 	// If the last byte is padding, truncate it.
     77 	if doAddPadding == true {
     78 		name = name[:nameSize-1]
     79 	}
     80 
     81 	dataSize := uint32(0)
     82 	err = binary.Read(r, defaultByteOrder, &dataSize)
     83 	log.PanicIf(err)
     84 
     85 	data := make([]byte, dataSize+dataSize%2)
     86 	_, err = io.ReadFull(r, data)
     87 	log.PanicIf(err)
     88 
     89 	data = data[:dataSize]
     90 
     91 	pir = Photoshop30InfoRecord{
     92 		RecordType:      string(recordType),
     93 		ImageResourceId: irId,
     94 		Name:            string(name),
     95 		Data:            data,
     96 	}
     97 
     98 	return pir, nil
     99 }
    100 
    101 // ReadPhotoshop30Info parses a sequence of photoship-info records from the stream.
    102 func ReadPhotoshop30Info(r io.Reader) (pirIndex map[uint16]Photoshop30InfoRecord, err error) {
    103 	pirIndex = make(map[uint16]Photoshop30InfoRecord)
    104 
    105 	for {
    106 		pir, err := ReadPhotoshop30InfoRecord(r)
    107 		if err != nil {
    108 			if err == io.EOF {
    109 				break
    110 			}
    111 
    112 			log.Panic(err)
    113 		}
    114 
    115 		pirIndex[pir.ImageResourceId] = pir
    116 	}
    117 
    118 	return pirIndex, nil
    119 }