/* Automatically generated by
	VMPluginCodeGenerator VMMaker.oscog-eem.2480 uuid: bb3ffda7-8241-4dea-b886-d656e474b6c1
   from
	JPEGReaderPlugin VMMaker.oscog-eem.2480 uuid: bb3ffda7-8241-4dea-b886-d656e474b6c1
 */
static char __buildInfo[] = "JPEGReaderPlugin VMMaker.oscog-eem.2480 uuid: bb3ffda7-8241-4dea-b886-d656e474b6c1 " __DATE__ ;



#include "config.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* Default EXPORT macro that does nothing (see comment in sq.h): */
#define EXPORT(returnType) returnType

/* Do not include the entire sq.h file but just those parts needed. */
#include "sqConfig.h"			/* Configuration options */
#include "sqVirtualMachine.h"	/*  The virtual machine proxy definition */
#include "sqPlatformSpecific.h"	/* Platform specific definitions */

#define true 1
#define false 0
#define null 0  /* using 'null' because nil is predefined in Think C */
#ifdef SQUEAK_BUILTIN_PLUGIN
# undef EXPORT
# define EXPORT(returnType) static returnType
#endif

#include "sqMemoryAccess.h"


/*** Constants ***/
#define BlockWidthIndex 5
#define BlueIndex 2
#define ConstBits 13
#define CurrentXIndex 0
#define CurrentYIndex 1
#define DCTSize 8
#define DCTSize2 64
#define FIXn0n298631336 2446
#define FIXn0n34414 22554
#define FIXn0n390180644 0xC7C
#define FIXn0n541196100 4433
#define FIXn0n71414 46802
#define FIXn0n765366865 6270
#define FIXn0n899976223 7373
#define FIXn1n175875602 9633
#define FIXn1n40200 91881
#define FIXn1n501321110 12299
#define FIXn1n77200 116130
#define FIXn1n847759065 15137
#define FIXn1n961570560 16069
#define FIXn2n053119869 16819
#define FIXn2n562915447 20995
#define FIXn3n072711026 25172
#define GreenIndex 1
#define HScaleIndex 2
#define MaxBits 16
#define MaxMCUBlocks 128
#define MaxSample 255
#define MCUBlockIndex 4
#define MCUWidthIndex 8
#define MinComponentSize 11
#define Pass1Bits 2
#define Pass1Div 0x800
#define Pass2Div 0x40000
#define PriorDCValueIndex 10
#define RedIndex 0
#define SampleOffset 127
#define VScaleIndex 3


/*** Function Prototypes ***/
static sqInt cbColorComponentFrom(sqInt oop);
static sqInt colorComponentBlocksfrom(int **blocks, sqInt oop);
static sqInt colorComponentfrom(int *aColorComponent, sqInt oop);
static sqInt colorConvertGrayscaleMCU(void);
static sqInt colorConvertMCU(void);
static sqInt crColorComponentFrom(sqInt oop);
static sqInt decodeBlockIntocomponent(int *anArray, int *aColorComponent);
static sqInt fillBuffer(void);
static sqInt getBits(sqInt requestedBits);
EXPORT(const char*) getModuleName(void);
static sqInt idctBlockIntqt(int *anArray, int *qt);
static sqInt jpegDecodeValueFromsize(int *table, sqInt tableSize);
static sqInt loadJPEGStreamFrom(sqInt streamOop);
static sqInt nextSampleCb(void);
static sqInt nextSampleCr(void);
static sqInt nextSampleFromblocks(int *aComponent, int **aBlockArray);
static sqInt nextSampleY(void);
EXPORT(sqInt) primitiveColorConvertGrayscaleMCU(void);
EXPORT(sqInt) primitiveColorConvertMCU(void);
EXPORT(sqInt) primitiveDecodeMCU(void);
EXPORT(sqInt) primitiveIdctInt(void);
static sqInt scaleAndSignExtendinFieldWidth(sqInt aNumber, sqInt w);
EXPORT(sqInt) setInterpreter(struct VirtualMachine *anInterpreter);
static sqInt stInit(void);
static sqInt storeJPEGStreamOn(sqInt streamOop);
static sqInt yColorComponentFrom(sqInt oop);


/*** Variables ***/
static int *acTable;
static sqInt acTableSize;
static int *cbBlocks[128];
static int cbComponent[11];
static sqInt cbSampleStream;
static int *crBlocks[128];
static int crComponent[11];
static sqInt crSampleStream;
static int *dcTable;
static sqInt dcTableSize;
static sqInt ditherMask;

#if !defined(SQUEAK_BUILTIN_PLUGIN)
static sqInt (*byteSizeOf)(sqInt oop);
static sqInt (*failed)(void);
static sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer);
static sqInt (*fetchPointerofObject)(sqInt index, sqInt oop);
static void * (*firstIndexableField)(sqInt oop);
static sqInt (*isBytes)(sqInt oop);
static sqInt (*isPointers)(sqInt oop);
static sqInt (*isWords)(sqInt oop);
static sqInt (*methodArgumentCount)(void);
static sqInt (*pop)(sqInt nItems);
static sqInt (*primitiveFail)(void);
static sqInt (*slotSizeOf)(sqInt oop);
static sqInt (*stackIntegerValue)(sqInt offset);
static sqInt (*stackValue)(sqInt offset);
static sqInt (*storeIntegerofObjectwithValue)(sqInt index, sqInt oop, sqInt integer);
#else /* !defined(SQUEAK_BUILTIN_PLUGIN) */
extern sqInt byteSizeOf(sqInt oop);
extern sqInt failed(void);
extern sqInt fetchIntegerofObject(sqInt fieldIndex, sqInt objectPointer);
extern sqInt fetchPointerofObject(sqInt index, sqInt oop);
extern void * firstIndexableField(sqInt oop);
extern sqInt isBytes(sqInt oop);
extern sqInt isPointers(sqInt oop);
extern sqInt isWords(sqInt oop);
extern sqInt methodArgumentCount(void);
extern sqInt pop(sqInt nItems);
extern sqInt primitiveFail(void);
extern sqInt slotSizeOf(sqInt oop);
extern sqInt stackIntegerValue(sqInt offset);
extern sqInt stackValue(sqInt offset);
extern sqInt storeIntegerofObjectwithValue(sqInt index, sqInt oop, sqInt integer);
extern
#endif
struct VirtualMachine* interpreterProxy;
static int *jpegBits;
static sqInt jpegBitsSize;
static int jpegNaturalOrder[64] = {
	0, 1, 8, 16, 9, 2, 3, 10, 
	17, 24, 32, 25, 18, 11, 4, 5, 
	12, 19, 26, 33, 40, 48, 41, 34, 
	27, 20, 13, 6, 7, 14, 21, 28, 
	35, 42, 49, 56, 57, 50, 43, 36, 
	29, 22, 15, 23, 30, 37, 44, 51, 
	58, 59, 52, 45, 38, 31, 39, 46, 
	53, 60, 61, 54, 47, 55, 62, 63
};
static sqInt jsBitBuffer;
static sqInt jsBitCount;
static unsigned char *jsCollection;
static sqInt jsPosition;
static sqInt jsReadLimit;
static const char *moduleName =
#ifdef SQUEAK_BUILTIN_PLUGIN
	"JPEGReaderPlugin VMMaker.oscog-eem.2480 (i)"
#else
	"JPEGReaderPlugin VMMaker.oscog-eem.2480 (e)"
#endif
;
static int *residuals;
static int *yBlocks[128];
static int yComponent[11];
static sqInt ySampleStream;


	/* JPEGReaderPlugin>>#cbColorComponentFrom: */
static sqInt
cbColorComponentFrom(sqInt oop)
{
	return (colorComponentfrom(cbComponent, oop))
	 && (colorComponentBlocksfrom(cbBlocks, oop));
}

	/* JPEGReaderPlugin>>#colorComponentBlocks:from: */
