Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1994, 1997, 1998, 1999 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: sdcte.c,v 1.7 2002/02/21 22:24:53 giles Exp $ */
18
/* DCT encoding filter stream */
19
#include "memory_.h"
20
#include "stdio_.h"
21
#include "jpeglib_.h"
22
#include "jerror_.h"
23
#include "gdebug.h"
24
#include "gsmemory.h"		/* for gsmalloc.h */
25
#include "gsmalloc.h"		/* for gs_memory_default */
26
#include "strimpl.h"
27
#include "sdct.h"
28
#include "sjpeg.h"
29
 
30
public_st_jpeg_compress_data();
31
 
32
/* ------ DCTEncode ------ */
33
 
34
/* JPEG destination manager procedures */
35
private void
36
dcte_init_destination(j_compress_ptr cinfo)
37
{
38
}
39
private boolean
40
dcte_empty_output_buffer(j_compress_ptr cinfo)
41
{
42
    return FALSE;
43
}
44
private void
45
dcte_term_destination(j_compress_ptr cinfo)
46
{
47
}
48
 
49
/* Set the defaults for the DCTEncode filter. */
50
private void
51
s_DCTE_set_defaults(stream_state * st)
52
{
53
    stream_DCT_state *const ss = (stream_DCT_state *) st;
54
 
55
    s_DCT_set_defaults(st);
56
    ss->QFactor = 1.0;
57
    ss->ColorTransform = -1;
58
    ss->Markers.data = 0;
59
    ss->Markers.size = 0;
60
    ss->NoMarker = true;
61
}
62
 
63
/* Initialize DCTEncode filter */
64
private int
65
s_DCTE_init(stream_state * st)
66
{
67
    stream_DCT_state *const ss = (stream_DCT_state *) st;
68
    struct jpeg_destination_mgr *dest = &ss->data.compress->destination;
69
 
70
    dest->init_destination = dcte_init_destination;
71
    dest->empty_output_buffer = dcte_empty_output_buffer;
72
    dest->term_destination = dcte_term_destination;
73
    ss->data.common->memory = ss->jpeg_memory;
74
    ss->data.compress->cinfo.dest = dest;
75
    ss->phase = 0;
76
    return 0;
77
}
78
 
79
/* Process a buffer */
80
private int
81
s_DCTE_process(stream_state * st, stream_cursor_read * pr,
82
	       stream_cursor_write * pw, bool last)
