OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [image/] [jpeg/] [writer.go] - Blame information for rev 760

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2011 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
package jpeg
6
 
7
import (
8
        "bufio"
9
        "errors"
10
        "image"
11
        "image/color"
12
        "io"
13
)
14
 
15
// min returns the minimum of two integers.
16
func min(x, y int) int {
17
        if x < y {
18
                return x
19
        }
20
        return y
21
}
22
 
23
// div returns a/b rounded to the nearest integer, instead of rounded to zero.
24
func div(a int, b int) int {
25
        if a >= 0 {
26
                return (a + (b >> 1)) / b
27
        }
28
        return -((-a + (b >> 1)) / b)
29
}
30
 
31
// bitCount counts the number of bits needed to hold an integer.
32
var bitCount = [256]byte{
33
        0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
34
        5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
35
        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
36
        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
37
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
38
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
39
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
40
        7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
41
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
42
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
43
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
44
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
45
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
46
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
47
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
48
        8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
49
}
50
 
51
type quantIndex int
52
 
53
const (
54
        quantIndexLuminance quantIndex = iota
55
        quantIndexChrominance
56
        nQuantIndex
57
)
58
 
59
// unscaledQuant are the unscaled quantization tables. Each encoder copies and
60
// scales the tables according to its quality parameter.
61
var unscaledQuant = [nQuantIndex][blockSize]byte{
62
        // Luminance.
63
        {
64
                16, 11, 10, 16, 24, 40, 51, 61,
65
                12, 12, 14, 19, 26, 58, 60, 55,
66
                14, 13, 16, 24, 40, 57, 69, 56,
67
                14, 17, 22, 29, 51, 87, 80, 62,
68
                18, 22, 37, 56, 68, 109, 103, 77,
69
                24, 35, 55, 64, 81, 104, 113, 92,
70
                49, 64, 78, 87, 103, 121, 120, 101,
71
                72, 92, 95, 98, 112, 100, 103, 99,
72
        },
73
        // Chrominance.
74
        {
75
                17, 18, 24, 47, 99, 99, 99, 99,
76
                18, 21, 26, 66, 99, 99, 99, 99,
77
                24, 26, 56, 99, 99, 99, 99, 99,
78
                47, 66, 99, 99, 99, 99, 99, 99,
79
                99, 99, 99, 99, 99, 99, 99, 99,
80
                99, 99, 99, 99, 99, 99, 99, 99,
81
                99, 99, 99, 99, 99, 99, 99, 99,
82
                99, 99, 99, 99, 99, 99, 99, 99,
83
        },
84
}
85
 
86
type huffIndex int
87
 
88
const (
89
        huffIndexLuminanceDC huffIndex = iota
90
        huffIndexLuminanceAC
91
        huffIndexChrominanceDC
92
        huffIndexChrominanceAC
93
        nHuffIndex
94
)
95
 
96
// huffmanSpec specifies a Huffman encoding.
97
type huffmanSpec struct {
98
        // count[i] is the number of codes of length i bits.
99
        count [16]byte
100
        // value[i] is the decoded value of the i'th codeword.
101
        value []byte
102
}
103
 
104
// theHuffmanSpec is the Huffman encoding specifications.
105
// This encoder uses the same Huffman encoding for all images.
106
var theHuffmanSpec = [nHuffIndex]huffmanSpec{
107
        // Luminance DC.
108
        {
109
                [16]byte{0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},
110
                []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
111
        },
112
        // Luminance AC.
113
        {
114
                [16]byte{0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125},
115
                []byte{
116
                        0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
117
                        0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
118
                        0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
119
                        0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
120
                        0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
121
                        0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
122
                        0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
123
                        0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
124
                        0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
125
                        0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
126
                        0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
127
                        0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
128
                        0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
129
                        0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
130
                        0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
131
                        0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
132
                        0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
133
                        0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
134
                        0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
135
                        0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
136
                        0xf9, 0xfa,
137
                },
138
        },
139
        // Chrominance DC.
140
        {
141
                [16]byte{0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0},
142
                []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
143
        },
144
        // Chrominance AC.
145
        {
146
                [16]byte{0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119},
147
                []byte{
148
                        0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
149
                        0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
150
                        0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
151
                        0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
152
                        0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
153
                        0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
154
                        0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
155
                        0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
156
                        0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
157
                        0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
158
                        0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
159
                        0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
160
                        0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
161
                        0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
162
                        0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
163
                        0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
164
                        0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
165
                        0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
166
                        0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
167
                        0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
168
                        0xf9, 0xfa,
169
                },
170
        },
171
}
172
 