static sqInt
colorComponentBlocksfrom(int **blocks, sqInt oop)
{
    sqInt arrayOop;
    sqInt blockOop;
    sqInt i;
    sqInt max;

	if (!(isPointers(oop))) {
		return 0;
	}
	if ((slotSizeOf(oop)) < MinComponentSize) {
		return 0;
	}
	arrayOop = fetchPointerofObject(MCUBlockIndex, oop);
	if (!(isPointers(arrayOop))) {
		return 0;
	}
	max = slotSizeOf(arrayOop);
	if (max > MaxMCUBlocks) {
		return 0;
	}
	for (i = 0; i < max; i += 1) {
		blockOop = fetchPointerofObject(i, arrayOop);
		if (!(isWords(blockOop))) {
			return 0;
		}
		if (!((slotSizeOf(blockOop)) == DCTSize2)) {
			return 0;
		}
		blocks[i] = (firstIndexableField(blockOop));
	}
	return !(failed());
}

	/* JPEGReaderPlugin>>#colorComponent:from: */
static sqInt
colorComponentfrom(int *aColorComponent, sqInt oop)
{
	if (!(isPointers(oop))) {
		return 0;
	}
	if ((slotSizeOf(oop)) < MinComponentSize) {
		return 0;
	}
	aColorComponent[CurrentXIndex] = (fetchIntegerofObject(CurrentXIndex, oop));
	aColorComponent[CurrentYIndex] = (fetchIntegerofObject(CurrentYIndex, oop));
	aColorComponent[HScaleIndex] = (fetchIntegerofObject(HScaleIndex, oop));
	aColorComponent[VScaleIndex] = (fetchIntegerofObject(VScaleIndex, oop));
	aColorComponent[BlockWidthIndex] = (fetchIntegerofObject(BlockWidthIndex, oop));
	aColorComponent[MCUWidthIndex] = (fetchIntegerofObject(MCUWidthIndex, oop));
	aColorComponent[PriorDCValueIndex] = (fetchIntegerofObject(PriorDCValueIndex, oop));
	return !(failed());
}

	/* JPEGReaderPlugin>>#colorConvertGrayscaleMCU */
static sqInt
colorConvertGrayscaleMCU(void)
{
    sqInt blockIndex;
    int curX;
    int dx;
    int dy;
    sqInt i;
    int sample;
    sqInt sampleIndex;
    int sx;
    int sy;
    sqInt y;

	yComponent[CurrentXIndex] = 0;
	yComponent[CurrentYIndex] = 0;
	for (i = 0; i < jpegBitsSize; i += 1) {
		/* begin nextSampleY */
		dx = (curX = yComponent[CurrentXIndex]);
		dy = yComponent[CurrentYIndex];
		sx = yComponent[HScaleIndex];
		sy = yComponent[VScaleIndex];
		if (!((sx == 0)
			 && (sy == 0))) {
			dx = dx / sx;
			dy = dy / sy;
		}
		blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3));
		sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7);
		sample = (yBlocks[blockIndex])[sampleIndex];
		curX += 1;
		if (curX < ((yComponent[MCUWidthIndex]) * 8)) {
			yComponent[CurrentXIndex] = curX;
		}
		else {
			yComponent[CurrentXIndex] = 0;
			yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1);
		}
		y = sample;
		y += residuals[GreenIndex];
		y = ((y < MaxSample) ? y : MaxSample);
		residuals[GreenIndex] = (y & ditherMask);
		y = y & (MaxSample - ditherMask);
		y = ((y < 1) ? 1 : y);
		jpegBits[i] = (((0xFF000000U + (((sqInt)((usqInt)(y) << 16)))) + (((sqInt)((usqInt)(y) << 8)))) + y);
	}
	return 0;
}

	/* JPEGReaderPlugin>>#colorConvertMCU */
static sqInt
colorConvertMCU(void)
{
    sqInt blockIndex;
    sqInt blockIndex1;
    sqInt blockIndex2;
    sqInt blue;
    sqInt cb;
    sqInt cr;
    int curX;
    int curX1;
    int curX2;
    int dx;
    int dx1;
    int dx2;
    int dy;
    int dy1;
    int dy2;
    sqInt green;
    sqInt i;
    sqInt red;
    int sample;
    int sample1;
    int sample2;
    sqInt sampleIndex;
    sqInt sampleIndex1;
    sqInt sampleIndex2;
    int sx;
    int sx1;
    int sx2;
    int sy;
    int sy1;
    int sy2;
    sqInt y;

	yComponent[CurrentXIndex] = 0;
	yComponent[CurrentYIndex] = 0;
	cbComponent[CurrentXIndex] = 0;
	cbComponent[CurrentYIndex] = 0;
	crComponent[CurrentXIndex] = 0;
	crComponent[CurrentYIndex] = 0;
	for (i = 0; i < jpegBitsSize; i += 1) {
		/* begin nextSampleY */
		dx = (curX = yComponent[CurrentXIndex]);
		dy = yComponent[CurrentYIndex];
		sx = yComponent[HScaleIndex];
		sy = yComponent[VScaleIndex];
		if (!((sx == 0)
			 && (sy == 0))) {
			dx = dx / sx;
			dy = dy / sy;
		}
		blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3));
		sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7);
		sample = (yBlocks[blockIndex])[sampleIndex];
		curX += 1;
		if (curX < ((yComponent[MCUWidthIndex]) * 8)) {
			yComponent[CurrentXIndex] = curX;
		}
		else {
			yComponent[CurrentXIndex] = 0;
			yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1);
		}
		y = sample;
		/* begin nextSampleCb */
		dx1 = (curX1 = cbComponent[CurrentXIndex]);
		dy1 = cbComponent[CurrentYIndex];
		sx1 = cbComponent[HScaleIndex];
		sy1 = cbComponent[VScaleIndex];
		if (!((sx1 == 0)
			 && (sy1 == 0))) {
			dx1 = dx1 / sx1;
			dy1 = dy1 / sy1;
		}
		blockIndex1 = ((((usqInt) dy1 >> 3)) * (cbComponent[BlockWidthIndex])) + (((usqInt) dx1 >> 3));
		sampleIndex1 = (((usqInt) (dy1 & 7) << 3)) + (dx1 & 7);
		sample1 = (cbBlocks[blockIndex1])[sampleIndex1];
		curX1 += 1;
		if (curX1 < ((cbComponent[MCUWidthIndex]) * 8)) {
			cbComponent[CurrentXIndex] = curX1;
		}
		else {
			cbComponent[CurrentXIndex] = 0;
			cbComponent[CurrentYIndex] = ((cbComponent[CurrentYIndex]) + 1);
		}
		cb = sample1;
		cb -= SampleOffset;
		/* begin nextSampleCr */
		dx2 = (curX2 = crComponent[CurrentXIndex]);
		dy2 = crComponent[CurrentYIndex];
		sx2 = crComponent[HScaleIndex];
		sy2 = crComponent[VScaleIndex];
		if (!((sx2 == 0)
			 && (sy2 == 0))) {
			dx2 = dx2 / sx2;
			dy2 = dy2 / sy2;
		}
		blockIndex2 = ((((usqInt) dy2 >> 3)) * (crComponent[BlockWidthIndex])) + (((usqInt) dx2 >> 3));
		sampleIndex2 = (((usqInt) (dy2 & 7) << 3)) + (dx2 & 7);
		sample2 = (crBlocks[blockIndex2])[sampleIndex2];
		curX2 += 1;
		if (curX2 < ((crComponent[MCUWidthIndex]) * 8)) {
			crComponent[CurrentXIndex] = curX2;
		}
		else {
			crComponent[CurrentXIndex] = 0;
			crComponent[CurrentYIndex] = ((crComponent[CurrentYIndex]) + 1);
		}
		cr = sample2;
		cr -= SampleOffset;
		red = (y + ((FIXn1n40200 * cr) / 65536)) + (residuals[RedIndex]);
		red = ((red < MaxSample) ? red : MaxSample);
		red = ((red < 0) ? 0 : red);
		residuals[RedIndex] = (red & ditherMask);
		red = red & (MaxSample - ditherMask);
		red = ((red < 1) ? 1 : red);
		green = ((y - ((FIXn0n34414 * cb) / 65536)) - ((FIXn0n71414 * cr) / 65536)) + (residuals[GreenIndex]);
		green = ((green < MaxSample) ? green : MaxSample);
		green = ((green < 0) ? 0 : green);
		residuals[GreenIndex] = (green & ditherMask);
		green = green & (MaxSample - ditherMask);
		green = ((green < 1) ? 1 : green);
		blue = (y + ((FIXn1n77200 * cb) / 65536)) + (residuals[BlueIndex]);
		blue = ((blue < MaxSample) ? blue : MaxSample);
		blue = ((blue < 0) ? 0 : blue);
		residuals[BlueIndex] = (blue & ditherMask);
		blue = blue & (MaxSample - ditherMask);
		blue = ((blue < 1) ? 1 : blue);
		jpegBits[i] = (((0xFF000000U + (((usqInt) red << 16))) + (((usqInt) green << 8))) + blue);
	}
	return 0;
}

	/* JPEGReaderPlugin>>#crColorComponentFrom: */
