mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 22:32:25 -05:00 
			
		
		
		
	
		
			
	
	
		
			86 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			86 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | package pngstructure | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"bufio" | ||
|  | 	"bytes" | ||
|  | 	"image" | ||
|  | 	"io" | ||
|  | 	"os" | ||
|  | 
 | ||
|  | 	"image/png" | ||
|  | 
 | ||
|  | 	riimage "github.com/dsoprea/go-utility/v2/image" | ||
|  | ) | ||
|  | 
 | ||
|  | // PngMediaParser knows how to parse a PNG stream. | ||
|  | type PngMediaParser struct { | ||
|  | } | ||
|  | 
 | ||
|  | // NewPngMediaParser returns a new `PngMediaParser`. | ||
|  | func NewPngMediaParser() riimage.MediaParser { | ||
|  | 	return new(PngMediaParser) | ||
|  | } | ||
|  | 
 | ||
|  | // Parse parses a PNG stream given a `io.ReadSeeker`. | ||
|  | func (pmp *PngMediaParser) Parse( | ||
|  | 	rs io.ReadSeeker, | ||
|  | 	size int, | ||
|  | ) (riimage.MediaContext, error) { | ||
|  | 	ps := NewPngSplitter() | ||
|  | 	if err := ps.readHeader(rs); err != nil { | ||
|  | 		return nil, err | ||
|  | 	} | ||
|  | 
 | ||
|  | 	s := bufio.NewScanner(rs) | ||
|  | 
 | ||
|  | 	// Since each segment can be any | ||
|  | 	// size, our buffer must be allowed | ||
|  | 	// to grow as large as the file. | ||
|  | 	buffer := []byte{} | ||
|  | 	s.Buffer(buffer, size) | ||
|  | 	s.Split(ps.Split) | ||
|  | 
 | ||
|  | 	for s.Scan() { | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if err := s.Err(); err != nil { | ||
|  | 		return nil, err | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return ps.Chunks() | ||
|  | } | ||
|  | 
 | ||
|  | // ParseFile parses a PNG stream given a file-path. | ||
|  | func (pmp *PngMediaParser) ParseFile(filepath string) (riimage.MediaContext, error) { | ||
|  | 	f, err := os.Open(filepath) | ||
|  | 	if err != nil { | ||
|  | 		return nil, err | ||
|  | 	} | ||
|  | 	defer f.Close() | ||
|  | 
 | ||
|  | 	stat, err := f.Stat() | ||
|  | 	if err != nil { | ||
|  | 		return nil, err | ||
|  | 	} | ||
|  | 
 | ||
|  | 	size := stat.Size() | ||
|  | 	return pmp.Parse(f, int(size)) | ||
|  | } | ||
|  | 
 | ||
|  | // ParseBytes parses a PNG stream given a byte-slice. | ||
|  | func (pmp *PngMediaParser) ParseBytes(data []byte) (riimage.MediaContext, error) { | ||
|  | 	br := bytes.NewReader(data) | ||
|  | 	return pmp.Parse(br, len(data)) | ||
|  | } | ||
|  | 
 | ||
|  | // LooksLikeFormat returns a boolean indicating | ||
|  | // whether the stream looks like a PNG image. | ||
|  | func (pmp *PngMediaParser) LooksLikeFormat(data []byte) bool { | ||
|  | 	return bytes.Equal(data[:len(PngSignature)], PngSignature[:]) | ||
|  | } | ||
|  | 
 | ||
|  | // GetImage returns an image.Image-compatible struct. | ||
|  | func (pmp *PngMediaParser) GetImage(r io.Reader) (img image.Image, err error) { | ||
|  | 	return png.Decode(r) | ||
|  | } |