83
{
84
    stream_DCT_state *const ss = (stream_DCT_state *) st;
85
    jpeg_compress_data *jcdp = ss->data.compress;
86
    struct jpeg_destination_mgr *dest = jcdp->cinfo.dest;
87
 
88
    if_debug2('w', "[wde]process avail=%u, last=%d\n",
89
	      (uint) (pr->limit - pr->ptr), last);
90
    dest->next_output_byte = pw->ptr + 1;
91
    dest->free_in_buffer = pw->limit - pw->ptr;
92
    switch (ss->phase) {
93
	case 0:		/* not initialized yet */
94
	    if (gs_jpeg_start_compress(ss, TRUE) < 0)
95
		return ERRC;
96
	    if_debug4('w', "[wde]width=%u, height=%u, components=%d, scan_line_size=%u\n",
97
		      jcdp->cinfo.image_width,
98
		      jcdp->cinfo.image_height,
99
		      jcdp->cinfo.input_components,
100
		      ss->scan_line_size);
101
	    pw->ptr = dest->next_output_byte - 1;
102
	    ss->phase = 1;
103
	    /* falls through */
104
	case 1:		/* initialized, Markers not written */
105
	    if (pw->limit - pw->ptr < ss->Markers.size)
106
		return 1;
107
	    memcpy(pw->ptr + 1, ss->Markers.data, ss->Markers.size);
108
	    pw->ptr += ss->Markers.size;
109
	    ss->phase = 2;
110
	    /* falls through */
111
	case 2:		/* still need to write Adobe marker */
112
	    if (!ss->NoMarker) {
113
		static const byte Adobe[] =
114
		{
115
		    0xFF, JPEG_APP0 + 14, 0, 14,	/* parameter length */
116
		    'A', 'd', 'o', 'b', 'e',
117
		    0, 100,	/* Version */
118
		    0, 0,	/* Flags0 */
119
		    0, 0,	/* Flags1 */
120
 
121
		};
122
 
123
#define ADOBE_MARKER_LEN sizeof(Adobe)
124
		if (pw->limit - pw->ptr < ADOBE_MARKER_LEN)
125
		    return 1;
126
		memcpy(pw->ptr + 1, Adobe, ADOBE_MARKER_LEN);
127
		pw->ptr += ADOBE_MARKER_LEN;
128
		*pw->ptr = ss->ColorTransform;
129
#undef ADOBE_MARKER_LEN
130
	    }
131
	    dest->next_output_byte = pw->ptr + 1;
132
	    dest->free_in_buffer = pw->limit - pw->ptr;
133
	    ss->phase = 3;
134
	    /* falls through */
135
	case 3:		/* markers written, processing data */
136
	    while (jcdp->cinfo.image_height > jcdp->cinfo.next_scanline) {
137
		int written;
138
 
139
		/*
140
		 * The data argument for jpeg_write_scanlines is
141
		 * declared as a JSAMPARRAY.  There is no corresponding
142
		 * const type, so we must remove const from the
143
		 * argument that we are passing here.  (Tom Lane of IJG
144
		 * judges that providing const analogues of the
145
		 * interface types wouldn't be worth the trouble.)
146
		 */
147
		/*const */ byte *samples = (byte *) (pr->ptr + 1);
148
 
149
		if_debug1('w', "[wde]next_scanline=%u\n",
150
			  jcdp->cinfo.next_scanline);
151
		if ((uint) (pr->limit - pr->ptr) < ss->scan_line_size) {
152
		    if (last)
153
			return ERRC;	/* premature EOD */
154
		    return 0;	/* need more data */
155
		}
156
		written = gs_jpeg_write_scanlines(ss, &samples, 1);
157
		if (written < 0)
158
		    return ERRC;
159
		if_debug3('w', "[wde]write returns %d, used=%u, written=%u\n",
160
			  written,
161
			  (uint) (samples - 1 - pr->ptr),
162
			  (uint) (dest->next_output_byte - 1 - pw->ptr));
163
		pw->ptr = dest->next_output_byte - 1;
164
		if (!written)
165
		    return 1;	/* output full */
166
		pr->ptr += ss->scan_line_size;
167
	    }
168
	    ss->phase = 4;
169
	    /* falls through */
170
	case 4:		/* all data processed, finishing */
171
	    /* jpeg_finish_compress can't suspend, so write its output
172
	     * to a fixed-size internal buffer.
173
	     */
174
	    dest->next_output_byte = jcdp->finish_compress_buf;
175
	    dest->free_in_buffer = sizeof(jcdp->finish_compress_buf);
176
	    if (gs_jpeg_finish_compress(ss) < 0)
177
		return ERRC;
178
	    jcdp->fcb_size =
179
		dest->next_output_byte - jcdp->finish_compress_buf;
180
	    jcdp->fcb_pos = 0;
181
	    ss->phase = 5;
182
	    /* falls through */
183
	case 5:		/* copy the final data to the output */
184
	    if (jcdp->fcb_pos < jcdp->fcb_size) {
185
		int count = min(jcdp->fcb_size - jcdp->fcb_pos,
186
				pw->limit - pw->ptr);
187
 
188
		if_debug1('w', "[wde]copying final %d\n", count);
189
		memcpy(pw->ptr + 1, jcdp->finish_compress_buf + jcdp->fcb_pos,
190
		       count);
191
		jcdp->fcb_pos += count;
192
		pw->ptr += count;
193
		if (jcdp->fcb_pos < jcdp->fcb_size)
194
		    return 1;
195
	    }
196
	    return EOFC;
197
    }
198
    /* Default case can't happen.... */
199
    return ERRC;
200
}
201
 
202
/* Release the stream */
203
private void
204
s_DCTE_release(stream_state * st)
205
{
206
    stream_DCT_state *const ss = (stream_DCT_state *) st;
207
 
208
    gs_jpeg_destroy(ss);
209
    gs_free_object(ss->data.common->memory, ss->data.compress,
210
		   "s_DCTE_release");
211
    /* Switch the template pointer back in case we still need it. */
212
    st->template = &s_DCTE_template;
213
}
214
 
215
/* Stream template */
216
const stream_template s_DCTE_template =
217
{&st_DCT_state, s_DCTE_init, s_DCTE_process, 1000, 4000, s_DCTE_release,
218
 s_DCTE_set_defaults
219
};