static sqInt
crColorComponentFrom(sqInt oop)
{
	return (colorComponentfrom(crComponent, oop))
	 && (colorComponentBlocksfrom(crBlocks, oop));
}

	/* JPEGReaderPlugin>>#decodeBlockInto:component: */
static sqInt
decodeBlockIntocomponent(int *anArray, int *aColorComponent)
{
    sqInt bits;
    sqInt byte;
    unsigned char byte1;
    unsigned char byte2;
    sqInt i;
    sqInt index;
    sqInt value;
    sqInt value1;
    sqInt zeroCount;

	byte = jpegDecodeValueFromsize(dcTable, dcTableSize);
	if (byte < 0) {
		return primitiveFail();
	}
	if (byte != 0) {
		/* begin getBits: */
		if (byte > jsBitCount) {
			/* begin fillBuffer */
			while (jsBitCount <= 16) {
				if (!(jsPosition < jsReadLimit)) {
					goto l1;
				}
				byte1 = jsCollection[jsPosition];
				jsPosition += 1;
				if (byte1 == 0xFF) {

					/* peek for 00 */
					if (!((jsPosition < jsReadLimit)
						 && ((jsCollection[jsPosition]) == 0))) {
						jsPosition -= 1;
						goto l1;
					}
					jsPosition += 1;
				}
				jsBitBuffer = (((usqInt) jsBitBuffer << 8)) | byte1;
				jsBitCount += 8;
			}
	l1:	/* end fillBuffer */;
			if (byte > jsBitCount) {
				bits = -1;
				goto l2;
			}
		}
		jsBitCount -= byte;
		value = ((usqInt) jsBitBuffer) >> jsBitCount;
		jsBitBuffer = jsBitBuffer & ((1U << jsBitCount) - 1);
		bits = value;
	l2:	/* end getBits: */;
		/* begin scaleAndSignExtend:inFieldWidth: */
		if (bits < (1U << (byte - 1))) {
			byte = (bits - (1U << byte)) + 1;
			goto l3;
		}
		else {
			byte = bits;
			goto l3;
		}
	l3:	/* end scaleAndSignExtend:inFieldWidth: */;
	}
	byte = aColorComponent[PriorDCValueIndex] = ((aColorComponent[PriorDCValueIndex]) + byte);
	anArray[0] = byte;
	for (i = 1; i < DCTSize2; i += 1) {
		anArray[i] = 0;
	}
	index = 1;
	while (index < DCTSize2) {
		byte = jpegDecodeValueFromsize(acTable, acTableSize);
		if (byte < 0) {
			return primitiveFail();
		}
		zeroCount = ((usqInt) byte) >> 4;
		byte = byte & 15;
		if (byte != 0) {
			index += zeroCount;
			/* begin getBits: */
			if (byte > jsBitCount) {
				/* begin fillBuffer */
				while (jsBitCount <= 16) {
					if (!(jsPosition < jsReadLimit)) {
						goto l4;
					}
					byte2 = jsCollection[jsPosition];
					jsPosition += 1;
					if (byte2 == 0xFF) {

						/* peek for 00 */
						if (!((jsPosition < jsReadLimit)
							 && ((jsCollection[jsPosition]) == 0))) {
							jsPosition -= 1;
							goto l4;
						}
						jsPosition += 1;
					}
					jsBitBuffer = (((usqInt) jsBitBuffer << 8)) | byte2;
					jsBitCount += 8;
				}
	l4:	/* end fillBuffer */;
				if (byte > jsBitCount) {
					bits = -1;
					goto l5;
				}
			}
			jsBitCount -= byte;
			value1 = ((usqInt) jsBitBuffer) >> jsBitCount;
			jsBitBuffer = jsBitBuffer & ((1U << jsBitCount) - 1);
			bits = value1;
	l5:	/* end getBits: */;
			/* begin scaleAndSignExtend:inFieldWidth: */
			if (bits < (1U << (byte - 1))) {
				byte = (bits - (1U << byte)) + 1;
				goto l6;
			}
			else {
				byte = bits;
				goto l6;
			}
	l6:	/* end scaleAndSignExtend:inFieldWidth: */;
			if ((index < 0)
			 || (index >= DCTSize2)) {
				return primitiveFail();
			}
			anArray[jpegNaturalOrder[index]] = byte;
		}
		else {
			if (zeroCount == 15) {
				index += zeroCount;
			}
			else {
				return null;
			}
		}
		index += 1;
	}
	return 0;
}

	/* JPEGReaderPlugin>>#fillBuffer */
static sqInt
fillBuffer(void)
{
    unsigned char byte;

	while (jsBitCount <= 16) {
		if (!(jsPosition < jsReadLimit)) {
			return jsBitCount;
		}
		byte = jsCollection[jsPosition];
		jsPosition += 1;
		if (byte == 0xFF) {

			/* peek for 00 */
			if (!((jsPosition < jsReadLimit)
				 && ((jsCollection[jsPosition]) == 0))) {
				jsPosition -= 1;
				return jsBitCount;
			}
			jsPosition += 1;
		}
		jsBitBuffer = (((usqInt) jsBitBuffer << 8)) | byte;
		jsBitCount += 8;
	}
	return jsBitCount;
}

	/* JPEGReaderPlugin>>#getBits: */
static sqInt
getBits(sqInt requestedBits)
{
    unsigned char byte;
    sqInt value;

	if (requestedBits > jsBitCount) {
		/* begin fillBuffer */
		while (jsBitCount <= 16) {
			if (!(jsPosition < jsReadLimit)) {
				goto l1;
			}
			byte = jsCollection[jsPosition];
			jsPosition += 1;
			if (byte == 0xFF) {

				/* peek for 00 */
				if (!((jsPosition < jsReadLimit)
					 && ((jsCollection[jsPosition]) == 0))) {
					jsPosition -= 1;
					goto l1;
				}
				jsPosition += 1;
			}
			jsBitBuffer = (((usqInt) jsBitBuffer << 8)) | byte;
			jsBitCount += 8;
		}
	l1:	/* end fillBuffer */;
		if (requestedBits > jsBitCount) {
			return -1;
		}
	}
	jsBitCount -= requestedBits;
	value = ((usqInt) jsBitBuffer) >> jsBitCount;
	jsBitBuffer = jsBitBuffer & ((1U << jsBitCount) - 1);
	return value;
}


/*	Note: This is hardcoded so it can be run from Squeak.
	The module name is used for validating a module *after*
	it is loaded to check if it does really contain the module
	we're thinking it contains. This is important! */

	/* InterpreterPlugin>>#getModuleName */
EXPORT(const char*)
getModuleName(void)
{
	return moduleName;
}

	/* JPEGReaderPlugin>>#idctBlockInt:qt: */
