1
2
3
4
5 package jpeg
6
7 import (
8 "bufio"
9 "errors"
10 "image"
11 "image/color"
12 "io"
13 )
14
15
16 func div(a, b int32) int32 {
17 if a >= 0 {
18 return (a + (b >> 1)) / b
19 }
20 return -((-a + (b >> 1)) / b)
21 }
22
23
24 var bitCount = [256]byte{
25 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
26 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
27 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
28 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
29 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
30 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
31 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
32 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
33 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
34 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
35 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
36 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
37 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
38 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
39 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
40 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
41 }
42
43 type quantIndex int
44
45 const (
46 quantIndexLuminance quantIndex = iota
47 quantIndexChrominance
48 nQuantIndex
49 )
50
51
52
53
54
55 var unscaledQuant = [nQuantIndex][blockSize]byte{
56
57 {
58 16, 11, 12, 14, 12, 10, 16, 14,
59 13, 14, 18, 17, 16, 19, 24, 40,
60 26, 24, 22, 22, 24, 49, 35, 37,
61 29, 40, 58, 51, 61, 60, 57, 51,
62 56, 55, 64, 72, 92, 78, 64, 68,
63 87, 69, 55, 56, 80, 109, 81, 87,
64 95, 98, 103, 104, 103, 62, 77, 113,
65 121, 112, 100, 120, 92, 101, 103, 99,
66 },
67
68 {
69 17, 18, 18, 24, 21, 24, 47, 26,
70 26, 47, 99, 66, 56, 66, 99, 99,
71 99, 99, 99, 99, 99, 99, 99, 99,
72 99, 99, 99, 99, 99, 99, 99, 99,
73 99, 99, 99, 99, 99, 99, 99, 99,
74 99, 99, 99, 99, 99, 99, 99, 99,
75 99, 99, 99, 99, 99, 99, 99, 99,
76 99, 99, 99, 99, 99, 99, 99, 99,
77 },
78 }
79
80 type huffIndex int
81
82 const (
83 huffIndexLuminanceDC huffIndex = iota
84 huffIndexLuminanceAC
85 huffIndexChrominanceDC
86 huffIndexChrominanceAC
87 nHuffIndex
88 )
89
90
91 type huffmanSpec struct {
92
93 count [16]byte
94
95 value []byte
96 }
97
98
99
100 var theHuffmanSpec = [nHuffIndex]huffmanSpec{
101
102 {
103 [16]byte{0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},
104 []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
105 },
106
107 {
108 [16]byte{0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125},
109 []byte{
110 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
111 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
112 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
113 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
114 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
115 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
116 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
117 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
118 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
119 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
120 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
121 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
122 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
123 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
124 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
125 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
126 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
127 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
128 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
129 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
130 0xf9, 0xfa,
131 },
132 },
133
134 {
135 [16]byte{0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
136 []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
137 },
138
139 {
140 [16]byte{0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119},
141 []byte{
142 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
143 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
144 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
145 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
146 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
147 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
148 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
149 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
150 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
151 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
152 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
153 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
154 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
155 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
156 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
157 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
158 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
159 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
160 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
161 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
162 0xf9, 0xfa,
163 },
164 },
165 }
166
167
168
169
170
171 type huffmanLUT []uint32
172
173 func (h *huffmanLUT) init(s huffmanSpec) {
174 maxValue := 0
175 for _, v := range s.value {
176 if int(v) > maxValue {
177 maxValue = int(v)
178 }
179 }
180 *h = make([]uint32, maxValue+1)
181 code, k := uint32(0), 0
182 for i := 0; i < len(s.count); i++ {
183 nBits := uint32(i+1) << 24
184 for j := uint8(0); j < s.count[i]; j++ {
185 (*h)[s.value[k]] = nBits | code
186 code++
187 k++
188 }
189 code <<= 1
190 }
191 }
192
193
194 var theHuffmanLUT [4]huffmanLUT
195
196 func init() {
197 for i, s := range theHuffmanSpec {
198 theHuffmanLUT[i].init(s)
199 }
200 }
201
202
203 type writer interface {
204 Flush() error
205 io.Writer
206 io.ByteWriter
207 }
208
209
210 type encoder struct {
211
212
213 w writer
214 err error
215
216 buf [16]byte
217
218 bits, nBits uint32
219
220 quant [nQuantIndex][blockSize]byte
221 }
222
223 func (e *encoder) flush() {
224 if e.err != nil {
225 return
226 }
227 e.err = e.w.Flush()
228 }
229
230 func (e *encoder) write(p []byte) {
231 if e.err != nil {
232 return
233 }
234 _, e.err = e.w.Write(p)
235 }
236
237 func (e *encoder) writeByte(b byte) {
238 if e.err != nil {
239 return
240 }
241 e.err = e.w.WriteByte(b)
242 }
243
244
245
246 func (e *encoder) emit(bits, nBits uint32) {
247 nBits += e.nBits
248 bits <<= 32 - nBits
249 bits |= e.bits
250 for nBits >= 8 {
251 b := uint8(bits >> 24)
252 e.writeByte(b)
253 if b == 0xff {
254 e.writeByte(0x00)
255 }
256 bits <<= 8
257 nBits -= 8
258 }
259 e.bits, e.nBits = bits, nBits
260 }
261
262
263 func (e *encoder) emitHuff(h huffIndex, value int32) {
264 x := theHuffmanLUT[h][value]
265 e.emit(x&(1<<24-1), x>>24)
266 }
267
268
269
270 func (e *encoder) emitHuffRLE(h huffIndex, runLength, value int32) {
271 a, b := value, value
272 if a < 0 {
273 a, b = -value, value-1
274 }
275 var nBits uint32
276 if a < 0x100 {
277 nBits = uint32(bitCount[a])
278 } else {
279 nBits = 8 + uint32(bitCount[a>>8])
280 }
281 e.emitHuff(h, runLength<<4|int32(nBits))
282 if nBits > 0 {
283 e.emit(uint32(b)&(1<<nBits-1), nBits)
284 }
285 }
286
287
288 func (e *encoder) writeMarkerHeader(marker uint8, markerlen int) {
289 e.buf[0] = 0xff
290 e.buf[1] = marker
291 e.buf[2] = uint8(markerlen >> 8)
292 e.buf[3] = uint8(markerlen & 0xff)
293 e.write(e.buf[:4])
294 }
295
296
297 func (e *encoder) writeDQT() {
298 const markerlen = 2 + int(nQuantIndex)*(1+blockSize)
299 e.writeMarkerHeader(dqtMarker, markerlen)
300 for i := range e.quant {
301 e.writeByte(uint8(i))
302 e.write(e.quant[i][:])
303 }
304 }
305
306
307 func (e *encoder) writeSOF0(size image.Point, nComponent int) {
308 markerlen := 8 + 3*nComponent
309 e.writeMarkerHeader(sof0Marker, markerlen)
310 e.buf[0] = 8
311 e.buf[1] = uint8(size.Y >> 8)
312 e.buf[2] = uint8(size.Y & 0xff)
313 e.buf[3] = uint8(size.X >> 8)
314 e.buf[4] = uint8(size.X & 0xff)
315 e.buf[5] = uint8(nComponent)
316 if nComponent == 1 {
317 e.buf[6] = 1
318
319 e.buf[7] = 0x11
320 e.buf[8] = 0x00
321 } else {
322 for i := 0; i < nComponent; i++ {
323 e.buf[3*i+6] = uint8(i + 1)
324
325 e.buf[3*i+7] = "\x22\x11\x11"[i]
326 e.buf[3*i+8] = "\x00\x01\x01"[i]
327 }
328 }
329 e.write(e.buf[:3*(nComponent-1)+9])
330 }
331
332
333 func (e *encoder) writeDHT(nComponent int) {
334 markerlen := 2
335 specs := theHuffmanSpec[:]
336 if nComponent == 1 {
337
338 specs = specs[:2]
339 }
340 for _, s := range specs {
341 markerlen += 1 + 16 + len(s.value)
342 }
343 e.writeMarkerHeader(dhtMarker, markerlen)
344 for i, s := range specs {
345 e.writeByte("\x00\x10\x01\x11"[i])
346 e.write(s.count[:])
347 e.write(s.value)
348 }
349 }
350
351
352
353
354 func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int32) int32 {
355 fdct(b)
356
357 dc := div(b[0], 8*int32(e.quant[q][0]))
358 e.emitHuffRLE(huffIndex(2*q+0), 0, dc-prevDC)
359
360 h, runLength := huffIndex(2*q+1), int32(0)
361 for zig := 1; zig < blockSize; zig++ {
362 ac := div(b[unzig[zig]], 8*int32(e.quant[q][zig]))
363 if ac == 0 {
364 runLength++
365 } else {
366 for runLength > 15 {
367 e.emitHuff(h, 0xf0)
368 runLength -= 16
369 }
370 e.emitHuffRLE(h, runLength, ac)
371 runLength = 0
372 }
373 }
374 if runLength > 0 {
375 e.emitHuff(h, 0x00)
376 }
377 return dc
378 }
379
380
381
382 func toYCbCr(m image.Image, p image.Point, yBlock, cbBlock, crBlock *block) {
383 b := m.Bounds()
384 xmax := b.Max.X - 1
385 ymax := b.Max.Y - 1
386 for j := 0; j < 8; j++ {
387 for i := 0; i < 8; i++ {
388 r, g, b, _ := m.At(min(p.X+i, xmax), min(p.Y+j, ymax)).RGBA()
389 yy, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
390 yBlock[8*j+i] = int32(yy)
391 cbBlock[8*j+i] = int32(cb)
392 crBlock[8*j+i] = int32(cr)
393 }
394 }
395 }
396
397
398 func grayToY(m *image.Gray, p image.Point, yBlock *block) {
399 b := m.Bounds()
400 xmax := b.Max.X - 1
401 ymax := b.Max.Y - 1
402 pix := m.Pix
403 for j := 0; j < 8; j++ {
404 for i := 0; i < 8; i++ {
405 idx := m.PixOffset(min(p.X+i, xmax), min(p.Y+j, ymax))
406 yBlock[8*j+i] = int32(pix[idx])
407 }
408 }
409 }
410
411
412 func rgbaToYCbCr(m *image.RGBA, p image.Point, yBlock, cbBlock, crBlock *block) {
413 b := m.Bounds()
414 xmax := b.Max.X - 1
415 ymax := b.Max.Y - 1
416 for j := 0; j < 8; j++ {
417 sj := p.Y + j
418 if sj > ymax {
419 sj = ymax
420 }
421 offset := (sj-b.Min.Y)*m.Stride - b.Min.X*4
422 for i := 0; i < 8; i++ {
423 sx := p.X + i
424 if sx > xmax {
425 sx = xmax
426 }
427 pix := m.Pix[offset+sx*4:]
428 yy, cb, cr := color.RGBToYCbCr(pix[0], pix[1], pix[2])
429 yBlock[8*j+i] = int32(yy)
430 cbBlock[8*j+i] = int32(cb)
431 crBlock[8*j+i] = int32(cr)
432 }
433 }
434 }
435
436
437 func yCbCrToYCbCr(m *image.YCbCr, p image.Point, yBlock, cbBlock, crBlock *block) {
438 b := m.Bounds()
439 xmax := b.Max.X - 1
440 ymax := b.Max.Y - 1
441 for j := 0; j < 8; j++ {
442 sy := p.Y + j
443 if sy > ymax {
444 sy = ymax
445 }
446 for i := 0; i < 8; i++ {
447 sx := p.X + i
448 if sx > xmax {
449 sx = xmax
450 }
451 yi := m.YOffset(sx, sy)
452 ci := m.COffset(sx, sy)
453 yBlock[8*j+i] = int32(m.Y[yi])
454 cbBlock[8*j+i] = int32(m.Cb[ci])
455 crBlock[8*j+i] = int32(m.Cr[ci])
456 }
457 }
458 }
459
460
461
462 func scale(dst *block, src *[4]block) {
463 for i := 0; i < 4; i++ {
464 dstOff := (i&2)<<4 | (i&1)<<2
465 for y := 0; y < 4; y++ {
466 for x := 0; x < 4; x++ {
467 j := 16*y + 2*x
468 sum := src[i][j] + src[i][j+1] + src[i][j+8] + src[i][j+9]
469 dst[8*y+x+dstOff] = (sum + 2) >> 2
470 }
471 }
472 }
473 }
474
475
476
477
478
479
480
481
482 var sosHeaderY = []byte{
483 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00,
484 }
485
486
487
488
489
490
491
492
493
494
495 var sosHeaderYCbCr = []byte{
496 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
497 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
498 }
499
500
501 func (e *encoder) writeSOS(m image.Image) {
502 switch m.(type) {
503 case *image.Gray:
504 e.write(sosHeaderY)
505 default:
506 e.write(sosHeaderYCbCr)
507 }
508 var (
509
510
511 b block
512 cb, cr [4]block
513
514 prevDCY, prevDCCb, prevDCCr int32
515 )
516 bounds := m.Bounds()
517 switch m := m.(type) {
518
519 case *image.Gray:
520 for y := bounds.Min.Y; y < bounds.Max.Y; y += 8 {
521 for x := bounds.Min.X; x < bounds.Max.X; x += 8 {
522 p := image.Pt(x, y)
523 grayToY(m, p, &b)
524 prevDCY = e.writeBlock(&b, 0, prevDCY)
525 }
526 }
527 default:
528 rgba, _ := m.(*image.RGBA)
529 ycbcr, _ := m.(*image.YCbCr)
530 for y := bounds.Min.Y; y < bounds.Max.Y; y += 16 {
531 for x := bounds.Min.X; x < bounds.Max.X; x += 16 {
532 for i := 0; i < 4; i++ {
533 xOff := (i & 1) * 8
534 yOff := (i & 2) * 4
535 p := image.Pt(x+xOff, y+yOff)
536 if rgba != nil {
537 rgbaToYCbCr(rgba, p, &b, &cb[i], &cr[i])
538 } else if ycbcr != nil {
539 yCbCrToYCbCr(ycbcr, p, &b, &cb[i], &cr[i])
540 } else {
541 toYCbCr(m, p, &b, &cb[i], &cr[i])
542 }
543 prevDCY = e.writeBlock(&b, 0, prevDCY)
544 }
545 scale(&b, &cb)
546 prevDCCb = e.writeBlock(&b, 1, prevDCCb)
547 scale(&b, &cr)
548 prevDCCr = e.writeBlock(&b, 1, prevDCCr)
549 }
550 }
551 }
552
553 e.emit(0x7f, 7)
554 }
555
556
557 const DefaultQuality = 75
558
559
560
561 type Options struct {
562 Quality int
563 }
564
565
566
567 func Encode(w io.Writer, m image.Image, o *Options) error {
568 b := m.Bounds()
569 if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 {
570 return errors.New("jpeg: image is too large to encode")
571 }
572 var e encoder
573 if ww, ok := w.(writer); ok {
574 e.w = ww
575 } else {
576 e.w = bufio.NewWriter(w)
577 }
578
579 quality := DefaultQuality
580 if o != nil {
581 quality = o.Quality
582 if quality < 1 {
583 quality = 1
584 } else if quality > 100 {
585 quality = 100
586 }
587 }
588
589 var scale int
590 if quality < 50 {
591 scale = 5000 / quality
592 } else {
593 scale = 200 - quality*2
594 }
595
596 for i := range e.quant {
597 for j := range e.quant[i] {
598 x := int(unscaledQuant[i][j])
599 x = (x*scale + 50) / 100
600 if x < 1 {
601 x = 1
602 } else if x > 255 {
603 x = 255
604 }
605 e.quant[i][j] = uint8(x)
606 }
607 }
608
609 nComponent := 3
610 switch m.(type) {
611
612 case *image.Gray:
613 nComponent = 1
614 }
615
616 e.buf[0] = 0xff
617 e.buf[1] = 0xd8
618 e.write(e.buf[:2])
619
620 e.writeDQT()
621
622 e.writeSOF0(b.Size(), nComponent)
623
624 e.writeDHT(nComponent)
625
626 e.writeSOS(m)
627
628 e.buf[0] = 0xff
629 e.buf[1] = 0xd9
630 e.write(e.buf[:2])
631 e.flush()
632 return e.err
633 }
634
View as plain text