173
// huffmanLUT is a compiled look-up table representation of a huffmanSpec.
174
// Each value maps to a uint32 of which the 8 most significant bits hold the
175
// codeword size in bits and the 24 least significant bits hold the codeword.
176
// The maximum codeword size is 16 bits.
177
type huffmanLUT []uint32
178
 
179
func (h *huffmanLUT) init(s huffmanSpec) {
180
        maxValue := 0
181
        for _, v := range s.value {
182
                if int(v) > maxValue {
183
                        maxValue = int(v)
184
                }
185
        }
186
        *h = make([]uint32, maxValue+1)
187
        code, k := uint32(0), 0
188
        for i := 0; i < len(s.count); i++ {
189
                nBits := uint32(i+1) << 24
190
                for j := uint8(0); j < s.count[i]; j++ {
191
                        (*h)[s.value[k]] = nBits | code
192
                        code++
193
                        k++
194
                }
195
                code <<= 1
196
        }
197
}
198
 
199
// theHuffmanLUT are compiled representations of theHuffmanSpec.
200
var theHuffmanLUT [4]huffmanLUT
201
 
202
func init() {
203
        for i, s := range theHuffmanSpec {
204
                theHuffmanLUT[i].init(s)
205
        }
206
}
207
 
208
// writer is a buffered writer.
209
type writer interface {
210
        Flush() error
211
        Write([]byte) (int, error)
212
        WriteByte(byte) error
213
}
214
 
215
// encoder encodes an image to the JPEG format.
216
type encoder struct {
217
        // w is the writer to write to. err is the first error encountered during
218
        // writing. All attempted writes after the first error become no-ops.
219
        w   writer
220
        err error
221
        // buf is a scratch buffer.
222
        buf [16]byte
223
        // bits and nBits are accumulated bits to write to w.
224
        bits, nBits uint32
225
        // quant is the scaled quantization tables.
226
        quant [nQuantIndex][blockSize]byte
227
}
228
 
229
func (e *encoder) flush() {
230
        if e.err != nil {
231
                return
232
        }
233
        e.err = e.w.Flush()
234
}
235
 
236
func (e *encoder) write(p []byte) {
237
        if e.err != nil {
238
                return
239
        }
240
        _, e.err = e.w.Write(p)
241
}
242
 
243
func (e *encoder) writeByte(b byte) {
244
        if e.err != nil {
245
                return
246
        }
247
        e.err = e.w.WriteByte(b)
248
}
249
 
250
// emit emits the least significant nBits bits of bits to the bitstream.
251
// The precondition is bits < 1<
252
func (e *encoder) emit(bits, nBits uint32) {
253
        nBits += e.nBits
254
        bits <<= 32 - nBits
255
        bits |= e.bits
256
        for nBits >= 8 {
257
                b := uint8(bits >> 24)
258
                e.writeByte(b)
259
                if b == 0xff {
260
                        e.writeByte(0x00)
261
                }
262
                bits <<= 8
263
                nBits -= 8
264
        }
265
        e.bits, e.nBits = bits, nBits
266
}
267
 