static sqInt
idctBlockIntqt(int *anArray, int *qt)
{
    sqInt anACTerm;
    int dcval;
    sqInt i;
    sqInt j;
    sqInt row;
    sqInt t0;
    sqInt t1;
    sqInt t10;
    sqInt t11;
    sqInt t12;
    sqInt t13;
    int t2;
    int t3;
    sqInt v;
    int ws[64];
    int z1;
    int z2;
    int z3;
    sqInt z4;
    sqInt z5;

	for (i = 0; i < DCTSize; i += 1) {
		anACTerm = -1;
		for (row = 1; row < DCTSize; row += 1) {
			if (anACTerm == -1) {
				if (!((anArray[(row * DCTSize) + i]) == 0)) {
					anACTerm = row;
				}
			}
		}
		if (anACTerm == -1) {
			dcval = ((sqInt)((usqInt)(((anArray[i]) * (qt[0]))) << Pass1Bits));
			for (j = 0; j < DCTSize; j += 1) {
				ws[(j * DCTSize) + i] = dcval;
			}
		}
		else {
			z2 = (anArray[(DCTSize * 2) + i]) * (qt[(DCTSize * 2) + i]);
			z3 = (anArray[(DCTSize * 6) + i]) * (qt[(DCTSize * 6) + i]);
			z1 = (z2 + z3) * FIXn0n541196100;
			t2 = z1 + (z3 * (0 - FIXn1n847759065));
			t3 = z1 + (z2 * FIXn0n765366865);
			z2 = (anArray[i]) * (qt[i]);
			z3 = (anArray[(DCTSize * 4) + i]) * (qt[(DCTSize * 4) + i]);
			t0 = ((sqInt)((usqInt)((z2 + z3)) << ConstBits));
			t1 = ((sqInt)((usqInt)((z2 - z3)) << ConstBits));
			t10 = t0 + t3;
			t13 = t0 - t3;
			t11 = t1 + t2;
			t12 = t1 - t2;
			t0 = (anArray[(DCTSize * 7) + i]) * (qt[(DCTSize * 7) + i]);
			t1 = (anArray[(DCTSize * 5) + i]) * (qt[(DCTSize * 5) + i]);
			t2 = (anArray[(DCTSize * 3) + i]) * (qt[(DCTSize * 3) + i]);
			t3 = (anArray[DCTSize + i]) * (qt[DCTSize + i]);
			z1 = t0 + t3;
			z2 = t1 + t2;
			z3 = t0 + t2;
			z4 = t1 + t3;
			z5 = (z3 + z4) * FIXn1n175875602;
			t0 = t0 * FIXn0n298631336;
			t1 = t1 * FIXn2n053119869;
			t2 = t2 * FIXn3n072711026;
			t3 = t3 * FIXn1n501321110;
			z1 = z1 * (0 - FIXn0n899976223);
			z2 = z2 * (0 - FIXn2n562915447);
			z3 = z3 * (0 - FIXn1n961570560);
			z4 = z4 * (0 - FIXn0n390180644);
			z3 += z5;
			z4 += z5;
			t0 = (t0 + z1) + z3;
			t1 = (t1 + z2) + z4;
			t2 = (t2 + z2) + z3;
			t3 = (t3 + z1) + z4;
			ws[i] = ((t10 + t3) / Pass1Div);
			ws[(DCTSize * 7) + i] = ((t10 - t3) / Pass1Div);
			ws[(DCTSize) + i] = ((t11 + t2) / Pass1Div);
			ws[(DCTSize * 6) + i] = ((t11 - t2) / Pass1Div);
			ws[(DCTSize * 2) + i] = ((t12 + t1) / Pass1Div);
			ws[(DCTSize * 5) + i] = ((t12 - t1) / Pass1Div);
			ws[(DCTSize * 3) + i] = ((t13 + t0) / Pass1Div);
			ws[(DCTSize * 4) + i] = ((t13 - t0) / Pass1Div);
		}
	}
	for (i = 0; i <= (DCTSize2 - DCTSize); i += DCTSize) {
		z2 = ws[i + 2];
		z3 = ws[i + 6];
		z1 = (z2 + z3) * FIXn0n541196100;
		t2 = z1 + (z3 * (0 - FIXn1n847759065));
		t3 = z1 + (z2 * FIXn0n765366865);
		t0 = ((sqInt)((usqInt)(((ws[i]) + (ws[i + 4]))) << ConstBits));
		t1 = ((sqInt)((usqInt)(((ws[i]) - (ws[i + 4]))) << ConstBits));
		t10 = t0 + t3;
		t13 = t0 - t3;
		t11 = t1 + t2;
		t12 = t1 - t2;
		t0 = ws[i + 7];
		t1 = ws[i + 5];
		t2 = ws[i + 3];
		t3 = ws[i + 1];
		z1 = t0 + t3;
		z2 = t1 + t2;
		z3 = t0 + t2;
		z4 = t1 + t3;
		z5 = (z3 + z4) * FIXn1n175875602;
		t0 = t0 * FIXn0n298631336;
		t1 = t1 * FIXn2n053119869;
		t2 = t2 * FIXn3n072711026;
		t3 = t3 * FIXn1n501321110;
		z1 = z1 * (0 - FIXn0n899976223);
		z2 = z2 * (0 - FIXn2n562915447);
		z3 = z3 * (0 - FIXn1n961570560);
		z4 = z4 * (0 - FIXn0n390180644);
		z3 += z5;
		z4 += z5;
		t0 = (t0 + z1) + z3;
		t1 = (t1 + z2) + z4;
		t2 = (t2 + z2) + z3;
		t3 = (t3 + z1) + z4;
		v = ((t10 + t3) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i] = v;
		v = ((t10 - t3) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 7] = v;
		v = ((t11 + t2) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 1] = v;
		v = ((t11 - t2) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 6] = v;
		v = ((t12 + t1) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 2] = v;
		v = ((t12 - t1) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 5] = v;
		v = ((t13 + t0) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 3] = v;
		v = ((t13 - t0) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 4] = v;
	}
	return 0;
}


/*	Decode the next value in the receiver using the given huffman table. */

	/* JPEGReaderPlugin>>#jpegDecodeValueFrom:size: */
static sqInt
jpegDecodeValueFromsize(int *table, sqInt tableSize)
{
    sqInt bits;
    sqInt bitsNeeded;
    unsigned char byte;
    sqInt index;
    sqInt tableIndex;
    int value;
    sqInt value1;


	/* Initial bits needed */
	bitsNeeded = ((usqInt) (table[0])) >> 24;
	if (bitsNeeded > MaxBits) {
		return -1;
	}

	/* First real table */
	tableIndex = 2;
	while (1) {
		/* begin getBits: */
		if (bitsNeeded > jsBitCount) {
			/* begin fillBuffer */
			while (jsBitCount <= 16) {
				if (!(jsPosition < jsReadLimit)) {
					goto l1;
				}
				byte = jsCollection[jsPosition];
				jsPosition += 1;
				if (byte == 0xFF) {

					/* peek for 00 */
					if (!((jsPosition < jsReadLimit)
						 && ((jsCollection[jsPosition]) == 0))) {
						jsPosition -= 1;
						goto l1;
					}
					jsPosition += 1;
				}
				jsBitBuffer = (((usqInt) jsBitBuffer << 8)) | byte;
				jsBitCount += 8;
			}
	l1:	/* end fillBuffer */;
			if (bitsNeeded > jsBitCount) {
				bits = -1;
				goto l2;
			}
		}
		jsBitCount -= bitsNeeded;
		value1 = ((usqInt) jsBitBuffer) >> jsBitCount;
		jsBitBuffer = jsBitBuffer & ((1U << jsBitCount) - 1);
		bits = value1;
	l2:	/* end getBits: */;
		if (bits < 0) {
			return -1;
		}
		index = (tableIndex + bits) - 1;
		if (index >= tableSize) {
			return -1;
		}

		/* Lookup entry in table */
		value = table[index];
		if ((value & 0x3F000000) == 0) {
			return value;
		}

		/* Table offset in low 16 bit */
		tableIndex = value & 0xFFFF;

		/* Additional bits in high 8 bit */
		bitsNeeded = (((usqInt) value) >> 24) & 0xFF;
		if (bitsNeeded > MaxBits) {
			return -1;
		}
	}
	return -1;
}

	/* JPEGReaderPlugin>>#loadJPEGStreamFrom: */
