9fans.net/go@v0.0.5/draw/memdraw/read.go (about)

     1  package memdraw
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  
     8  	"9fans.net/go/draw"
     9  )
    10  
    11  func readmemimage(fd *os.File) (*Image, error) {
    12  	var hdr [5*12 + 1]byte
    13  	if _, err := io.ReadFull(fd, hdr[:11]); err != nil {
    14  		return nil, fmt.Errorf("readimage: %v", err)
    15  	}
    16  	if string(hdr[:11]) == "compressed\n" {
    17  		return creadmemimage(fd)
    18  	}
    19  	if _, err := io.ReadFull(fd, hdr[11:5*12]); err != nil {
    20  		return nil, fmt.Errorf("readimage: %v", err)
    21  	}
    22  
    23  	/*
    24  	 * distinguish new channel descriptor from old ldepth.
    25  	 * channel descriptors have letters as well as numbers,
    26  	 * while ldepths are a single digit formatted as %-11d.
    27  	 */
    28  	new := false
    29  	var m int
    30  	for m = 0; m < 10; m++ {
    31  		if hdr[m] != ' ' {
    32  			new = true
    33  			break
    34  		}
    35  	}
    36  	if hdr[11] != ' ' {
    37  		return nil, fmt.Errorf("readimage: bad format")
    38  	}
    39  	var chan_ draw.Pix
    40  	if new {
    41  		s := string(hdr[:11])
    42  		var err error
    43  		chan_, err = draw.ParsePix(s)
    44  		if err != nil {
    45  			return nil, fmt.Errorf("readimage: %v", err)
    46  		}
    47  	} else {
    48  		ldepth := (int(hdr[10])) - '0'
    49  		if ldepth < 0 || ldepth > 3 {
    50  			return nil, fmt.Errorf("readimage: bad ldepth %d", ldepth)
    51  		}
    52  		chan_ = ldepthToPix[ldepth]
    53  	}
    54  	var r draw.Rectangle
    55  
    56  	r.Min.X = atoi(hdr[1*12 : 2*12])
    57  	r.Min.Y = atoi(hdr[2*12 : 3*12])
    58  	r.Max.X = atoi(hdr[3*12 : 4*12])
    59  	r.Max.Y = atoi(hdr[4*12 : 5*12])
    60  	if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y {
    61  		return nil, fmt.Errorf("readimage: bad rectangle")
    62  	}
    63  
    64  	miny := r.Min.Y
    65  	maxy := r.Max.Y
    66  
    67  	l := draw.BytesPerLine(r, chan_.Depth())
    68  	i, err := AllocImage(r, chan_)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	chunk := 32 * 1024
    73  	if chunk < l {
    74  		chunk = l
    75  	}
    76  	tmp := make([]byte, chunk)
    77  	for maxy > miny {
    78  		dy := maxy - miny
    79  		if dy*l > chunk {
    80  			dy = chunk / l
    81  		}
    82  		if dy <= 0 {
    83  			Free(i)
    84  			return nil, fmt.Errorf("readmemimage: image too wide for buffer")
    85  		}
    86  		n := dy * l
    87  		if _, err = io.ReadFull(fd, tmp[:n]); err != nil {
    88  			Free(i)
    89  			return nil, fmt.Errorf("readmemimage: %v", err)
    90  		}
    91  		if !new {
    92  			for j := 0; j < chunk; j++ {
    93  				tmp[j] ^= 0xFF
    94  			}
    95  		}
    96  
    97  		if _, err := loadmemimage(i, draw.Rect(r.Min.X, miny, r.Max.X, miny+dy), tmp[:n]); err != nil {
    98  			Free(i)
    99  			return nil, err
   100  		}
   101  		miny += dy
   102  	}
   103  	return i, nil
   104  }