Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package jpeg | 5 package jpeg |
6 | 6 |
7 import ( | 7 import ( |
8 "bufio" | 8 "bufio" |
9 "image" | 9 "image" |
10 "image/ycbcr" | 10 "image/ycbcr" |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, | 164 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, |
165 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, | 165 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, |
166 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, | 166 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, |
167 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | 167 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, |
168 0xf9, 0xfa, | 168 0xf9, 0xfa, |
169 }, | 169 }, |
170 }, | 170 }, |
171 } | 171 } |
172 | 172 |
173 // huffmanLUT is a compiled look-up table representation of a huffmanSpec. | 173 // huffmanLUT is a compiled look-up table representation of a huffmanSpec. |
174 // Each value maps to an uint32 of which the 8 most significant bits hold the | 174 // Each value maps to a uint32 of which the 8 most significant bits hold the |
r
2011/04/18 19:30:42
s/an/a/
nigeltao
2011/04/19 00:47:06
Done.
| |
175 // codeword size in bits and the 24 least significant bits hold the codeword. | 175 // codeword size in bits and the 24 least significant bits hold the codeword. |
176 // The maximum codeword size is 16 bits. | 176 // The maximum codeword size is 16 bits. |
177 type huffmanLUT []uint32 | 177 type huffmanLUT []uint32 |
178 | 178 |
179 func (h *huffmanLUT) init(s huffmanSpec) { | 179 func (h *huffmanLUT) init(s huffmanSpec) { |
180 maxValue := 0 | 180 maxValue := 0 |
181 for _, v := range s.value { | 181 for _, v := range s.value { |
182 if int(v) > maxValue { | 182 if int(v) > maxValue { |
183 maxValue = int(v) | 183 maxValue = int(v) |
184 } | 184 } |
(...skipping 18 matching lines...) Expand all Loading... | |
203 for i, s := range theHuffmanSpec { | 203 for i, s := range theHuffmanSpec { |
204 theHuffmanLUT[i].init(s) | 204 theHuffmanLUT[i].init(s) |
205 } | 205 } |
206 } | 206 } |
207 | 207 |
208 // writer is a buffered writer. | 208 // writer is a buffered writer. |
209 type writer interface { | 209 type writer interface { |
210 Flush() os.Error | 210 Flush() os.Error |
211 Write([]byte) (int, os.Error) | 211 Write([]byte) (int, os.Error) |
212 WriteByte(byte) os.Error | 212 WriteByte(byte) os.Error |
213 WriteString(string) (int, os.Error) | |
214 } | |
215 | |
216 // An encoder wraps a writer's methods to save the first returned error as | |
217 // e.err and return void. | |
r
2011/04/18 19:30:42
void?
nigeltao
2011/04/19 00:47:06
Rewritten.
| |
218 | |
219 func (e *encoder) flush() { | |
220 if e.err != nil { | |
221 return | |
222 } | |
223 e.err = e.w.Flush() | |
224 } | |
225 | |
226 func (e *encoder) write(p []byte) { | |
227 if e.err != nil { | |
228 return | |
229 } | |
230 _, e.err = e.w.Write(p) | |
231 } | |
232 | |
233 func (e *encoder) writeByte(b byte) { | |
234 if e.err != nil { | |
235 return | |
236 } | |
237 e.err = e.w.WriteByte(b) | |
238 } | |
239 | |
240 func (e *encoder) writeString(s string) { | |
241 if e.err != nil { | |
242 return | |
243 } | |
244 _, e.err = e.w.WriteString(s) | |
245 } | 213 } |
246 | 214 |
247 // encoder encodes an image to the JPEG format. | 215 // encoder encodes an image to the JPEG format. |
r
2011/04/18 19:30:42
move this above its methods and combine the commen
nigeltao
2011/04/19 00:47:06
Done.
| |
248 type encoder struct { | 216 type encoder struct { |
249 » // w is the writer to write to. err is the first error encountered | 217 » // w is the writer to write to. err is the first error encountered durin g |
250 » // during writing. | 218 » // writing. All attempted writes after the first error become no-ops. |
251 w writer | 219 w writer |
252 err os.Error | 220 err os.Error |
221 // buf is a scratch buffer. | |
222 buf [16]byte | |
253 // bits and nBits are accumulated bits to write to w. | 223 // bits and nBits are accumulated bits to write to w. |
254 bits uint32 | 224 bits uint32 |
255 nBits uint8 | 225 nBits uint8 |
256 // quant is the scaled quantization tables. | 226 // quant is the scaled quantization tables. |
257 quant [nQuantIndex][blockSize]byte | 227 quant [nQuantIndex][blockSize]byte |
228 } | |
229 | |
230 func (e *encoder) flush() { | |
231 if e.err != nil { | |
232 return | |
233 } | |
234 e.err = e.w.Flush() | |
235 } | |
236 | |
237 func (e *encoder) write(p []byte) { | |
238 if e.err != nil { | |
239 return | |
240 } | |
241 _, e.err = e.w.Write(p) | |
242 } | |
243 | |
244 func (e *encoder) writeByte(b byte) { | |
245 if e.err != nil { | |
246 return | |
247 } | |
248 e.err = e.w.WriteByte(b) | |
258 } | 249 } |
259 | 250 |
260 // emit emits the least significant nBits bits of bits to the bitstream. | 251 // emit emits the least significant nBits bits of bits to the bitstream. |
r
2011/04/18 19:30:42
nBits bits of bits to the bits. wow.
| |
261 // The precondition is bits < 1<<nBits && nBits <= 16. | 252 // The precondition is bits < 1<<nBits && nBits <= 16. |
262 func (e *encoder) emit(bits uint32, nBits uint8) { | 253 func (e *encoder) emit(bits uint32, nBits uint8) { |
263 nBits += e.nBits | 254 nBits += e.nBits |
264 bits <<= 32 - nBits | 255 bits <<= 32 - nBits |
265 bits |= e.bits | 256 bits |= e.bits |
266 for nBits >= 8 { | 257 for nBits >= 8 { |
267 b := uint8(bits >> 24) | 258 b := uint8(bits >> 24) |
268 e.writeByte(b) | 259 e.writeByte(b) |
269 » » if b == 255 { | 260 » » if b == 0xff { |
270 e.writeByte(0x00) | 261 e.writeByte(0x00) |
271 } | 262 } |
272 bits <<= 8 | 263 bits <<= 8 |
273 nBits -= 8 | 264 nBits -= 8 |
274 } | 265 } |
275 e.bits, e.nBits = bits, nBits | 266 e.bits, e.nBits = bits, nBits |
276 } | 267 } |
277 | 268 |
278 // emitHuff emits the given value with the given Huffman encoder. | 269 // emitHuff emits the given value with the given Huffman encoder. |
279 func (e *encoder) emitHuff(h huffIndex, value int) { | 270 func (e *encoder) emitHuff(h huffIndex, value int) { |
(...skipping 13 matching lines...) Expand all Loading... | |
293 nBits = bitCount[a] | 284 nBits = bitCount[a] |
294 } else { | 285 } else { |
295 nBits = 8 + bitCount[a>>8] | 286 nBits = 8 + bitCount[a>>8] |
296 } | 287 } |
297 e.emitHuff(h, runLength<<4|int(nBits)) | 288 e.emitHuff(h, runLength<<4|int(nBits)) |
298 if nBits > 0 { | 289 if nBits > 0 { |
299 e.emit(uint32(b)&(1<<nBits-1), nBits) | 290 e.emit(uint32(b)&(1<<nBits-1), nBits) |
300 } | 291 } |
301 } | 292 } |
302 | 293 |
303 // writeMarkerHeader writes the header for a maker with the given length. | 294 // writeMarkerHeader writes the header for a marker with the given length. |
r
2011/04/18 19:30:42
s/maker/marker/
nigeltao
2011/04/19 00:47:06
Done.
| |
304 func (e *encoder) writeMarkerHeader(marker uint8, markerlen int) { | 295 func (e *encoder) writeMarkerHeader(marker uint8, markerlen int) { |
305 » e.writeByte(0xff) | 296 » e.buf[0] = 0xff |
306 » e.writeByte(marker) | 297 » e.buf[1] = marker |
307 » e.writeByte(uint8(markerlen >> 8)) | 298 » e.buf[2] = uint8(markerlen >> 8) |
308 » e.writeByte(uint8(markerlen & 0xff)) | 299 » e.buf[3] = uint8(markerlen & 0xff) |
r
2011/04/18 19:30:42
this is a fair bit of overhead. we could put a [4]
nigeltao
2011/04/19 00:47:06
Done.
| |
300 » e.write(e.buf[:4]) | |
309 } | 301 } |
310 | 302 |
311 // writeDQT writes the Define Quantization Table marker. | 303 // writeDQT writes the Define Quantization Table marker. |
312 func (e *encoder) writeDQT() { | 304 func (e *encoder) writeDQT() { |
313 markerlen := 2 | 305 markerlen := 2 |
314 for _, q := range e.quant { | 306 for _, q := range e.quant { |
315 markerlen += 1 + len(q) | 307 markerlen += 1 + len(q) |
316 } | 308 } |
317 e.writeMarkerHeader(dqtMarker, markerlen) | 309 e.writeMarkerHeader(dqtMarker, markerlen) |
318 for i, q := range e.quant { | 310 for i, q := range e.quant { |
319 e.writeByte(uint8(i)) | 311 e.writeByte(uint8(i)) |
320 e.write(q[:]) | 312 e.write(q[:]) |
321 } | 313 } |
322 } | 314 } |
323 | 315 |
324 // writeSOF0 writes the Start Of Frame (Baseline) marker. | 316 // writeSOF0 writes the Start Of Frame (Baseline) marker. |
325 func (e *encoder) writeSOF0(size image.Point) { | 317 func (e *encoder) writeSOF0(size image.Point) { |
326 markerlen := 8 + 3*nComponent | 318 markerlen := 8 + 3*nComponent |
327 e.writeMarkerHeader(sof0Marker, markerlen) | 319 e.writeMarkerHeader(sof0Marker, markerlen) |
328 » e.writeByte(8) // 8-bit color. | 320 » e.buf[0] = 8 // 8-bit color. |
329 » e.writeByte(uint8(size.Y >> 8)) | 321 » e.buf[1] = uint8(size.Y >> 8) |
330 » e.writeByte(uint8(size.Y & 0xff)) | 322 » e.buf[2] = uint8(size.Y & 0xff) |
331 » e.writeByte(uint8(size.X >> 8)) | 323 » e.buf[3] = uint8(size.X >> 8) |
332 » e.writeByte(uint8(size.X & 0xff)) | 324 » e.buf[4] = uint8(size.X & 0xff) |
r
2011/04/18 19:30:42
ditto.
nigeltao
2011/04/19 00:47:06
Done.
| |
333 » e.writeByte(nComponent) | 325 » e.buf[5] = nComponent |
334 for i := 0; i < nComponent; i++ { | 326 for i := 0; i < nComponent; i++ { |
335 » » e.writeByte(uint8(i + 1)) | 327 » » e.buf[3*i+6] = uint8(i + 1) |
336 // We use 4:2:0 chroma subsampling. | 328 // We use 4:2:0 chroma subsampling. |
337 » » e.writeByte("\x22\x11\x11"[i]) | 329 » » e.buf[3*i+7] = "\x22\x11\x11"[i] |
338 » » e.writeByte("\x00\x01\x01"[i]) | 330 » » e.buf[3*i+8] = "\x00\x01\x01"[i] |
r
2011/04/18 19:30:42
ditto
nigeltao
2011/04/19 00:47:06
Done.
| |
339 » } | 331 » } |
332 » e.write(e.buf[:3*(nComponent-1)+9]) | |
340 } | 333 } |
341 | 334 |
342 // writeDHT writes the Define Huffman Table marker. | 335 // writeDHT writes the Define Huffman Table marker. |
343 func (e *encoder) writeDHT() { | 336 func (e *encoder) writeDHT() { |
344 markerlen := 2 | 337 markerlen := 2 |
345 for _, s := range theHuffmanSpec { | 338 for _, s := range theHuffmanSpec { |
346 markerlen += 1 + 16 + len(s.value) | 339 markerlen += 1 + 16 + len(s.value) |
347 } | 340 } |
348 e.writeMarkerHeader(dhtMarker, markerlen) | 341 e.writeMarkerHeader(dhtMarker, markerlen) |
349 for i, s := range theHuffmanSpec { | 342 for i, s := range theHuffmanSpec { |
350 e.writeByte("\x00\x10\x01\x11"[i]) | 343 e.writeByte("\x00\x10\x01\x11"[i]) |
351 e.write(s.count[:]) | 344 e.write(s.count[:]) |
352 e.write(s.value) | 345 e.write(s.value) |
r
2011/04/18 19:30:42
ditto
nigeltao
2011/04/19 00:47:06
I don't think this applies here; s.value is a slic
| |
353 } | 346 } |
354 } | 347 } |
355 | 348 |
356 // writeBlock writes a block of pixel data using the given quantization table, | 349 // writeBlock writes a block of pixel data using the given quantization table, |
357 // returning the post-quantized DC value of the DCT-transformed block. | 350 // returning the post-quantized DC value of the DCT-transformed block. |
358 func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int) int { | 351 func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int) int { |
359 fdct(b) | 352 fdct(b) |
360 // Emit the DC delta. | 353 // Emit the DC delta. |
361 dc := div(b[0], (8 * int(e.quant[q][0]))) | 354 dc := div(b[0], (8 * int(e.quant[q][0]))) |
362 e.emitHuffRLE(huffIndex(2*q+0), 0, dc-prevDC) | 355 e.emitHuffRLE(huffIndex(2*q+0), 0, dc-prevDC) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
406 for y := 0; y < 4; y++ { | 399 for y := 0; y < 4; y++ { |
407 for x := 0; x < 4; x++ { | 400 for x := 0; x < 4; x++ { |
408 j := 16*y + 2*x | 401 j := 16*y + 2*x |
409 sum := src[i][j] + src[i][j+1] + src[i][j+8] + s rc[i][j+9] | 402 sum := src[i][j] + src[i][j+1] + src[i][j+8] + s rc[i][j+9] |
410 dst[8*y+x+dstOff] = (sum + 2) >> 2 | 403 dst[8*y+x+dstOff] = (sum + 2) >> 2 |
411 } | 404 } |
412 } | 405 } |
413 } | 406 } |
414 } | 407 } |
415 | 408 |
409 // sosHeader is the SOS marker "\xff\xda" followed by 12 bytes: | |
410 // - the marker length "\x00\x0c", | |
411 // - the number of components "\x03", | |
412 // - component 1 uses DC table 0 and AC table 0 "\x01\x00", | |
413 // - component 2 uses DC table 1 and AC table 1 "\x02\x11", | |
414 // - component 3 uses DC table 1 and AC table 1 "\x03\x11", | |
415 // - padding "\x00\x00\x00". | |
416 var sosHeader = []byte{ | |
417 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, | |
418 0x11, 0x03, 0x11, 0x00, 0x00, 0x00, | |
419 } | |
420 | |
416 // writeSOS writes the StartOfScan marker. | 421 // writeSOS writes the StartOfScan marker. |
417 func (e *encoder) writeSOS(m image.Image) { | 422 func (e *encoder) writeSOS(m image.Image) { |
418 » // Write the SOS marker "\xff\xda" followed by 12 bytes: | 423 » e.write(sosHeader) |
419 » //» - the marker length "\x00\x0c", | |
420 » //» - the number of components "\x03", | |
421 » //» - component 1 uses DC table 0 and AC table 0 "\x01\x00", | |
422 » //» - component 2 uses DC table 1 and AC table 1 "\x02\x11", | |
423 » //» - component 3 uses DC table 1 and AC table 1 "\x03\x11", | |
424 » //» - padding "\x00\x00\x00". | |
425 » e.writeString("\xff\xda\x00\x0c\x03\x01\x00\x02\x11\x03\x11\x00\x00\x00" ) | |
r
2011/04/18 19:30:42
depending on the implementation of the writer, wri
nigeltao
2011/04/19 00:47:06
Done.
| |
426 var ( | 424 var ( |
427 // Scratch buffers to hold the YCbCr values. | 425 // Scratch buffers to hold the YCbCr values. |
428 yBlock block | 426 yBlock block |
429 cbBlock [4]block | 427 cbBlock [4]block |
430 crBlock [4]block | 428 crBlock [4]block |
431 cBlock block | 429 cBlock block |
r
2011/04/18 19:30:42
ok for now, but these are more unnecessary allocat
nigeltao
2011/04/19 00:47:06
There is only one SOS per image. Also, eventually,
| |
432 // DC components are delta-encoded. | 430 // DC components are delta-encoded. |
433 » » lastY, lastCb, lastCr int | 431 » » prevDCY, prevDCCb, prevDCCr int |
434 ) | 432 ) |
435 bounds := m.Bounds() | 433 bounds := m.Bounds() |
436 for y := bounds.Min.Y; y < bounds.Max.Y; y += 16 { | 434 for y := bounds.Min.Y; y < bounds.Max.Y; y += 16 { |
437 for x := bounds.Min.X; x < bounds.Max.X; x += 16 { | 435 for x := bounds.Min.X; x < bounds.Max.X; x += 16 { |
438 for i := 0; i < 4; i++ { | 436 for i := 0; i < 4; i++ { |
439 xOff := (i & 1) * 8 | 437 xOff := (i & 1) * 8 |
440 yOff := (i & 2) * 4 | 438 yOff := (i & 2) * 4 |
441 p := image.Point{x + xOff, y + yOff} | 439 p := image.Point{x + xOff, y + yOff} |
442 toYCbCr(m, p, &yBlock, &cbBlock[i], &crBlock[i]) | 440 toYCbCr(m, p, &yBlock, &cbBlock[i], &crBlock[i]) |
443 » » » » lastY = e.writeBlock(&yBlock, 0, lastY) | 441 » » » » prevDCY = e.writeBlock(&yBlock, 0, prevDCY) |
444 } | 442 } |
445 scale(&cBlock, &cbBlock) | 443 scale(&cBlock, &cbBlock) |
446 » » » lastCb = e.writeBlock(&cBlock, 1, lastCb) | 444 » » » prevDCCb = e.writeBlock(&cBlock, 1, prevDCCb) |
447 scale(&cBlock, &crBlock) | 445 scale(&cBlock, &crBlock) |
448 » » » lastCr = e.writeBlock(&cBlock, 1, lastCr) | 446 » » » prevDCCr = e.writeBlock(&cBlock, 1, prevDCCr) |
449 } | 447 } |
450 } | 448 } |
451 // Pad the last byte with 1's. | 449 // Pad the last byte with 1's. |
452 e.emit(0x7f, 7) | 450 e.emit(0x7f, 7) |
453 } | 451 } |
454 | 452 |
455 // DefaultQuality is the default quality encoding parameter. | 453 // DefaultQuality is the default quality encoding parameter. |
456 const DefaultQuality = 75 | 454 const DefaultQuality = 75 |
457 | 455 |
458 // Options are the encoding parameters. | 456 // Options are the encoding parameters. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 x = (x*scale + 50) / 100 | 496 x = (x*scale + 50) / 100 |
499 if x < 1 { | 497 if x < 1 { |
500 x = 1 | 498 x = 1 |
501 } else if x > 255 { | 499 } else if x > 255 { |
502 x = 255 | 500 x = 255 |
503 } | 501 } |
504 e.quant[i][j] = uint8(x) | 502 e.quant[i][j] = uint8(x) |
505 } | 503 } |
506 } | 504 } |
507 // Write the Start Of Image marker. | 505 // Write the Start Of Image marker. |
508 » e.writeString("\xff\xd8") | 506 » e.buf[0] = 0xff |
507 » e.buf[1] = 0xd8 | |
508 » e.write(e.buf[:2]) | |
509 // Write the quantization tables. | 509 // Write the quantization tables. |
510 e.writeDQT() | 510 e.writeDQT() |
511 // Write the image dimensions. | 511 // Write the image dimensions. |
512 e.writeSOF0(b.Size()) | 512 e.writeSOF0(b.Size()) |
513 // Write the Huffman tables. | 513 // Write the Huffman tables. |
514 e.writeDHT() | 514 e.writeDHT() |
515 // Write the image data. | 515 // Write the image data. |
516 e.writeSOS(m) | 516 e.writeSOS(m) |
517 // Write the End Of Image marker. | 517 // Write the End Of Image marker. |
518 » e.writeString("\xff\xd9") | 518 » e.buf[0] = 0xff |
519 » e.buf[1] = 0xd9 | |
520 » e.write(e.buf[:2]) | |
519 e.flush() | 521 e.flush() |
520 return e.err | 522 return e.err |
521 } | 523 } |
LEFT | RIGHT |