static sqInt
loadJPEGStreamFrom(sqInt streamOop)
{
    sqInt oop;
    sqInt sz;

	if (!(isPointers(streamOop))) {
		return 0;
	}
	if ((slotSizeOf(streamOop)) < 5) {
		return 0;
	}
	oop = fetchPointerofObject(0, streamOop);
	if (!(isBytes(oop))) {
		return 0;
	}
	jsCollection = firstIndexableField(oop);
	sz = byteSizeOf(oop);
	jsPosition = fetchIntegerofObject(1, streamOop);
	jsReadLimit = fetchIntegerofObject(2, streamOop);
	jsBitBuffer = fetchIntegerofObject(3, streamOop);
	jsBitCount = fetchIntegerofObject(4, streamOop);
	if (failed()) {
		return 0;
	}
	if (sz < jsReadLimit) {
		return 0;
	}
	if ((jsPosition < 0)
	 || (jsPosition >= jsReadLimit)) {
		return 0;
	}
	return 1;
}

	/* JPEGReaderPlugin>>#nextSampleCb */
static sqInt
nextSampleCb(void)
{
    sqInt blockIndex;
    int curX;
    int dx;
    int dy;
    int sample;
    sqInt sampleIndex;
    int sx;
    int sy;

	dx = (curX = cbComponent[CurrentXIndex]);
	dy = cbComponent[CurrentYIndex];
	sx = cbComponent[HScaleIndex];
	sy = cbComponent[VScaleIndex];
	if (!((sx == 0)
		 && (sy == 0))) {
		dx = dx / sx;
		dy = dy / sy;
	}
	blockIndex = ((((usqInt) dy >> 3)) * (cbComponent[BlockWidthIndex])) + (((usqInt) dx >> 3));
	sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7);
	sample = (cbBlocks[blockIndex])[sampleIndex];
	curX += 1;
	if (curX < ((cbComponent[MCUWidthIndex]) * 8)) {
		cbComponent[CurrentXIndex] = curX;
	}
	else {
		cbComponent[CurrentXIndex] = 0;
		cbComponent[CurrentYIndex] = ((cbComponent[CurrentYIndex]) + 1);
	}
	return sample;
}

	/* JPEGReaderPlugin>>#nextSampleCr */
static sqInt
nextSampleCr(void)
{
    sqInt blockIndex;
    int curX;
    int dx;
    int dy;
    int sample;
    sqInt sampleIndex;
    int sx;
    int sy;

	dx = (curX = crComponent[CurrentXIndex]);
	dy = crComponent[CurrentYIndex];
	sx = crComponent[HScaleIndex];
	sy = crComponent[VScaleIndex];
	if (!((sx == 0)
		 && (sy == 0))) {
		dx = dx / sx;
		dy = dy / sy;
	}
	blockIndex = ((((usqInt) dy >> 3)) * (crComponent[BlockWidthIndex])) + (((usqInt) dx >> 3));
	sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7);
	sample = (crBlocks[blockIndex])[sampleIndex];
	curX += 1;
	if (curX < ((crComponent[MCUWidthIndex]) * 8)) {
		crComponent[CurrentXIndex] = curX;
	}
	else {
		crComponent[CurrentXIndex] = 0;
		crComponent[CurrentYIndex] = ((crComponent[CurrentYIndex]) + 1);
	}
	return sample;
}

	/* JPEGReaderPlugin>>#nextSampleFrom:blocks: */
static sqInt
nextSampleFromblocks(int *aComponent, int **aBlockArray)
{
    sqInt blockIndex;
    int curX;
    int dx;
    int dy;
    int sample;
    sqInt sampleIndex;
    int sx;
    int sy;

	dx = (curX = aComponent[CurrentXIndex]);
	dy = aComponent[CurrentYIndex];
	sx = aComponent[HScaleIndex];
	sy = aComponent[VScaleIndex];
	if (!((sx == 0)
		 && (sy == 0))) {
		dx = dx / sx;
		dy = dy / sy;
	}
	blockIndex = ((((usqInt) dy >> 3)) * (aComponent[BlockWidthIndex])) + (((usqInt) dx >> 3));
	sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7);
	sample = (aBlockArray[blockIndex])[sampleIndex];
	curX += 1;
	if (curX < ((aComponent[MCUWidthIndex]) * 8)) {
		aComponent[CurrentXIndex] = curX;
	}
	else {
		aComponent[CurrentXIndex] = 0;
		aComponent[CurrentYIndex] = ((aComponent[CurrentYIndex]) + 1);
	}
	return sample;
}

	/* JPEGReaderPlugin>>#nextSampleY */
static sqInt
nextSampleY(void)
{
    sqInt blockIndex;
    int curX;
    int dx;
    int dy;
    int sample;
    sqInt sampleIndex;
    int sx;
    int sy;

	dx = (curX = yComponent[CurrentXIndex]);
	dy = yComponent[CurrentYIndex];
	sx = yComponent[HScaleIndex];
	sy = yComponent[VScaleIndex];
	if (!((sx == 0)
		 && (sy == 0))) {
		dx = dx / sx;
		dy = dy / sy;
	}
	blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3));
	sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7);
	sample = (yBlocks[blockIndex])[sampleIndex];
	curX += 1;
	if (curX < ((yComponent[MCUWidthIndex]) * 8)) {
		yComponent[CurrentXIndex] = curX;
	}
	else {
		yComponent[CurrentXIndex] = 0;
		yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1);
	}
	return sample;
}


/*	Requires:
	JPEGColorComponent
	bits
	WordArray with: 3*Integer (residuals)
	ditherMask
	 */

	/* JPEGReaderPlugin>>#primitiveColorConvertGrayscaleMCU */
EXPORT(sqInt)
primitiveColorConvertGrayscaleMCU(void)
{
    sqInt arrayOop;
    sqInt blockIndex;
    int curX;
    int dx;
    int dy;
    sqInt i;
    int sample;
    sqInt sampleIndex;
    int sx;
    int sy;
    sqInt y;

	/* begin stInit */
	if (!((methodArgumentCount()) == 4)) {
		return primitiveFail();
	}
	ditherMask = stackIntegerValue(0);
	if (failed()) {
		return null;
	}
	arrayOop = stackValue(1);
	if (!((isWords(arrayOop))
		 && ((slotSizeOf(arrayOop)) == 3))) {
		return primitiveFail();
	}
	residuals = firstIndexableField(arrayOop);
	arrayOop = stackValue(2);
	if (!(isWords(arrayOop))) {
		return primitiveFail();
	}
	jpegBitsSize = slotSizeOf(arrayOop);
	jpegBits = firstIndexableField(arrayOop);
	arrayOop = stackValue(3);
	if (!((colorComponentfrom(yComponent, arrayOop))
		 && (colorComponentBlocksfrom(yBlocks, arrayOop)))) {
		return primitiveFail();
	}
	/* begin colorConvertGrayscaleMCU */
	yComponent[CurrentXIndex] = 0;
	yComponent[CurrentYIndex] = 0;
	for (i = 0; i < jpegBitsSize; i += 1) {
		/* begin nextSampleY */
		dx = (curX = yComponent[CurrentXIndex]);
		dy = yComponent[CurrentYIndex];
		sx = yComponent[HScaleIndex];
		sy = yComponent[VScaleIndex];
		if (!((sx == 0)
			 && (sy == 0))) {
			dx = dx / sx;
			dy = dy / sy;
		}
		blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3));
		sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7);
		sample = (yBlocks[blockIndex])[sampleIndex];
		curX += 1;
		if (curX < ((yComponent[MCUWidthIndex]) * 8)) {
			yComponent[CurrentXIndex] = curX;
		}
		else {
			yComponent[CurrentXIndex] = 0;
			yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1);
		}
		y = sample;
		y += residuals[GreenIndex];
		y = ((y < MaxSample) ? y : MaxSample);
		residuals[GreenIndex] = (y & ditherMask);
		y = y & (MaxSample - ditherMask);
		y = ((y < 1) ? 1 : y);
		jpegBits[i] = (((0xFF000000U + (((sqInt)((usqInt)(y) << 16)))) + (((sqInt)((usqInt)(y) << 8)))) + y);
	}
	pop(4);
	return 0;
}


