1 /* Automatically generated from Squeak on 30 July 2012 4:52:43 pm
2    by VMMaker 4.9.8
3  */
4 
5 #include <math.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <time.h>
10 
11 /* Default EXPORT macro that does nothing (see comment in sq.h): */
12 #define EXPORT(returnType) returnType
13 
14 /* Do not include the entire sq.h file but just those parts needed. */
15 /*  The virtual machine proxy definition */
16 #include "sqVirtualMachine.h"
17 /* Configuration options */
18 #include "sqConfig.h"
19 /* Platform specific definitions */
20 #include "sqPlatformSpecific.h"
21 
22 #define true 1
23 #define false 0
24 #define null 0  /* using 'null' because nil is predefined in Think C */
25 #ifdef SQUEAK_BUILTIN_PLUGIN
26 #undef EXPORT
27 // was #undef EXPORT(returnType) but screws NorCroft cc
28 #define EXPORT(returnType) static returnType
29 #endif
30 #include "JPEGReadWriter2Plugin.h"
31 
32 #include "sqMemoryAccess.h"
33 
34 
35 /*** Constants ***/
36 
37 /*** Function Prototypes ***/
38 #pragma export on
39 EXPORT(const char*) getModuleName(void);
40 #pragma export off
41 static sqInt halt(void);
42 #pragma export on
43 EXPORT(sqInt) initialiseModule(void);
44 EXPORT(sqInt) primImageHeight(void);
45 EXPORT(sqInt) primImageWidth(void);
46 EXPORT(sqInt) primJPEGCompressStructSize(void);
47 EXPORT(sqInt) primJPEGDecompressStructSize(void);
48 EXPORT(sqInt) primJPEGErrorMgr2StructSize(void);
49 EXPORT(sqInt) primJPEGPluginIsPresent(void);
50 EXPORT(sqInt) primJPEGReadHeaderfromByteArrayerrorMgr(void);
51 EXPORT(sqInt) primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr(void);
52 EXPORT(sqInt) primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr(void);
53 EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter);
54 EXPORT(sqInt) shutdownModule(void);
55 #pragma export off
56 /*** Variables ***/
57 
58 #ifdef SQUEAK_BUILTIN_PLUGIN
59 extern
60 #endif
61 struct VirtualMachine* interpreterProxy;
62 static const char *moduleName =
63 #ifdef SQUEAK_BUILTIN_PLUGIN
64 	"JPEGReadWriter2Plugin 30 July 2012 (i)"
65 #else
66 	"JPEGReadWriter2Plugin 30 July 2012 (e)"
67 #endif
68 ;
69 
70 
71 
72 /*	Note: This is hardcoded so it can be run from Squeak.
73 	The module name is used for validating a module *after*
74 	it is loaded to check if it does really contain the module
75 	we're thinking it contains. This is important! */
76 
getModuleName(void)77 EXPORT(const char*) getModuleName(void) {
78 	return moduleName;
79 }
80 
halt(void)81 static sqInt halt(void) {
82 	;
83 }
84 
initialiseModule(void)85 EXPORT(sqInt) initialiseModule(void) {
86 	return 1;
87 }
88 
primImageHeight(void)89 EXPORT(sqInt) primImageHeight(void) {
90 	char *aJPEGDecompressStruct;
91 	sqInt _return_value;
92 
93 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0)));
94 	aJPEGDecompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0))));
95 	if (interpreterProxy->failed()) {
96 		return null;
97 	}
98 
99 		interpreterProxy->success
100 			((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct jpeg_decompress_struct)));
101 		if (interpreterProxy->failed()) return null;
102 	;
103 	_return_value = interpreterProxy->integerObjectOf((((j_decompress_ptr)aJPEGDecompressStruct)->image_height));
104 	if (interpreterProxy->failed()) {
105 		return null;
106 	}
107 	interpreterProxy->popthenPush(2, _return_value);
108 	return null;
109 }
110 
primImageWidth(void)111 EXPORT(sqInt) primImageWidth(void) {
112 	char *aJPEGDecompressStruct;
113 	sqInt _return_value;
114 
115 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0)));
116 	aJPEGDecompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0))));
117 	if (interpreterProxy->failed()) {
118 		return null;
119 	}
120 
121 		interpreterProxy->success
122 			((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct jpeg_decompress_struct)));
123 		if (interpreterProxy->failed()) return null;
124 	;
125 	_return_value = interpreterProxy->integerObjectOf((((j_decompress_ptr)aJPEGDecompressStruct)->image_width));
126 	if (interpreterProxy->failed()) {
127 		return null;
128 	}
129 	interpreterProxy->popthenPush(2, _return_value);
130 	return null;
131 }
132 
primJPEGCompressStructSize(void)133 EXPORT(sqInt) primJPEGCompressStructSize(void) {
134 	sqInt _return_value;
135 
136 	_return_value = interpreterProxy->integerObjectOf((sizeof(struct jpeg_compress_struct)));
137 	if (interpreterProxy->failed()) {
138 		return null;
139 	}
140 	interpreterProxy->popthenPush(1, _return_value);
141 	return null;
142 }
143 
primJPEGDecompressStructSize(void)144 EXPORT(sqInt) primJPEGDecompressStructSize(void) {
145 	sqInt _return_value;
146 
147 	_return_value = interpreterProxy->integerObjectOf((sizeof(struct jpeg_decompress_struct)));
148 	if (interpreterProxy->failed()) {
149 		return null;
150 	}
151 	interpreterProxy->popthenPush(1, _return_value);
152 	return null;
153 }
154 
primJPEGErrorMgr2StructSize(void)155 EXPORT(sqInt) primJPEGErrorMgr2StructSize(void) {
156 	sqInt _return_value;
157 
158 	_return_value = interpreterProxy->integerObjectOf((sizeof(struct error_mgr2)));
159 	if (interpreterProxy->failed()) {
160 		return null;
161 	}
162 	interpreterProxy->popthenPush(1, _return_value);
163 	return null;
164 }
165 
primJPEGPluginIsPresent(void)166 EXPORT(sqInt) primJPEGPluginIsPresent(void) {
167 	sqInt _return_value;
168 
169 	_return_value = (1? interpreterProxy->trueObject(): interpreterProxy->falseObject());
170 	if (interpreterProxy->failed()) {
171 		return null;
172 	}
173 	interpreterProxy->popthenPush(1, _return_value);
174 	return null;
175 }
176 
primJPEGReadHeaderfromByteArrayerrorMgr(void)177 EXPORT(sqInt) primJPEGReadHeaderfromByteArrayerrorMgr(void) {
178 	sqInt sourceSize;
179 	j_decompress_ptr  pcinfo;
180 	error_ptr2  pjerr;
181 	char *aJPEGDecompressStruct;
182 	char *source;
183 	char *aJPEGErrorMgr2Struct;
184 
185 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(2)));
186 	aJPEGDecompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(2))));
187 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(1)));
188 	source = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(1))));
189 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0)));
190 	aJPEGErrorMgr2Struct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0))));
191 	if (interpreterProxy->failed()) {
192 		return null;
193 	}
194 	pcinfo = null;
195 	pjerr = null;
196 	sourceSize = null;
197 	pcinfo;
198 	pjerr;
199 	sourceSize;
200 
201 		interpreterProxy->success
202 			((interpreterProxy->stSizeOf(interpreterProxy->stackValue(2))) >= (sizeof(struct jpeg_decompress_struct)));
203 		interpreterProxy->success
204 			((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct error_mgr2)));
205 		if (interpreterProxy->failed()) return null;
206 	;
207 
208 		sourceSize = interpreterProxy->stSizeOf(interpreterProxy->stackValue(1));
209 		pcinfo = (j_decompress_ptr)aJPEGDecompressStruct;
210 		pjerr = (error_ptr2)aJPEGErrorMgr2Struct;
211 		if (sourceSize) {
212 			pcinfo->err = jpeg_std_error(&pjerr->pub);
213 			pjerr->pub.error_exit = error_exit;
214 			if (setjmp(pjerr->setjmp_buffer)) {
215 				jpeg_destroy_decompress(pcinfo);
216 				sourceSize = 0;
217 			}
218 			if (sourceSize) {
219 				jpeg_create_decompress(pcinfo);
220 				jpeg_mem_src(pcinfo, source, sourceSize);
221 				jpeg_read_header(pcinfo, TRUE);
222 			}
223 		}
224 	;
225 	if (interpreterProxy->failed()) {
226 		return null;
227 	}
228 	interpreterProxy->pop(3);
229 	return null;
230 }
231 
primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr(void)232 EXPORT(sqInt) primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr(void) {
233 	unsigned *  formBits;
234 	sqInt ok;
235 	sqInt g1;
236 	sqInt gOff;
237 	error_ptr2  pjerr;
238 	sqInt bOff2;
239 	sqInt formWidth;
240 	sqInt formDepth;
241 	sqInt dmv1;
242 	sqInt formPix;
243 	sqInt dmo;
244 	sqInt formBitsOops;
245 	sqInt r2;
246 	sqInt dmi;
247 	sqInt r1;
248 	sqInt gOff2;
249 	sqInt j;
250 	sqInt formPitch;
251 	sqInt i;
252 	sqInt b2;
253 	sqInt rowStride;
254 	sqInt b1;
255 	sqInt formBitsSize;
256 	sqInt di;
257 	sqInt dmv2;
258 	sqInt rOff;
259 	JSAMPARRAY  buffer;
260 	sqInt pixPerWord;
261 	j_decompress_ptr  pcinfo;
262 	sqInt g2;
263 	sqInt bOff;
264 	sqInt sourceSize;
265 	sqInt rOff2;
266 	sqInt formHeight;
267 	char *aJPEGDecompressStruct;
268 	char *source;
269 	sqInt form;
270 	sqInt ditherFlag;
271 	char *aJPEGErrorMgr2Struct;
272 
273 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(4)));
274 	aJPEGDecompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(4))));
275 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(3)));
276 	source = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(3))));
277 	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(2), "Form"));
278 	form = interpreterProxy->stackValue(2);
279 	ditherFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1));
280 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0)));
281 	aJPEGErrorMgr2Struct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0))));
282 	if (interpreterProxy->failed()) {
283 		return null;
284 	}
285 	pcinfo = null;
286 	pjerr = null;
287 	buffer = null;
288 	rowStride = null;
289 	formDepth = null;
290 	formBits = null;
291 	i = null;
292 	j = null;
293 	formPix = null;
294 	ok = null;
295 	rOff = null;
296 	gOff = null;
297 	bOff = null;
298 	rOff2 = null;
299 	gOff2 = null;
300 	bOff2 = null;
301 	sourceSize = null;
302 	r1 = null;
303 	r2 = null;
304 	g1 = null;
305 	g2 = null;
306 	b1 = null;
307 	b2 = null;
308 	dmv1 = null;
309 	dmv2 = null;
310 	di = null;
311 	dmi = null;
312 	dmo = null;
313 	pcinfo;
314 	pjerr;
315 	buffer;
316 	rowStride;
317 	formBits;
318 	formDepth;
319 	i;
320 	j;
321 	formPix;
322 	ok;
323 	rOff;
324 	gOff;
325 	bOff;
326 	rOff2;
327 	gOff2;
328 	bOff2;
329 	sourceSize;
330 	r1;
331 	r2;
332 	g1;
333 	g2;
334 	b1;
335 	b2;
336 	dmv1;
337 	dmv2;
338 	di;
339 	dmi;
340 	dmo;
341 	formBitsOops = interpreterProxy->fetchPointerofObject(0, form);
342 
343 	/* Various parameter checks */
344 
345 	formDepth = interpreterProxy->fetchIntegerofObject(3, form);
346 
347 		interpreterProxy->success
348 			((interpreterProxy->stSizeOf(interpreterProxy->stackValue(4))) >= (sizeof(struct jpeg_decompress_struct)));
349 		interpreterProxy->success
350 			((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct error_mgr2)));
351 		if (interpreterProxy->failed()) return null;
352 	;
353 	formWidth = ((j_decompress_ptr)aJPEGDecompressStruct)->image_width;
354 	formHeight = ((j_decompress_ptr)aJPEGDecompressStruct)->image_height;
355 	pixPerWord = 32 / formDepth;
356 	formPitch = ((formWidth + (pixPerWord - 1)) / pixPerWord) * 4;
357 	formBitsSize = interpreterProxy->byteSizeOf(formBitsOops);
358 	interpreterProxy->success((interpreterProxy->isWordsOrBytes(formBitsOops)) && (formBitsSize == (formPitch * formHeight)));
359 	if (interpreterProxy->failed()) {
360 		return null;
361 	}
362 	formBits = interpreterProxy->firstIndexableField(formBitsOops);
363 
364 		sourceSize = interpreterProxy->stSizeOf(interpreterProxy->stackValue(3));
365 		if (sourceSize == 0) {
366 			interpreterProxy->success(false);
367 			return null;
368 		}
369 		pcinfo = (j_decompress_ptr)aJPEGDecompressStruct;
370 		pjerr = (error_ptr2)aJPEGErrorMgr2Struct;
371 		pcinfo->err = jpeg_std_error(&pjerr->pub);
372 		pjerr->pub.error_exit = error_exit;
373 		ok = 1;
374 		if (setjmp(pjerr->setjmp_buffer)) {
375 			jpeg_destroy_decompress(pcinfo);
376 			ok = 0;
377 		}
378 		if (ok) {
379 			ok = jpeg_mem_src_newLocationOfData(pcinfo, source, sourceSize);
380 			if (ok) {
381 				/* Dither Matrix taken from Form>>orderedDither32To16, but rewritten for this method. */
382 				int ditherMatrix1[] = { 2, 0, 14, 12, 1, 3, 13, 15 };
383 				int ditherMatrix2[] = { 10, 8, 6, 4, 9, 11, 5, 7 };
384  				jpeg_start_decompress(pcinfo);
385 				rowStride = pcinfo->output_width * pcinfo->output_components;
386 				if (pcinfo->out_color_components == 3) {
387 					rOff = 0; gOff = 1; bOff = 2;
388 					rOff2 = 3; gOff2 = 4; bOff2 = 5;
389 				} else {
390 					rOff = 0; gOff = 0; bOff = 0;
391 					rOff2 = 1; gOff2 = 1; bOff2 = 1;
392 				}
393 				/* Make a one-row-high sample array that will go away when done with image */
394 				buffer = (*(pcinfo->mem)->alloc_sarray)
395 					((j_common_ptr) pcinfo, JPOOL_IMAGE, rowStride, 1);
396 
397 				/* Step 6: while (scan lines remain to be read) */
398 				/*           jpeg_read_scanlines(...); */
399 
400 				/* Here we use the library state variable cinfo.output_scanline as the
401 				 * loop counter, so that we dont have to keep track ourselves.
402 				 */
403 				while (pcinfo->output_scanline < pcinfo->output_height) {
404 					/* jpeg_read_scanlines expects an array of pointers to scanlines.
405 					 * Here the array is only one element long, but you could ask for
406 					 * more than one scanline at a time if thats more convenient.
407 					 */
408 					(void) jpeg_read_scanlines(pcinfo, buffer, 1);
409 
410 					switch (formDepth) {
411 						case 32:
412 							for(i = 0, j = 0; i < rowStride; i +=(pcinfo->out_color_components), j++) {
413 								formPix = (255 << 24) | (buffer[0][i+rOff] << 16) | (buffer[0][i+gOff] << 8) | buffer[0][i+bOff];
414 								if (formPix == 0) formPix = 1;
415 								formBits [ ((pcinfo->output_scanline - 1) * (pcinfo->image_width)) + j ] = formPix;
416 							}
417 							break;
418 
419 						case 16:
420 							for(i = 0, j = 0; i < rowStride; i +=(pcinfo->out_color_components*2), j++) {
421 								r1 = buffer[0][i+rOff];
422 								r2 = buffer[0][i+rOff2];
423 								g1 = buffer[0][i+gOff];
424 								g2 = buffer[0][i+gOff2];
425 								b1 = buffer[0][i+bOff];
426 								b2 = buffer[0][i+bOff2];
427 
428 								if (!ditherFlag) {
429 									r1 = r1 >> 3;
430 									r2 = r2 >> 3;
431 									g1 = g1 >> 3;
432 									g2 = g2 >> 3;
433 									b1 = b1 >> 3;
434 									b2 = b2 >> 3;
435 								} else {
436 									/* Do 4x4 ordered dithering. Taken from Form>>orderedDither32To16 */
437 									dmv1 = ditherMatrix1[ ((pcinfo->output_scanline & 3 )<< 1) | (j&1) ];
438 									dmv2 = ditherMatrix2[ ((pcinfo->output_scanline & 3 )<< 1) | (j&1) ];
439 
440 									di = (r1 * 496) >> 8; dmi = di & 15; dmo = di >> 4;
441 									if(dmv1 < dmi) { r1 = dmo+1; } else { r1 = dmo; };
442 									di = (g1 * 496) >> 8; dmi = di & 15; dmo = di >> 4;
443 									if(dmv1 < dmi) { g1 = dmo+1; } else { g1 = dmo; };
444 									di = (b1 * 496) >> 8; dmi = di & 15; dmo = di >> 4;
445 									if(dmv1 < dmi) { b1 = dmo+1; } else { b1 = dmo; };
446 
447 									di = (r2 * 496) >> 8; dmi = di & 15; dmo = di >> 4;
448 									if(dmv2 < dmi) { r2 = dmo+1; } else { r2 = dmo; };
449 									di = (g2 * 496) >> 8; dmi = di & 15; dmo = di >> 4;
450 									if(dmv2 < dmi) { g2 = dmo+1; } else { g2 = dmo; };
451 									di = (b2 * 496) >> 8; dmi = di & 15; dmo = di >> 4;
452 									if(dmv2 < dmi) { b2 = dmo+1; } else { b2 = dmo; };
453 								}
454 
455 								formPix = (r1 << 10) | (g1 << 5) | b1;
456 								if (!formPix) formPix = 1;
457 								formPix = (formPix << 16) | (r2 << 10) | (g2 << 5) | b2;
458 								if (!(formPix & 65535)) formPix = formPix | 1;
459 								formBits [ ((pcinfo->output_scanline - 1) * (pcinfo->image_width)) / 2 + j ] = formPix;
460 							}
461 							break;
462 					}
463 				}
464 				jpeg_finish_decompress(pcinfo);
465 			}
466 			jpeg_destroy_decompress(pcinfo);
467 		}
468 	;
469 	if (interpreterProxy->failed()) {
470 		return null;
471 	}
472 	interpreterProxy->pop(5);
473 	return null;
474 }
475 
primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr(void)476 EXPORT(sqInt) primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr(void) {
477 	sqInt formWidth;
478 	sqInt j;
479 	unsigned int destinationSize;
480 	sqInt i;
481 	sqInt formPix;
482 	sqInt formDepth;
483 	error_ptr2  pjerr;
484 	sqInt formPitch;
485 	sqInt rowStride;
486 	sqInt formBitsSize;
487 	sqInt formBitsOops;
488 	sqInt formHeight;
489 	unsigned *  formBits;
490 	sqInt pixPerWord;
491 	j_compress_ptr  pcinfo;
492 	JSAMPARRAY  buffer;
493 	char *aJPEGCompressStruct;
494 	char *destination;
495 	sqInt form;
496 	sqInt quality;
497 	sqInt progressiveFlag;
498 	char *aJPEGErrorMgr2Struct;
499 	sqInt _return_value;
500 
501 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(5)));
502 	aJPEGCompressStruct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(5))));
503 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(4)));
504 	destination = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(4))));
505 	interpreterProxy->success(interpreterProxy->isKindOf(interpreterProxy->stackValue(3), "Form"));
506 	form = interpreterProxy->stackValue(3);
507 	quality = interpreterProxy->stackIntegerValue(2);
508 	progressiveFlag = interpreterProxy->booleanValueOf(interpreterProxy->stackValue(1));
509 	interpreterProxy->success(interpreterProxy->isBytes(interpreterProxy->stackValue(0)));
510 	aJPEGErrorMgr2Struct = ((char *) (interpreterProxy->firstIndexableField(interpreterProxy->stackValue(0))));
511 	if (interpreterProxy->failed()) {
512 		return null;
513 	}
514 	pcinfo = null;
515 	pjerr = null;
516 	buffer = null;
517 	rowStride = null;
518 	formBits = null;
519 	formWidth = null;
520 	formHeight = null;
521 	formDepth = null;
522 	i = null;
523 	j = null;
524 	formPix = null;
525 	destinationSize = null;
526 	pcinfo;
527 	pjerr;
528 	buffer;
529 	rowStride;
530 	formBits;
531 	formWidth;
532 	formHeight;
533 	formDepth;
534 	i;
535 	j;
536 	formPix;
537 	destinationSize;
538 	formBitsOops = interpreterProxy->fetchPointerofObject(0, form);
539 	formWidth = interpreterProxy->fetchIntegerofObject(1, form);
540 	formHeight = interpreterProxy->fetchIntegerofObject(2, form);
541 
542 	/* Various parameter checks */
543 
544 	formDepth = interpreterProxy->fetchIntegerofObject(3, form);
545 
546 		interpreterProxy->success
547 			((interpreterProxy->stSizeOf(interpreterProxy->stackValue(5))) >= (sizeof(struct jpeg_compress_struct)));
548 		interpreterProxy->success
549 			((interpreterProxy->stSizeOf(interpreterProxy->stackValue(0))) >= (sizeof(struct error_mgr2)));
550 		if (interpreterProxy->failed()) return null;
551 	;
552 	pixPerWord = 32 / formDepth;
553 	formPitch = ((formWidth + (pixPerWord - 1)) / pixPerWord) * 4;
554 	formBitsSize = interpreterProxy->byteSizeOf(formBitsOops);
555 	interpreterProxy->success((interpreterProxy->isWordsOrBytes(formBitsOops)) && (formBitsSize == (formPitch * formHeight)));
556 	if (interpreterProxy->failed()) {
557 		return null;
558 	}
559 	formBits = interpreterProxy->firstIndexableField(formBitsOops);
560 
561 		destinationSize = interpreterProxy->stSizeOf(interpreterProxy->stackValue(4));
562 		pcinfo = (j_compress_ptr)aJPEGCompressStruct;
563 		pjerr = (error_ptr2)aJPEGErrorMgr2Struct;
564 		if (destinationSize) {
565 			pcinfo->err = jpeg_std_error(&pjerr->pub);
566 			pjerr->pub.error_exit = error_exit;
567 			if (setjmp(pjerr->setjmp_buffer)) {
568 				jpeg_destroy_compress(pcinfo);
569 				destinationSize = 0;
570 			}
571 			if (destinationSize) {
572 				jpeg_create_compress(pcinfo);
573 				jpeg_mem_dest(pcinfo, destination, &destinationSize);
574 				pcinfo->image_width = formWidth;
575 				pcinfo->image_height = formHeight;
576 				pcinfo->input_components = 3;
577 				pcinfo->in_color_space = JCS_RGB;
578 				jpeg_set_defaults(pcinfo);
579 				if (quality > 0)
580 					jpeg_set_quality (pcinfo, quality, 1);
581 				if (progressiveFlag)
582 					jpeg_simple_progression(pcinfo);
583 				jpeg_start_compress(pcinfo, TRUE);
584 				rowStride = formWidth * 3;
585 
586 				/* Make a one-row-high sample array that will go away
587 				  when done with image */
588 				buffer = (*(pcinfo->mem)->alloc_sarray)
589 					((j_common_ptr) pcinfo, JPOOL_IMAGE, rowStride, 1);
590 
591 				while (pcinfo->next_scanline < pcinfo->image_height) {
592 					switch (formDepth) {
593 						case 32:
594 							for(i = 0, j = 0; i < rowStride; i +=3, j++) {
595 								formPix = formBits [ ((pcinfo->next_scanline) * formWidth) + j ];
596 								buffer[0][i] = (formPix >> 16) & 255;
597 								buffer[0][i+1] = (formPix >> 8) & 255;
598 								buffer[0][i+2] = formPix & 255;
599 							}
600 							break;
601 						case 16:
602 							for(i = 0, j = 0; i < rowStride; i +=6, j++) {
603 								formPix = formBits [ ((pcinfo->next_scanline) * formWidth) / 2 + j ];
604 								buffer[0][i] = (formPix >> 23) & 248;
605 								buffer[0][i+1] = (formPix >> 18) & 248;
606 								buffer[0][i+2] = (formPix >> 13) & 248;
607 								buffer[0][i+3] = (formPix >> 7) & 248;
608 								buffer[0][i+4] = (formPix >> 2) & 248;
609 								buffer[0][i+5] = (formPix << 3) & 248;
610 							}
611 							break;
612 					}
613 					(void) jpeg_write_scanlines(pcinfo, buffer, 1);
614 
615 				}
616 				jpeg_finish_compress(pcinfo);
617 				jpeg_destroy_compress(pcinfo);
618 			}
619 		}
620 	;
621 	_return_value = interpreterProxy->integerObjectOf((destinationSize));
622 	if (interpreterProxy->failed()) {
623 		return null;
624 	}
625 	interpreterProxy->popthenPush(7, _return_value);
626 	return null;
627 }
628 
629 
630 /*	Note: This is coded so that is can be run from Squeak. */
631 
setInterpreter(struct VirtualMachine * anInterpreter)632 EXPORT(sqInt) setInterpreter(struct VirtualMachine*anInterpreter) {
633 	sqInt ok;
634 
635 	interpreterProxy = anInterpreter;
636 	ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
637 	if (ok == 0) {
638 		return 0;
639 	}
640 	ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
641 	return ok;
642 }
643 
shutdownModule(void)644 EXPORT(sqInt) shutdownModule(void) {
645 	return 1;
646 }
647 
648 
649 #ifdef SQUEAK_BUILTIN_PLUGIN
650 
651 
652 void* JPEGReadWriter2Plugin_exports[][3] = {
653 	{"JPEGReadWriter2Plugin", "primImageWidth", (void*)primImageWidth},
654 	{"JPEGReadWriter2Plugin", "getModuleName", (void*)getModuleName},
655 	{"JPEGReadWriter2Plugin", "primJPEGCompressStructSize", (void*)primJPEGCompressStructSize},
656 	{"JPEGReadWriter2Plugin", "primJPEGErrorMgr2StructSize", (void*)primJPEGErrorMgr2StructSize},
657 	{"JPEGReadWriter2Plugin", "primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr", (void*)primJPEGWriteImageonByteArrayformqualityprogressiveJPEGerrorMgr},
658 	{"JPEGReadWriter2Plugin", "setInterpreter", (void*)setInterpreter},
659 	{"JPEGReadWriter2Plugin", "primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr", (void*)primJPEGReadImagefromByteArrayonFormdoDitheringerrorMgr},
660 	{"JPEGReadWriter2Plugin", "primImageHeight", (void*)primImageHeight},
661 	{"JPEGReadWriter2Plugin", "primJPEGReadHeaderfromByteArrayerrorMgr", (void*)primJPEGReadHeaderfromByteArrayerrorMgr},
662 	{"JPEGReadWriter2Plugin", "primJPEGPluginIsPresent", (void*)primJPEGPluginIsPresent},
663 	{"JPEGReadWriter2Plugin", "shutdownModule", (void*)shutdownModule},
664 	{"JPEGReadWriter2Plugin", "initialiseModule", (void*)initialiseModule},
665 	{"JPEGReadWriter2Plugin", "primJPEGDecompressStructSize", (void*)primJPEGDecompressStructSize},
666 	{NULL, NULL, NULL}
667 };
668 
669 
670 #endif /* ifdef SQ_BUILTIN_PLUGIN */
671 
672