268
// emitHuff emits the given value with the given Huffman encoder.
269
func (e *encoder) emitHuff(h huffIndex, value int) {
270
        x := theHuffmanLUT[h][value]
271
        e.emit(x&(1<<24-1), x>>24)
272
}
273
 
274
// emitHuffRLE emits a run of runLength copies of value encoded with the given
275
// Huffman encoder.
276
func (e *encoder) emitHuffRLE(h huffIndex, runLength, value int) {
277
        a, b := value, value
278
        if a < 0 {
279
                a, b = -value, value-1
280
        }
281
        var nBits uint32
282
        if a < 0x100 {
283
                nBits = uint32(bitCount[a])
284
        } else {
285
                nBits = 8 + uint32(bitCount[a>>8])
286
        }
287
        e.emitHuff(h, runLength<<4|int(nBits))
288
        if nBits > 0 {
289
                e.emit(uint32(b)&(1<
290
        }
291
}
292
 
293
// writeMarkerHeader writes the header for a marker with the given length.
294
func (e *encoder) writeMarkerHeader(marker uint8, markerlen int) {
295
        e.buf[0] = 0xff
296
        e.buf[1] = marker
297
        e.buf[2] = uint8(markerlen >> 8)
298
        e.buf[3] = uint8(markerlen & 0xff)
299
        e.write(e.buf[:4])
300
}
301
 
302
// writeDQT writes the Define Quantization Table marker.
303
func (e *encoder) writeDQT() {
304
        markerlen := 2 + int(nQuantIndex)*(1+blockSize)
305
        e.writeMarkerHeader(dqtMarker, markerlen)
306
        for i := range e.quant {
307
                e.writeByte(uint8(i))
308
                e.write(e.quant[i][:])
309
        }
310
}
311
 
312
// writeSOF0 writes the Start Of Frame (Baseline) marker.
313
func (e *encoder) writeSOF0(size image.Point) {
314
        markerlen := 8 + 3*nColorComponent
315
        e.writeMarkerHeader(sof0Marker, markerlen)
316
        e.buf[0] = 8 // 8-bit color.
317
        e.buf[1] = uint8(size.Y >> 8)
318
        e.buf[2] = uint8(size.Y & 0xff)
319
        e.buf[3] = uint8(size.X >> 8)
320
        e.buf[4] = uint8(size.X & 0xff)
321
        e.buf[5] = nColorComponent
322
        for i := 0; i < nColorComponent; i++ {
323
                e.buf[3*i+6] = uint8(i + 1)
324
                // We use 4:2:0 chroma subsampling.
325
                e.buf[3*i+7] = "\x22\x11\x11"[i]
326
                e.buf[3*i+8] = "\x00\x01\x01"[i]
327
        }
328
        e.write(e.buf[:3*(nColorComponent-1)+9])
329
}
330
 
331
// writeDHT writes the Define Huffman Table marker.
332
func (e *encoder) writeDHT() {
333
        markerlen := 2
334
        for _, s := range theHuffmanSpec {
335
                markerlen += 1 + 16 + len(s.value)
336
        }
337
        e.writeMarkerHeader(dhtMarker, markerlen)
338
        for i, s := range theHuffmanSpec {
339
                e.writeByte("\x00\x10\x01\x11"[i])
340
                e.write(s.count[:])
341
                e.write(s.value)
342
        }
343
}
344
 
345
// writeBlock writes a block of pixel data using the given quantization table,
346
// returning the post-quantized DC value of the DCT-transformed block.
347
func (e *encoder) writeBlock(b *block, q quantIndex, prevDC int) int {
348
        fdct(b)
349
        // Emit the DC delta.
350
        dc := div(b[0], (8 * int(e.quant[q][0])))
351
        e.emitHuffRLE(huffIndex(2*q+0), 0, dc-prevDC)
352
        // Emit the AC components.
353
        h, runLength := huffIndex(2*q+1), 0
354
        for k := 1; k < blockSize; k++ {
355
                ac := div(b[unzig[k]], (8 * int(e.quant[q][k])))
356
                if ac == 0 {
357
                        runLength++
358
                } else {
359
                        for runLength > 15 {
360
                                e.emitHuff(h, 0xf0)
361
                                runLength -= 16
362
                        }
363
                        e.emitHuffRLE(h, runLength, ac)
364
                        runLength = 0
365
                }
366
        }
367
        if runLength > 0 {
368
                e.emitHuff(h, 0x00)
369
        }
370
        return dc
371
}
372
 
373
// toYCbCr converts the 8x8 region of m whose top-left corner is p to its
374
// YCbCr values.
375
func toYCbCr(m image.Image, p image.Point, yBlock, cbBlock, crBlock *block) {
376
        b := m.Bounds()
377
        xmax := b.Max.X - 1
378
        ymax := b.Max.Y - 1
379
        for j := 0; j < 8; j++ {
380
                for i := 0; i < 8; i++ {
381
                        r, g, b, _ := m.At(min(p.X+i, xmax), min(p.Y+j, ymax)).RGBA()
382
                        yy, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
383
                        yBlock[8*j+i] = int(yy)
384
                        cbBlock[8*j+i] = int(cb)
385
                        crBlock[8*j+i] = int(cr)
386
                }
387
        }
388
}
389
 
390
// rgbaToYCbCr is a specialized version of toYCbCr for image.RGBA images.
391
func rgbaToYCbCr(m *image.RGBA, p image.Point, yBlock, cbBlock, crBlock *block) {
392
        b := m.Bounds()
393
        xmax := b.Max.X - 1
394
        ymax := b.Max.Y - 1
395
        for j := 0; j < 8; j++ {
396
                sj := p.Y + j
397
                if sj > ymax {
398
                        sj = ymax
399
                }
400
                offset := (sj-b.Min.Y)*m.Stride - b.Min.X*4
401
                for i := 0; i < 8; i++ {
402
                        sx := p.X + i
403
                        if sx > xmax {
404
                                sx = xmax
405
                        }
406
                        pix := m.Pix[offset+sx*4:]
407
                        yy, cb, cr := color.RGBToYCbCr(pix[0], pix[1], pix[2])
408
                        yBlock[8*j+i] = int(yy)
409
                        cbBlock[8*j+i] = int(cb)
410
                        crBlock[8*j+i] = int(cr)
411
                }
412
        }
413
}
414
 
415
// scale scales the 16x16 region represented by the 4 src blocks to the 8x8
416
// dst block.
417
func scale(dst *block, src *[4]block) {
418
        for i := 0; i < 4; i++ {
419
                dstOff := (i&2)<<4 | (i&1)<<2
420
                for y := 0; y < 4; y++ {
421
                        for x := 0; x < 4; x++ {
422
                                j := 16*y + 2*x
423
                                sum := src[i][j] + src[i][j+1] + src[i][j+8] + src[i][j+9]
424
                                dst[8*y+x+dstOff] = (sum + 2) >> 2
425
                        }
426
                }
427
        }
428
}
429
 
430
// sosHeader is the SOS marker "\xff\xda" followed by 12 bytes:
431
//      - the marker length "\x00\x0c",
432
//      - the number of components "\x03",
433
//      - component 1 uses DC table 0 and AC table 0 "\x01\x00",
434
//      - component 2 uses DC table 1 and AC table 1 "\x02\x11",
435
//      - component 3 uses DC table 1 and AC table 1 "\x03\x11",
436
//      - padding "\x00\x00\x00".
437
var sosHeader = []byte{
438
        0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
439
        0x11, 0x03, 0x11, 0x00, 0x00, 0x00,
440
}
441
 
442
// writeSOS writes the StartOfScan marker.
443
func (e *encoder) writeSOS(m image.Image) {
444
        e.write(sosHeader)
445
        var (
446
                // Scratch buffers to hold the YCbCr values.
447
                yBlock  block
448
                cbBlock [4]block
449
                crBlock [4]block
450
                cBlock  block
451
                // DC components are delta-encoded.
452
                prevDCY, prevDCCb, prevDCCr int
453
        )
454
        bounds := m.Bounds()
455
        rgba, _ := m.(*image.RGBA)
456
        for y := bounds.Min.Y; y < bounds.Max.Y; y += 16 {
457
                for x := bounds.Min.X; x < bounds.Max.X; x += 16 {
458
                        for i := 0; i < 4; i++ {
459
                                xOff := (i & 1) * 8
460
                                yOff := (i & 2) * 4
461
                                p := image.Pt(x+xOff, y+yOff)
462
                                if rgba != nil {
463
                                        rgbaToYCbCr(rgba, p, &yBlock, &cbBlock[i], &crBlock[i])
464
                                } else {
465
                                        toYCbCr(m, p, &yBlock, &cbBlock[i], &crBlock[i])
466
                                }
467
                                prevDCY = e.writeBlock(&yBlock, 0, prevDCY)
468
                        }
469
                        scale(&cBlock, &cbBlock)
470
                        prevDCCb = e.writeBlock(&cBlock, 1, prevDCCb)
471
                        scale(&cBlock, &crBlock)
472
                        prevDCCr = e.writeBlock(&cBlock, 1, prevDCCr)
473
                }
474
        }
475
        // Pad the last byte with 1's.
476
        e.emit(0x7f, 7)
477
}
478
 
479
// DefaultQuality is the default quality encoding parameter.
480
const DefaultQuality = 75
481
 
482
// Options are the encoding parameters.
483
// Quality ranges from 1 to 100 inclusive, higher is better.
484
type Options struct {
485
        Quality int
486
}
487
 
488
// Encode writes the Image m to w in JPEG 4:2:0 baseline format with the given
489
// options. Default parameters are used if a nil *Options is passed.
490
func Encode(w io.Writer, m image.Image, o *Options) error {
491
        b := m.Bounds()
492
        if b.Dx() >= 1<<16 || b.Dy() >= 1<<16 {
493
                return errors.New("jpeg: image is too large to encode")
494
        }
495
        var e encoder
496
        if ww, ok := w.(writer); ok {
497
                e.w = ww
498
        } else {
499
                e.w = bufio.NewWriter(w)
500
        }
501
        // Clip quality to [1, 100].
502
        quality := DefaultQuality
503
        if o != nil {
504
                quality = o.Quality
505
                if quality < 1 {
506
                        quality = 1
507
                } else if quality > 100 {
508
                        quality = 100
509
                }
510
        }
511
        // Convert from a quality rating to a scaling factor.
512
        var scale int
513
        if quality < 50 {
514
                scale = 5000 / quality
515
        } else {
516
                scale = 200 - quality*2
517
        }
518
        // Initialize the quantization tables.
519
        for i := range e.quant {
520
                for j := range e.quant[i] {
521
                        x := int(unscaledQuant[i][j])
522
                        x = (x*scale + 50) / 100
523
                        if x < 1 {
524
                                x = 1
525
                        } else if x > 255 {
526
                                x = 255
527
                        }
528
                        e.quant[i][j] = uint8(x)
529
                }
530
        }
531
        // Write the Start Of Image marker.
532
        e.buf[0] = 0xff
533
        e.buf[1] = 0xd8
534
        e.write(e.buf[:2])
535
        // Write the quantization tables.
536
        e.writeDQT()
537
        // Write the image dimensions.
538
        e.writeSOF0(b.Size())
539
        // Write the Huffman tables.
540
        e.writeDHT()
541
        // Write the image data.
542
        e.writeSOS(m)
543
        // Write the End Of Image marker.
544
        e.buf[0] = 0xff
545
        e.buf[1] = 0xd9
546
        e.write(e.buf[:2])
547
        e.flush()
548
        return e.err
549
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.