/*	Requires:
	Array with: 3*JPEGColorComponent
	bits
	WordArray with: 3*Integer (residuals)
	ditherMask
	 */

	/* JPEGReaderPlugin>>#primitiveColorConvertMCU */
EXPORT(sqInt)
primitiveColorConvertMCU(void)
{
    sqInt arrayOop;
    sqInt blockIndex;
    sqInt blockIndex1;
    sqInt blockIndex2;
    sqInt blue;
    sqInt cb;
    sqInt cr;
    int curX;
    int curX1;
    int curX2;
    int dx;
    int dx1;
    int dx2;
    int dy;
    int dy1;
    int dy2;
    sqInt green;
    sqInt i;
    sqInt red;
    int sample;
    int sample1;
    int sample2;
    sqInt sampleIndex;
    sqInt sampleIndex1;
    sqInt sampleIndex2;
    int sx;
    int sx1;
    int sx2;
    int sy;
    int sy1;
    int sy2;
    sqInt y;

	/* begin stInit */
	if (!((methodArgumentCount()) == 4)) {
		return primitiveFail();
	}
	ditherMask = stackIntegerValue(0);
	if (failed()) {
		return null;
	}
	arrayOop = stackValue(1);
	if (!((isWords(arrayOop))
		 && ((slotSizeOf(arrayOop)) == 3))) {
		return primitiveFail();
	}
	residuals = firstIndexableField(arrayOop);
	arrayOop = stackValue(2);
	if (!(isWords(arrayOop))) {
		return primitiveFail();
	}
	jpegBitsSize = slotSizeOf(arrayOop);
	jpegBits = firstIndexableField(arrayOop);
	arrayOop = stackValue(3);
	if (!((isPointers(arrayOop))
		 && ((slotSizeOf(arrayOop)) == 3))) {
		return primitiveFail();
	}
	if (!(yColorComponentFrom(fetchPointerofObject(0, arrayOop)))) {
		return primitiveFail();
	}
	if (!(cbColorComponentFrom(fetchPointerofObject(1, arrayOop)))) {
		return primitiveFail();
	}
	if (!(crColorComponentFrom(fetchPointerofObject(2, arrayOop)))) {
		return primitiveFail();
	}
	/* begin colorConvertMCU */
	yComponent[CurrentXIndex] = 0;
	yComponent[CurrentYIndex] = 0;
	cbComponent[CurrentXIndex] = 0;
	cbComponent[CurrentYIndex] = 0;
	crComponent[CurrentXIndex] = 0;
	crComponent[CurrentYIndex] = 0;
	for (i = 0; i < jpegBitsSize; i += 1) {
		/* begin nextSampleY */
		dx = (curX = yComponent[CurrentXIndex]);
		dy = yComponent[CurrentYIndex];
		sx = yComponent[HScaleIndex];
		sy = yComponent[VScaleIndex];
		if (!((sx == 0)
			 && (sy == 0))) {
			dx = dx / sx;
			dy = dy / sy;
		}
		blockIndex = ((((usqInt) dy >> 3)) * (yComponent[BlockWidthIndex])) + (((usqInt) dx >> 3));
		sampleIndex = (((usqInt) (dy & 7) << 3)) + (dx & 7);
		sample = (yBlocks[blockIndex])[sampleIndex];
		curX += 1;
		if (curX < ((yComponent[MCUWidthIndex]) * 8)) {
			yComponent[CurrentXIndex] = curX;
		}
		else {
			yComponent[CurrentXIndex] = 0;
			yComponent[CurrentYIndex] = ((yComponent[CurrentYIndex]) + 1);
		}
		y = sample;
		/* begin nextSampleCb */
		dx1 = (curX1 = cbComponent[CurrentXIndex]);
		dy1 = cbComponent[CurrentYIndex];
		sx1 = cbComponent[HScaleIndex];
		sy1 = cbComponent[VScaleIndex];
		if (!((sx1 == 0)
			 && (sy1 == 0))) {
			dx1 = dx1 / sx1;
			dy1 = dy1 / sy1;
		}
		blockIndex1 = ((((usqInt) dy1 >> 3)) * (cbComponent[BlockWidthIndex])) + (((usqInt) dx1 >> 3));
		sampleIndex1 = (((usqInt) (dy1 & 7) << 3)) + (dx1 & 7);
		sample1 = (cbBlocks[blockIndex1])[sampleIndex1];
		curX1 += 1;
		if (curX1 < ((cbComponent[MCUWidthIndex]) * 8)) {
			cbComponent[CurrentXIndex] = curX1;
		}
		else {
			cbComponent[CurrentXIndex] = 0;
			cbComponent[CurrentYIndex] = ((cbComponent[CurrentYIndex]) + 1);
		}
		cb = sample1;
		cb -= SampleOffset;
		/* begin nextSampleCr */
		dx2 = (curX2 = crComponent[CurrentXIndex]);
		dy2 = crComponent[CurrentYIndex];
		sx2 = crComponent[HScaleIndex];
		sy2 = crComponent[VScaleIndex];
		if (!((sx2 == 0)
			 && (sy2 == 0))) {
			dx2 = dx2 / sx2;
			dy2 = dy2 / sy2;
		}
		blockIndex2 = ((((usqInt) dy2 >> 3)) * (crComponent[BlockWidthIndex])) + (((usqInt) dx2 >> 3));
		sampleIndex2 = (((usqInt) (dy2 & 7) << 3)) + (dx2 & 7);
		sample2 = (crBlocks[blockIndex2])[sampleIndex2];
		curX2 += 1;
		if (curX2 < ((crComponent[MCUWidthIndex]) * 8)) {
			crComponent[CurrentXIndex] = curX2;
		}
		else {
			crComponent[CurrentXIndex] = 0;
			crComponent[CurrentYIndex] = ((crComponent[CurrentYIndex]) + 1);
		}
		cr = sample2;
		cr -= SampleOffset;
		red = (y + ((FIXn1n40200 * cr) / 65536)) + (residuals[RedIndex]);
		red = ((red < MaxSample) ? red : MaxSample);
		red = ((red < 0) ? 0 : red);
		residuals[RedIndex] = (red & ditherMask);
		red = red & (MaxSample - ditherMask);
		red = ((red < 1) ? 1 : red);
		green = ((y - ((FIXn0n34414 * cb) / 65536)) - ((FIXn0n71414 * cr) / 65536)) + (residuals[GreenIndex]);
		green = ((green < MaxSample) ? green : MaxSample);
		green = ((green < 0) ? 0 : green);
		residuals[GreenIndex] = (green & ditherMask);
		green = green & (MaxSample - ditherMask);
		green = ((green < 1) ? 1 : green);
		blue = (y + ((FIXn1n77200 * cb) / 65536)) + (residuals[BlueIndex]);
		blue = ((blue < MaxSample) ? blue : MaxSample);
		blue = ((blue < 0) ? 0 : blue);
		residuals[BlueIndex] = (blue & ditherMask);
		blue = blue & (MaxSample - ditherMask);
		blue = ((blue < 1) ? 1 : blue);
		jpegBits[i] = (((0xFF000000U + (((usqInt) red << 16))) + (((usqInt) green << 8))) + blue);
	}
	pop(4);
	return 0;
}


/*	In:
	anArray WordArray of: DCTSize2
	aColorComponent JPEGColorComponent
	dcTable			WordArray
	acTable			WordArray
	stream			JPEGStream
	 */

	/* JPEGReaderPlugin>>#primitiveDecodeMCU */
