gtsocial-umbx

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

scanner.go (5604B)


      1 package imaging
      2 
      3 import (
      4 	"image"
      5 	"image/color"
      6 )
      7 
      8 type scanner struct {
      9 	image   image.Image
     10 	w, h    int
     11 	palette []color.NRGBA
     12 }
     13 
     14 func newScanner(img image.Image) *scanner {
     15 	s := &scanner{
     16 		image: img,
     17 		w:     img.Bounds().Dx(),
     18 		h:     img.Bounds().Dy(),
     19 	}
     20 	if img, ok := img.(*image.Paletted); ok {
     21 		s.palette = make([]color.NRGBA, len(img.Palette))
     22 		for i := 0; i < len(img.Palette); i++ {
     23 			s.palette[i] = color.NRGBAModel.Convert(img.Palette[i]).(color.NRGBA)
     24 		}
     25 	}
     26 	return s
     27 }
     28 
     29 // scan scans the given rectangular region of the image into dst.
     30 func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) {
     31 	switch img := s.image.(type) {
     32 	case *image.NRGBA:
     33 		size := (x2 - x1) * 4
     34 		j := 0
     35 		i := y1*img.Stride + x1*4
     36 		if size == 4 {
     37 			for y := y1; y < y2; y++ {
     38 				d := dst[j : j+4 : j+4]
     39 				s := img.Pix[i : i+4 : i+4]
     40 				d[0] = s[0]
     41 				d[1] = s[1]
     42 				d[2] = s[2]
     43 				d[3] = s[3]
     44 				j += size
     45 				i += img.Stride
     46 			}
     47 		} else {
     48 			for y := y1; y < y2; y++ {
     49 				copy(dst[j:j+size], img.Pix[i:i+size])
     50 				j += size
     51 				i += img.Stride
     52 			}
     53 		}
     54 
     55 	case *image.NRGBA64:
     56 		j := 0
     57 		for y := y1; y < y2; y++ {
     58 			i := y*img.Stride + x1*8
     59 			for x := x1; x < x2; x++ {
     60 				s := img.Pix[i : i+8 : i+8]
     61 				d := dst[j : j+4 : j+4]
     62 				d[0] = s[0]
     63 				d[1] = s[2]
     64 				d[2] = s[4]
     65 				d[3] = s[6]
     66 				j += 4
     67 				i += 8
     68 			}
     69 		}
     70 
     71 	case *image.RGBA:
     72 		j := 0
     73 		for y := y1; y < y2; y++ {
     74 			i := y*img.Stride + x1*4
     75 			for x := x1; x < x2; x++ {
     76 				d := dst[j : j+4 : j+4]
     77 				a := img.Pix[i+3]
     78 				switch a {
     79 				case 0:
     80 					d[0] = 0
     81 					d[1] = 0
     82 					d[2] = 0
     83 					d[3] = a
     84 				case 0xff:
     85 					s := img.Pix[i : i+4 : i+4]
     86 					d[0] = s[0]
     87 					d[1] = s[1]
     88 					d[2] = s[2]
     89 					d[3] = a
     90 				default:
     91 					s := img.Pix[i : i+4 : i+4]
     92 					r16 := uint16(s[0])
     93 					g16 := uint16(s[1])
     94 					b16 := uint16(s[2])
     95 					a16 := uint16(a)
     96 					d[0] = uint8(r16 * 0xff / a16)
     97 					d[1] = uint8(g16 * 0xff / a16)
     98 					d[2] = uint8(b16 * 0xff / a16)
     99 					d[3] = a
    100 				}
    101 				j += 4
    102 				i += 4
    103 			}
    104 		}
    105 
    106 	case *image.RGBA64:
    107 		j := 0
    108 		for y := y1; y < y2; y++ {
    109 			i := y*img.Stride + x1*8
    110 			for x := x1; x < x2; x++ {
    111 				s := img.Pix[i : i+8 : i+8]
    112 				d := dst[j : j+4 : j+4]
    113 				a := s[6]
    114 				switch a {
    115 				case 0:
    116 					d[0] = 0
    117 					d[1] = 0
    118 					d[2] = 0
    119 				case 0xff:
    120 					d[0] = s[0]
    121 					d[1] = s[2]
    122 					d[2] = s[4]
    123 				default:
    124 					r32 := uint32(s[0])<<8 | uint32(s[1])
    125 					g32 := uint32(s[2])<<8 | uint32(s[3])
    126 					b32 := uint32(s[4])<<8 | uint32(s[5])
    127 					a32 := uint32(s[6])<<8 | uint32(s[7])
    128 					d[0] = uint8((r32 * 0xffff / a32) >> 8)
    129 					d[1] = uint8((g32 * 0xffff / a32) >> 8)
    130 					d[2] = uint8((b32 * 0xffff / a32) >> 8)
    131 				}
    132 				d[3] = a
    133 				j += 4
    134 				i += 8
    135 			}
    136 		}
    137 
    138 	case *image.Gray:
    139 		j := 0
    140 		for y := y1; y < y2; y++ {
    141 			i := y*img.Stride + x1
    142 			for x := x1; x < x2; x++ {
    143 				c := img.Pix[i]
    144 				d := dst[j : j+4 : j+4]
    145 				d[0] = c
    146 				d[1] = c
    147 				d[2] = c
    148 				d[3] = 0xff
    149 				j += 4
    150 				i++
    151 			}
    152 		}
    153 
    154 	case *image.Gray16:
    155 		j := 0
    156 		for y := y1; y < y2; y++ {
    157 			i := y*img.Stride + x1*2
    158 			for x := x1; x < x2; x++ {
    159 				c := img.Pix[i]
    160 				d := dst[j : j+4 : j+4]
    161 				d[0] = c
    162 				d[1] = c
    163 				d[2] = c
    164 				d[3] = 0xff
    165 				j += 4
    166 				i += 2
    167 			}
    168 		}
    169 
    170 	case *image.YCbCr:
    171 		j := 0
    172 		x1 += img.Rect.Min.X
    173 		x2 += img.Rect.Min.X
    174 		y1 += img.Rect.Min.Y
    175 		y2 += img.Rect.Min.Y
    176 
    177 		hy := img.Rect.Min.Y / 2
    178 		hx := img.Rect.Min.X / 2
    179 		for y := y1; y < y2; y++ {
    180 			iy := (y-img.Rect.Min.Y)*img.YStride + (x1 - img.Rect.Min.X)
    181 
    182 			var yBase int
    183 			switch img.SubsampleRatio {
    184 			case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio422:
    185 				yBase = (y - img.Rect.Min.Y) * img.CStride
    186 			case image.YCbCrSubsampleRatio420, image.YCbCrSubsampleRatio440:
    187 				yBase = (y/2 - hy) * img.CStride
    188 			}
    189 
    190 			for x := x1; x < x2; x++ {
    191 				var ic int
    192 				switch img.SubsampleRatio {
    193 				case image.YCbCrSubsampleRatio444, image.YCbCrSubsampleRatio440:
    194 					ic = yBase + (x - img.Rect.Min.X)
    195 				case image.YCbCrSubsampleRatio422, image.YCbCrSubsampleRatio420:
    196 					ic = yBase + (x/2 - hx)
    197 				default:
    198 					ic = img.COffset(x, y)
    199 				}
    200 
    201 				yy1 := int32(img.Y[iy]) * 0x10101
    202 				cb1 := int32(img.Cb[ic]) - 128
    203 				cr1 := int32(img.Cr[ic]) - 128
    204 
    205 				r := yy1 + 91881*cr1
    206 				if uint32(r)&0xff000000 == 0 {
    207 					r >>= 16
    208 				} else {
    209 					r = ^(r >> 31)
    210 				}
    211 
    212 				g := yy1 - 22554*cb1 - 46802*cr1
    213 				if uint32(g)&0xff000000 == 0 {
    214 					g >>= 16
    215 				} else {
    216 					g = ^(g >> 31)
    217 				}
    218 
    219 				b := yy1 + 116130*cb1
    220 				if uint32(b)&0xff000000 == 0 {
    221 					b >>= 16
    222 				} else {
    223 					b = ^(b >> 31)
    224 				}
    225 
    226 				d := dst[j : j+4 : j+4]
    227 				d[0] = uint8(r)
    228 				d[1] = uint8(g)
    229 				d[2] = uint8(b)
    230 				d[3] = 0xff
    231 
    232 				iy++
    233 				j += 4
    234 			}
    235 		}
    236 
    237 	case *image.Paletted:
    238 		j := 0
    239 		for y := y1; y < y2; y++ {
    240 			i := y*img.Stride + x1
    241 			for x := x1; x < x2; x++ {
    242 				c := s.palette[img.Pix[i]]
    243 				d := dst[j : j+4 : j+4]
    244 				d[0] = c.R
    245 				d[1] = c.G
    246 				d[2] = c.B
    247 				d[3] = c.A
    248 				j += 4
    249 				i++
    250 			}
    251 		}
    252 
    253 	default:
    254 		j := 0
    255 		b := s.image.Bounds()
    256 		x1 += b.Min.X
    257 		x2 += b.Min.X
    258 		y1 += b.Min.Y
    259 		y2 += b.Min.Y
    260 		for y := y1; y < y2; y++ {
    261 			for x := x1; x < x2; x++ {
    262 				r16, g16, b16, a16 := s.image.At(x, y).RGBA()
    263 				d := dst[j : j+4 : j+4]
    264 				switch a16 {
    265 				case 0xffff:
    266 					d[0] = uint8(r16 >> 8)
    267 					d[1] = uint8(g16 >> 8)
    268 					d[2] = uint8(b16 >> 8)
    269 					d[3] = 0xff
    270 				case 0:
    271 					d[0] = 0
    272 					d[1] = 0
    273 					d[2] = 0
    274 					d[3] = 0
    275 				default:
    276 					d[0] = uint8(((r16 * 0xffff) / a16) >> 8)
    277 					d[1] = uint8(((g16 * 0xffff) / a16) >> 8)
    278 					d[2] = uint8(((b16 * 0xffff) / a16) >> 8)
    279 					d[3] = uint8(a16 >> 8)
    280 				}
    281 				j += 4
    282 			}
    283 		}
    284 	}
    285 }