github.com/andybalholm/giopdf@v0.0.0-20220317170119-aad9a095ad48/image.go (about) 1 package giopdf 2 3 import ( 4 "fmt" 5 "image" 6 "image/color" 7 "image/jpeg" 8 "io" 9 10 "github.com/andybalholm/giopdf/pdf" 11 ) 12 13 func decodeImage(img pdf.Value) (image.Image, error) { 14 if img.HasFilter("DCTDecode") { 15 // It's a JPEG image. 16 return jpeg.Decode(img.EncodedReader("DCTDecode")) 17 } 18 19 data, err := io.ReadAll(img.Reader()) 20 if err != nil { 21 return nil, err 22 } 23 cs := img.Key("ColorSpace").Name() 24 bits := img.Key("BitsPerComponent").Int() 25 switch { 26 case cs == "DeviceGray" && bits == 1: 27 result := &bitmapImage{ 28 Width: img.Key("Width").Int(), 29 Height: img.Key("Height").Int(), 30 Data: data, 31 Foreground: color.White, 32 Background: color.Black, 33 } 34 switch img.Key("Decode").String() { 35 case "[0, 1]", "<nil>": 36 // Default; leave values unchanged. 37 case "[1, 0]": 38 result.Background = color.White 39 result.Foreground = color.Black 40 default: 41 return nil, fmt.Errorf("unsupported Decode array: %v", img.Key("Decode")) 42 } 43 return result, nil 44 } 45 46 return nil, fmt.Errorf("unsupported image (ColorSpace: %v, BitsPerComponent: %d)", img.Key("ColorSpace"), bits) 47 } 48 49 type bitmapImage struct { 50 Width int 51 Height int 52 Data []byte 53 Foreground color.Color 54 Background color.Color 55 } 56 57 func (bi *bitmapImage) ColorModel() color.Model { 58 return color.GrayModel 59 } 60 61 func (bi *bitmapImage) Bounds() image.Rectangle { 62 return image.Rect(0, 0, bi.Width, bi.Height) 63 } 64 65 func (bi *bitmapImage) At(x, y int) color.Color { 66 stride := bi.Width / 8 67 if bi.Width%8 != 0 { 68 stride += 1 69 } 70 b := bi.Data[stride*y+x/8] 71 b &= 1 << (7 - x%8) 72 73 if b == 0 { 74 return bi.Background 75 } 76 return bi.Foreground 77 }