EXPORT(sqInt)
primitiveDecodeMCU(void)
{
    int *anArray;
    sqInt arrayOop;
    sqInt bits;
    sqInt byte;
    unsigned char byte1;
    unsigned char byte2;
    sqInt i;
    sqInt index;
    sqInt oop;
    sqInt streamOop;
    sqInt value;
    sqInt value1;
    sqInt zeroCount;

	if (!((methodArgumentCount()) == 5)) {
		return primitiveFail();
	}
	oop = stackValue(0);
	if (!(loadJPEGStreamFrom(oop))) {
		return primitiveFail();
	}
	arrayOop = stackValue(1);
	if (!(isWords(arrayOop))) {
		return primitiveFail();
	}
	acTableSize = slotSizeOf(arrayOop);
	acTable = firstIndexableField(arrayOop);
	arrayOop = stackValue(2);
	if (!(isWords(arrayOop))) {
		return primitiveFail();
	}
	dcTableSize = slotSizeOf(arrayOop);
	dcTable = firstIndexableField(arrayOop);
	oop = stackValue(3);
	if (!(colorComponentfrom(yComponent, oop))) {
		return primitiveFail();
	}
	arrayOop = stackValue(4);
	if (!((isWords(arrayOop))
		 && ((slotSizeOf(arrayOop)) == DCTSize2))) {
		return primitiveFail();
	}
	anArray = firstIndexableField(arrayOop);
	if (failed()) {
		return null;
	}
	/* begin decodeBlockInto:component: */
	byte = jpegDecodeValueFromsize(dcTable, dcTableSize);
	if (byte < 0) {
		primitiveFail();
		goto l7;
	}
	if (byte != 0) {
		/* begin getBits: */
		if (byte > jsBitCount) {
			/* begin fillBuffer */
			while (jsBitCount <= 16) {
				if (!(jsPosition < jsReadLimit)) {
					goto l1;
				}
				byte1 = jsCollection[jsPosition];
				jsPosition += 1;
				if (byte1 == 0xFF) {

					/* peek for 00 */
					if (!((jsPosition < jsReadLimit)
						 && ((jsCollection[jsPosition]) == 0))) {
						jsPosition -= 1;
						goto l1;
					}
					jsPosition += 1;
				}
				jsBitBuffer = (((usqInt) jsBitBuffer << 8)) | byte1;
				jsBitCount += 8;
			}
	l1:	/* end fillBuffer */;
			if (byte > jsBitCount) {
				bits = -1;
				goto l2;
			}
		}
		jsBitCount -= byte;
		value = ((usqInt) jsBitBuffer) >> jsBitCount;
		jsBitBuffer = jsBitBuffer & ((1U << jsBitCount) - 1);
		bits = value;
	l2:	/* end getBits: */;
		/* begin scaleAndSignExtend:inFieldWidth: */
		if (bits < (1U << (byte - 1))) {
			byte = (bits - (1U << byte)) + 1;
			goto l3;
		}
		else {
			byte = bits;
			goto l3;
		}
	l3:	/* end scaleAndSignExtend:inFieldWidth: */;
	}
	byte = yComponent[PriorDCValueIndex] = ((yComponent[PriorDCValueIndex]) + byte);
	anArray[0] = byte;
	for (i = 1; i < DCTSize2; i += 1) {
		anArray[i] = 0;
	}
	index = 1;
	while (index < DCTSize2) {
		byte = jpegDecodeValueFromsize(acTable, acTableSize);
		if (byte < 0) {
			primitiveFail();
			goto l7;
		}
		zeroCount = ((usqInt) byte) >> 4;
		byte = byte & 15;
		if (byte != 0) {
			index += zeroCount;
			/* begin getBits: */
			if (byte > jsBitCount) {
				/* begin fillBuffer */
				while (jsBitCount <= 16) {
					if (!(jsPosition < jsReadLimit)) {
						goto l4;
					}
					byte2 = jsCollection[jsPosition];
					jsPosition += 1;
					if (byte2 == 0xFF) {

						/* peek for 00 */
						if (!((jsPosition < jsReadLimit)
							 && ((jsCollection[jsPosition]) == 0))) {
							jsPosition -= 1;
							goto l4;
						}
						jsPosition += 1;
					}
					jsBitBuffer = (((usqInt) jsBitBuffer << 8)) | byte2;
					jsBitCount += 8;
				}
	l4:	/* end fillBuffer */;
				if (byte > jsBitCount) {
					bits = -1;
					goto l5;
				}
			}
			jsBitCount -= byte;
			value1 = ((usqInt) jsBitBuffer) >> jsBitCount;
			jsBitBuffer = jsBitBuffer & ((1U << jsBitCount) - 1);
			bits = value1;
	l5:	/* end getBits: */;
			/* begin scaleAndSignExtend:inFieldWidth: */
			if (bits < (1U << (byte - 1))) {
				byte = (bits - (1U << byte)) + 1;
				goto l6;
			}
			else {
				byte = bits;
				goto l6;
			}
	l6:	/* end scaleAndSignExtend:inFieldWidth: */;
			if ((index < 0)
			 || (index >= DCTSize2)) {
				primitiveFail();
				goto l7;
			}
			anArray[jpegNaturalOrder[index]] = byte;
		}
		else {
			if (zeroCount == 15) {
				index += zeroCount;
			}
			else {
				goto l7;
			}
		}
		index += 1;
	}
	l7:	/* end decodeBlockInto:component: */;
	if (failed()) {
		return null;
	}
	/* begin storeJPEGStreamOn: */
	streamOop = stackValue(0);
	storeIntegerofObjectwithValue(1, streamOop, jsPosition);
	storeIntegerofObjectwithValue(3, streamOop, jsBitBuffer);
	storeIntegerofObjectwithValue(4, streamOop, jsBitCount);
	storeIntegerofObjectwithValue(PriorDCValueIndex, stackValue(3), yComponent[PriorDCValueIndex]);
	pop(5);
	return 0;
}


/*	In:
	anArray: IntegerArray new: DCTSize2
	qt: IntegerArray new: DCTSize2.
	 */

	/* JPEGReaderPlugin>>#primitiveIdctInt */
EXPORT(sqInt)
primitiveIdctInt(void)
{
    sqInt anACTerm;
    int *anArray;
    sqInt arrayOop;
    int dcval;
    sqInt i;
    sqInt j;
    int *qt;
    sqInt row;
    sqInt t0;
    sqInt t1;
    sqInt t10;
    sqInt t11;
    sqInt t12;
    sqInt t13;
    int t2;
    int t3;
    sqInt v;
    int ws[64];
    int z1;
    int z2;
    int z3;
    sqInt z4;
    sqInt z5;

	if (!((methodArgumentCount()) == 2)) {
		return primitiveFail();
	}
	arrayOop = stackValue(0);
	if (!((isWords(arrayOop))
		 && ((slotSizeOf(arrayOop)) == DCTSize2))) {
		return primitiveFail();
	}
	qt = firstIndexableField(arrayOop);
	arrayOop = stackValue(1);
	if (!((isWords(arrayOop))
		 && ((slotSizeOf(arrayOop)) == DCTSize2))) {
		return primitiveFail();
	}
	anArray = firstIndexableField(arrayOop);
	/* begin idctBlockInt:qt: */
	for (i = 0; i < DCTSize; i += 1) {
		anACTerm = -1;
		for (row = 1; row < DCTSize; row += 1) {
			if (anACTerm == -1) {
				if (!((anArray[(row * DCTSize) + i]) == 0)) {
					anACTerm = row;
				}
			}
		}
		if (anACTerm == -1) {
			dcval = ((sqInt)((usqInt)(((anArray[i]) * (qt[0]))) << Pass1Bits));
			for (j = 0; j < DCTSize; j += 1) {
				ws[(j * DCTSize) + i] = dcval;
			}
		}
		else {
			z2 = (anArray[(DCTSize * 2) + i]) * (qt[(DCTSize * 2) + i]);
			z3 = (anArray[(DCTSize * 6) + i]) * (qt[(DCTSize * 6) + i]);
			z1 = (z2 + z3) * FIXn0n541196100;
			t2 = z1 + (z3 * (0 - FIXn1n847759065));
			t3 = z1 + (z2 * FIXn0n765366865);
			z2 = (anArray[i]) * (qt[i]);
			z3 = (anArray[(DCTSize * 4) + i]) * (qt[(DCTSize * 4) + i]);
			t0 = ((sqInt)((usqInt)((z2 + z3)) << ConstBits));
			t1 = ((sqInt)((usqInt)((z2 - z3)) << ConstBits));
			t10 = t0 + t3;
			t13 = t0 - t3;
			t11 = t1 + t2;
			t12 = t1 - t2;
			t0 = (anArray[(DCTSize * 7) + i]) * (qt[(DCTSize * 7) + i]);
			t1 = (anArray[(DCTSize * 5) + i]) * (qt[(DCTSize * 5) + i]);
			t2 = (anArray[(DCTSize * 3) + i]) * (qt[(DCTSize * 3) + i]);
			t3 = (anArray[DCTSize + i]) * (qt[DCTSize + i]);
			z1 = t0 + t3;
			z2 = t1 + t2;
			z3 = t0 + t2;
			z4 = t1 + t3;
			z5 = (z3 + z4) * FIXn1n175875602;
			t0 = t0 * FIXn0n298631336;
			t1 = t1 * FIXn2n053119869;
			t2 = t2 * FIXn3n072711026;
			t3 = t3 * FIXn1n501321110;
			z1 = z1 * (0 - FIXn0n899976223);
			z2 = z2 * (0 - FIXn2n562915447);
			z3 = z3 * (0 - FIXn1n961570560);
			z4 = z4 * (0 - FIXn0n390180644);
			z3 += z5;
			z4 += z5;
			t0 = (t0 + z1) + z3;
			t1 = (t1 + z2) + z4;
			t2 = (t2 + z2) + z3;
			t3 = (t3 + z1) + z4;
			ws[i] = ((t10 + t3) / Pass1Div);
			ws[(DCTSize * 7) + i] = ((t10 - t3) / Pass1Div);
			ws[(DCTSize) + i] = ((t11 + t2) / Pass1Div);
			ws[(DCTSize * 6) + i] = ((t11 - t2) / Pass1Div);
			ws[(DCTSize * 2) + i] = ((t12 + t1) / Pass1Div);
			ws[(DCTSize * 5) + i] = ((t12 - t1) / Pass1Div);
			ws[(DCTSize * 3) + i] = ((t13 + t0) / Pass1Div);
			ws[(DCTSize * 4) + i] = ((t13 - t0) / Pass1Div);
		}
	}
	for (i = 0; i <= (DCTSize2 - DCTSize); i += DCTSize) {
		z2 = ws[i + 2];
		z3 = ws[i + 6];
		z1 = (z2 + z3) * FIXn0n541196100;
		t2 = z1 + (z3 * (0 - FIXn1n847759065));
		t3 = z1 + (z2 * FIXn0n765366865);
		t0 = ((sqInt)((usqInt)(((ws[i]) + (ws[i + 4]))) << ConstBits));
		t1 = ((sqInt)((usqInt)(((ws[i]) - (ws[i + 4]))) << ConstBits));
		t10 = t0 + t3;
		t13 = t0 - t3;
		t11 = t1 + t2;
		t12 = t1 - t2;
		t0 = ws[i + 7];
		t1 = ws[i + 5];
		t2 = ws[i + 3];
		t3 = ws[i + 1];
		z1 = t0 + t3;
		z2 = t1 + t2;
		z3 = t0 + t2;
		z4 = t1 + t3;
		z5 = (z3 + z4) * FIXn1n175875602;
		t0 = t0 * FIXn0n298631336;
		t1 = t1 * FIXn2n053119869;
		t2 = t2 * FIXn3n072711026;
		t3 = t3 * FIXn1n501321110;
		z1 = z1 * (0 - FIXn0n899976223);
		z2 = z2 * (0 - FIXn2n562915447);
		z3 = z3 * (0 - FIXn1n961570560);
		z4 = z4 * (0 - FIXn0n390180644);
		z3 += z5;
		z4 += z5;
		t0 = (t0 + z1) + z3;
		t1 = (t1 + z2) + z4;
		t2 = (t2 + z2) + z3;
		t3 = (t3 + z1) + z4;
		v = ((t10 + t3) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i] = v;
		v = ((t10 - t3) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 7] = v;
		v = ((t11 + t2) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 1] = v;
		v = ((t11 - t2) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 6] = v;
		v = ((t12 + t1) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 2] = v;
		v = ((t12 - t1) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 5] = v;
		v = ((t13 + t0) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 3] = v;
		v = ((t13 - t0) / Pass2Div) + SampleOffset;
		v = ((v < MaxSample) ? v : MaxSample);
		v = ((v < 0) ? 0 : v);
		anArray[i + 4] = v;
	}
	pop(2);
	return 0;
}

	/* JPEGReaderPlugin>>#scaleAndSignExtend:inFieldWidth: */
static sqInt
scaleAndSignExtendinFieldWidth(sqInt aNumber, sqInt w)
{
	if (aNumber < (1U << (w - 1))) {
		return (aNumber - (1U << w)) + 1;
	}
	else {
		return aNumber;
	}
}


/*	Note: This is coded so that it can be run in Squeak. */

	/* InterpreterPlugin>>#setInterpreter: */
EXPORT(sqInt)
setInterpreter(struct VirtualMachine *anInterpreter)
{
    sqInt ok;

	interpreterProxy = anInterpreter;
	ok = ((interpreterProxy->majorVersion()) == (VM_PROXY_MAJOR))
	 && ((interpreterProxy->minorVersion()) >= (VM_PROXY_MINOR));
	if (ok) {
		
#if !defined(SQUEAK_BUILTIN_PLUGIN)
		byteSizeOf = interpreterProxy->byteSizeOf;
		failed = interpreterProxy->failed;
		fetchIntegerofObject = interpreterProxy->fetchIntegerofObject;
		fetchPointerofObject = interpreterProxy->fetchPointerofObject;
		firstIndexableField = interpreterProxy->firstIndexableField;
		isBytes = interpreterProxy->isBytes;
		isPointers = interpreterProxy->isPointers;
		isWords = interpreterProxy->isWords;
		methodArgumentCount = interpreterProxy->methodArgumentCount;
		pop = interpreterProxy->pop;
		primitiveFail = interpreterProxy->primitiveFail;
		slotSizeOf = interpreterProxy->slotSizeOf;
		stackIntegerValue = interpreterProxy->stackIntegerValue;
		stackValue = interpreterProxy->stackValue;
		storeIntegerofObjectwithValue = interpreterProxy->storeIntegerofObjectwithValue;
#endif /* !defined(SQUEAK_BUILTIN_PLUGIN) */
	}
	return ok;
}

	/* JPEGReaderPlugin>>#stInit */
static sqInt
stInit(void)
{
	return 0;
}

	/* JPEGReaderPlugin>>#storeJPEGStreamOn: */
static sqInt
storeJPEGStreamOn(sqInt streamOop)
{
	storeIntegerofObjectwithValue(1, streamOop, jsPosition);
	storeIntegerofObjectwithValue(3, streamOop, jsBitBuffer);
	storeIntegerofObjectwithValue(4, streamOop, jsBitCount);
	return 0;
}

	/* JPEGReaderPlugin>>#yColorComponentFrom: */
static sqInt
yColorComponentFrom(sqInt oop)
{
	return (colorComponentfrom(yComponent, oop))
	 && (colorComponentBlocksfrom(yBlocks, oop));
}


#ifdef SQUEAK_BUILTIN_PLUGIN

static char _m[] = "JPEGReaderPlugin";
void* JPEGReaderPlugin_exports[][3] = {
	{(void*)_m, "getModuleName", (void*)getModuleName},
	{(void*)_m, "primitiveColorConvertGrayscaleMCU\000\002", (void*)primitiveColorConvertGrayscaleMCU},
	{(void*)_m, "primitiveColorConvertMCU\000\003", (void*)primitiveColorConvertMCU},
	{(void*)_m, "primitiveDecodeMCU\000\002", (void*)primitiveDecodeMCU},
	{(void*)_m, "primitiveIdctInt\000\001", (void*)primitiveIdctInt},
	{(void*)_m, "setInterpreter", (void*)setInterpreter},
	{NULL, NULL, NULL}
};

#else /* ifdef SQ_BUILTIN_PLUGIN */

signed char primitiveColorConvertGrayscaleMCUAccessorDepth = 2;
signed char primitiveColorConvertMCUAccessorDepth = 3;
signed char primitiveDecodeMCUAccessorDepth = 2;
signed char primitiveIdctIntAccessorDepth = 1;

#endif /* ifdef SQ_BUILTIN_PLUGIN */
