/* Automatically generated from Squeak on #(21 October 2001 9:19:44 pm) */

#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. */
/*  The virtual machine proxy definition */
#include "sqVirtualMachine.h"
/* Configuration options */
#include "sqConfig.h"
/* Platform specific definitions */
#include "sqPlatformSpecific.h"

#define true 1
#define false 0
#define null 0  /* using 'null' because nil is predefined in Think C */

/* memory access macros */
#define byteAt(i) (*((unsigned char *) (i)))
#define byteAtput(i, val) (*((unsigned char *) (i)) = val)
#define longAt(i) (*((int *) (i)))
#define longAtput(i, val) (*((int *) (i)) = val)

/*** Variables ***/
static int *acTable;
static int acTableSize;
static int *cbBlocks[128];
static int cbComponent[11];
static int cbSampleStream;
static int *crBlocks[128];
static int crComponent[11];
static int crSampleStream;
static int *dcTable;
static int dcTableSize;
static int ditherMask;
static struct VirtualMachine* interpreterProxy;
static int *jpegBits;
static int 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 int jsBitBuffer;
static int jsBitCount;
static unsigned char *jsCollection;
static int jsPosition;
static int jsReadLimit;
static const char *moduleName = "JPEGReaderPlugin 21 October 2001 (i)";
static int *residuals;
static int *yBlocks[128];
static int yComponent[11];
static int ySampleStream;

/*** Function Prototypes ***/
static int cbColorComponentFrom(int oop);
static int colorComponentfrom(int * aColorComponent, int oop);
static int colorComponentBlocksfrom(int ** blocks, int oop);
static int colorConvertGrayscaleMCU(void);
static int colorConvertMCU(void);
static int crColorComponentFrom(int oop);
static int decodeBlockIntocomponent(int * anArray, int * aColorComponent);
static int fillBuffer(void);
static int getBits(int requestedBits);
#pragma export on
EXPORT(const char*) JPEGReaderPlugin_getModuleName(void);
#pragma export off
static int idctBlockIntqt(int * anArray, int * qt);
static int jpegDecodeValueFromsize(int *table, int tableSize);
static int loadJPEGStreamFrom(int streamOop);
static int nextSampleCb(void);
static int nextSampleCr(void);
static int nextSampleFromblocks(int * aComponent, int ** aBlockArray);
static int nextSampleY(void);
#pragma export on
EXPORT(int) JPEGReaderPlugin_primitiveColorConvertGrayscaleMCU(void);
EXPORT(int) JPEGReaderPlugin_primitiveColorConvertMCU(void);
EXPORT(int) JPEGReaderPlugin_primitiveDecodeMCU(void);
EXPORT(int) JPEGReaderPlugin_primitiveIdctInt(void);
#pragma export off
static int scaleAndSignExtendinFieldWidth(int aNumber, int w);
#pragma export on
EXPORT(int) JPEGReaderPlugin_setInterpreter(struct VirtualMachine* anInterpreter);
#pragma export off
static int stInit(void);
static int storeJPEGStreamOn(int streamOop);
static int yColorComponentFrom(int oop);

static int cbColorComponentFrom(int oop) {
	return (colorComponentfrom(cbComponent, oop)) && (colorComponentBlocksfrom(cbBlocks, oop));
}

static int colorComponentfrom(int * aColorComponent, int oop) {
	if ((oop & 1)) {
		return 0;
	}
	if (!(interpreterProxy->isPointers(oop))) {
		return 0;
	}
	if ((interpreterProxy->slotSizeOf(oop)) < 11) {
		return 0;
	}
	aColorComponent[0] = (interpreterProxy->fetchIntegerofObject(0, oop));
	aColorComponent[1] = (interpreterProxy->fetchIntegerofObject(1, oop));
	aColorComponent[2] = (interpreterProxy->fetchIntegerofObject(2, oop));
	aColorComponent[3] = (interpreterProxy->fetchIntegerofObject(3, oop));
	aColorComponent[5] = (interpreterProxy->fetchIntegerofObject(5, oop));
	aColorComponent[8] = (interpreterProxy->fetchIntegerofObject(8, oop));
	aColorComponent[10] = (interpreterProxy->fetchIntegerofObject(10, oop));
	return !(interpreterProxy->failed());
}

static int colorComponentBlocksfrom(int ** blocks, int oop) {
    int max;
    int i;
    int blockOop;
    int arrayOop;

	if ((oop & 1)) {
		return 0;
	}
	if (!(interpreterProxy->isPointers(oop))) {
		return 0;
	}
	if ((interpreterProxy->slotSizeOf(oop)) < 11) {
		return 0;
	}
	arrayOop = interpreterProxy->fetchPointerofObject(4, oop);
	if ((arrayOop & 1)) {
		return 0;
	}
	if (!(interpreterProxy->isPointers(arrayOop))) {
		return 0;
	}
	max = interpreterProxy->slotSizeOf(arrayOop);
	if (max > 128) {
		return 0;
	}
	for (i = 0; i <= (max - 1); i += 1) {
		blockOop = interpreterProxy->fetchPointerofObject(i, arrayOop);
		if ((blockOop & 1)) {
			return 0;
		}
		if (!(interpreterProxy->isWords(blockOop))) {
			return 0;
		}
		if (!((interpreterProxy->slotSizeOf(blockOop)) == 64)) {
			return 0;
		}
		blocks[i] = (interpreterProxy->firstIndexableField(blockOop));
	}
	return !(interpreterProxy->failed());
}

static int colorConvertGrayscaleMCU(void) {
    int y;
    int i;
    int sampleIndex;
    int blockIndex;
    int dx;
    int sx;
    int sy;
    int dy;
    int curX;
    int sample;

	yComponent[0] = 0;
	yComponent[1] = 0;
	for (i = 0; i <= (jpegBitsSize - 1); i += 1) {
		/* begin nextSampleY */
		dx = curX = yComponent[0];
		dy = yComponent[1];
		sx = yComponent[2];
		sy = yComponent[3];
		if (!((sx == 0) && (sy == 0))) {
			dx = dx / sx;
			dy = dy / sy;
		}
		blockIndex = ((((unsigned) dy >> 3)) * (yComponent[5])) + (((unsigned) dx >> 3));
		sampleIndex = (((unsigned) (dy & 7) << 3)) + (dx & 7);
		sample = (yBlocks[blockIndex])[sampleIndex];
		curX += 1;
		if (curX < ((yComponent[8]) * 8)) {
			yComponent[0] = curX;
		} else {
			yComponent[0] = 0;
			yComponent[1] = ((yComponent[1]) + 1);
		}
		y = sample;
		y += residuals[1];
		y = ((y < 255) ? y : 255);
		residuals[1] = (y & ditherMask);
		y = y & (255 - ditherMask);
		y = ((y < 1) ? 1 : y);
		jpegBits[i] = (((4278190080U + (y << 16)) + (y << 8)) + y);
	}
}

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

	yComponent[0] = 0;
	yComponent[1] = 0;
	cbComponent[0] = 0;
	cbComponent[1] = 0;
	crComponent[0] = 0;
	crComponent[1] = 0;
	for (i = 0; i <= (jpegBitsSize - 1); i += 1) {
		/* begin nextSampleY */
		dx = curX = yComponent[0];
		dy = yComponent[1];
		sx = yComponent[2];
		sy = yComponent[3];
		if (!((sx == 0) && (sy == 0))) {
			dx = dx / sx;
			dy = dy / sy;
		}
		blockIndex = ((((unsigned) dy >> 3)) * (yComponent[5])) + (((unsigned) dx >> 3));
		sampleIndex = (((unsigned) (dy & 7) << 3)) + (dx & 7);
		sample = (yBlocks[blockIndex])[sampleIndex];
		curX += 1;
		if (curX < ((yComponent[8]) * 8)) {
			yComponent[0] = curX;
		} else {
			yComponent[0] = 0;
			yComponent[1] = ((yComponent[1]) + 1);
		}
		y = sample;
		/* begin nextSampleCb */
		dx1 = curX1 = cbComponent[0];
		dy1 = cbComponent[1];
		sx1 = cbComponent[2];
		sy1 = cbComponent[3];
		if (!((sx1 == 0) && (sy1 == 0))) {
			dx1 = dx1 / sx1;
			dy1 = dy1 / sy1;
		}
		blockIndex1 = ((((unsigned) dy1 >> 3)) * (cbComponent[5])) + (((unsigned) dx1 >> 3));
		sampleIndex1 = (((unsigned) (dy1 & 7) << 3)) + (dx1 & 7);
		sample1 = (cbBlocks[blockIndex1])[sampleIndex1];
		curX1 += 1;
		if (curX1 < ((cbComponent[8]) * 8)) {
			cbComponent[0] = curX1;
		} else {
			cbComponent[0] = 0;
			cbComponent[1] = ((cbComponent[1]) + 1);
		}
		cb = sample1;
		cb -= 127;
		/* begin nextSampleCr */
		dx2 = curX2 = crComponent[0];
		dy2 = crComponent[1];
		sx2 = crComponent[2];
		sy2 = crComponent[3];
		if (!((sx2 == 0) && (sy2 == 0))) {
			dx2 = dx2 / sx2;
			dy2 = dy2 / sy2;
		}
		blockIndex2 = ((((unsigned) dy2 >> 3)) * (crComponent[5])) + (((unsigned) dx2 >> 3));
		sampleIndex2 = (((unsigned) (dy2 & 7) << 3)) + (dx2 & 7);
		sample2 = (crBlocks[blockIndex2])[sampleIndex2];
		curX2 += 1;
		if (curX2 < ((crComponent[8]) * 8)) {
			crComponent[0] = curX2;
		} else {
			crComponent[0] = 0;
			crComponent[1] = ((crComponent[1]) + 1);
		}
		cr = sample2;
		cr -= 127;
		red = (y + (((int) (91881 * cr) >> 16))) + (residuals[0]);
		red = ((red < 255) ? red : 255);
		red = ((red < 0) ? 0 : red);
		residuals[0] = (red & ditherMask);
		red = red & (255 - ditherMask);
		red = ((red < 1) ? 1 : red);
		green = ((y - (((int) (22554 * cb) >> 16))) - (((int) (46802 * cr) >> 16))) + (residuals[1]);
		green = ((green < 255) ? green : 255);
		green = ((green < 0) ? 0 : green);
		residuals[1] = (green & ditherMask);
		green = green & (255 - ditherMask);
		green = ((green < 1) ? 1 : green);
		blue = (y + (((int) (116130 * cb) >> 16))) + (residuals[2]);
		blue = ((blue < 255) ? blue : 255);
		blue = ((blue < 0) ? 0 : blue);
		residuals[2] = (blue & ditherMask);
		blue = blue & (255 - ditherMask);
		blue = ((blue < 1) ? 1 : blue);
		jpegBits[i] = (((4278190080U + (((unsigned) red << 16))) + (((unsigned) green << 8))) + blue);
	}
}

static int crColorComponentFrom(int oop) {
	return (colorComponentfrom(crComponent, oop)) && (colorComponentBlocksfrom(crBlocks, oop));
}

static int decodeBlockIntocomponent(int * anArray, int * aColorComponent) {
    int bits;
    int byte;
    int i;
    int index;
    int zeroCount;

	byte = jpegDecodeValueFromsize(dcTable, dcTableSize);
	if (byte < 0) {
		return interpreterProxy->primitiveFail();
	}
	if (byte != 0) {
		bits = getBits(byte);
		/* begin scaleAndSignExtend:inFieldWidth: */
		if (bits < ((((byte - 1) < 0) ? ((unsigned) 1 >> -(byte - 1)) : ((unsigned) 1 << (byte - 1))))) {
			byte = (bits - (((byte < 0) ? ((unsigned) 1 >> -byte) : ((unsigned) 1 << byte)))) + 1;
			goto l1;
		} else {
			byte = bits;
			goto l1;
		}
	l1:	/* end scaleAndSignExtend:inFieldWidth: */;
	}
	byte = aColorComponent[10] = ((aColorComponent[10]) + byte);
	anArray[0] = byte;
	for (i = 1; i <= (64 - 1); i += 1) {
		anArray[i] = 0;
	}
	index = 1;
	while (index < 64) {
		byte = jpegDecodeValueFromsize(acTable, acTableSize);
		if (byte < 0) {
			return interpreterProxy->primitiveFail();
		}
		zeroCount = ((unsigned) byte) >> 4;
		byte = byte & 15;
		if (byte != 0) {
			index += zeroCount;
			bits = getBits(byte);
			/* begin scaleAndSignExtend:inFieldWidth: */
			if (bits < ((((byte - 1) < 0) ? ((unsigned) 1 >> -(byte - 1)) : ((unsigned) 1 << (byte - 1))))) {
				byte = (bits - (((byte < 0) ? ((unsigned) 1 >> -byte) : ((unsigned) 1 << byte)))) + 1;
				goto l2;
			} else {
				byte = bits;
				goto l2;
			}
		l2:	/* end scaleAndSignExtend:inFieldWidth: */;
			if ((index < 0) || (index >= 64)) {
				return interpreterProxy->primitiveFail();
			}
			anArray[jpegNaturalOrder[index]] = byte;
		} else {
			if (zeroCount == 15) {
				index += zeroCount;
			} else {
				return null;
			}
		}
		index += 1;
	}
}

static int fillBuffer(void) {
    int byte;

	while (jsBitCount <= 16) {
		if (!(jsPosition < jsReadLimit)) {
			return jsBitCount;
		}
		byte = jsCollection[jsPosition];
		jsPosition += 1;
		if (byte == 255) {
			if (!((jsPosition < jsReadLimit) && ((jsCollection[jsPosition]) == 0))) {
				jsPosition -= 1;
				return jsBitCount;
			}
			jsPosition += 1;
		}
		jsBitBuffer = (((unsigned) jsBitBuffer << 8)) | byte;
		jsBitCount += 8;
	}
	return jsBitCount;
}

static int getBits(int requestedBits) {
    int value;
    int byte;

	if (requestedBits > jsBitCount) {
		/* begin fillBuffer */
		while (jsBitCount <= 16) {
			if (!(jsPosition < jsReadLimit)) {
				goto l1;
			}
			byte = jsCollection[jsPosition];
			jsPosition += 1;
			if (byte == 255) {
				if (!((jsPosition < jsReadLimit) && ((jsCollection[jsPosition]) == 0))) {
					jsPosition -= 1;
					goto l1;
				}
				jsPosition += 1;
			}
			jsBitBuffer = (((unsigned) jsBitBuffer << 8)) | byte;
			jsBitCount += 8;
		}
	l1:	/* end fillBuffer */;
		if (requestedBits > jsBitCount) {
			return -1;
		}
	}
	value = (((requestedBits - jsBitCount) < 0) ? ((unsigned) jsBitBuffer >> -(requestedBits - jsBitCount)) : ((unsigned) jsBitBuffer << (requestedBits - jsBitCount)));
	jsBitBuffer = jsBitBuffer & (((((jsBitCount - requestedBits) < 0) ? ((unsigned) 1 >> -(jsBitCount - requestedBits)) : ((unsigned) 1 << (jsBitCount - requestedBits)))) - 1);
	jsBitCount -= requestedBits;
	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! */

EXPORT(const char*) JPEGReaderPlugin_getModuleName(void) {
	return moduleName;
}

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

	;
	for (i = 0; i <= (8 - 1); i += 1) {
		anACTerm = -1;
		for (row = 1; row <= (8 - 1); row += 1) {
			if (anACTerm == -1) {
				if (!((anArray[(row * 8) + i]) == 0)) {
					anACTerm = row;
				}
			}
		}
		if (anACTerm == -1) {
			dcval = ((unsigned) ((anArray[i]) * (qt[0])) << 2);
			for (j = 0; j <= (8 - 1); j += 1) {
				ws[(j * 8) + i] = dcval;
			}
		} else {
			z2 = (anArray[(8 * 2) + i]) * (qt[(8 * 2) + i]);
			z3 = (anArray[(8 * 6) + i]) * (qt[(8 * 6) + i]);
			z1 = (z2 + z3) * 4433;
			t2 = z1 + (z3 * (0 - 15137));
			t3 = z1 + (z2 * 6270);
			z2 = (anArray[i]) * (qt[i]);
			z3 = (anArray[(8 * 4) + i]) * (qt[(8 * 4) + i]);
			t0 = ((unsigned) (z2 + z3) << 13);
			t1 = ((unsigned) (z2 - z3) << 13);
			t10 = t0 + t3;
			t13 = t0 - t3;
			t11 = t1 + t2;
			t12 = t1 - t2;
			t0 = (anArray[(8 * 7) + i]) * (qt[(8 * 7) + i]);
			t1 = (anArray[(8 * 5) + i]) * (qt[(8 * 5) + i]);
			t2 = (anArray[(8 * 3) + i]) * (qt[(8 * 3) + i]);
			t3 = (anArray[8 + i]) * (qt[8 + i]);
			z1 = t0 + t3;
			z2 = t1 + t2;
			z3 = t0 + t2;
			z4 = t1 + t3;
			z5 = (z3 + z4) * 9633;
			t0 = t0 * 2446;
			t1 = t1 * 16819;
			t2 = t2 * 25172;
			t3 = t3 * 12299;
			z1 = z1 * (0 - 7373);
			z2 = z2 * (0 - 20995);
			z3 = z3 * (0 - 16069);
			z4 = z4 * (0 - 3196);
			z3 += z5;
			z4 += z5;
			t0 = (t0 + z1) + z3;
			t1 = (t1 + z2) + z4;
			t2 = (t2 + z2) + z3;
			t3 = (t3 + z1) + z4;
			ws[i] = (((int) (t10 + t3) >> 11));
			ws[(8 * 7) + i] = (((int) (t10 - t3) >> 11));
			ws[(8 * 1) + i] = (((int) (t11 + t2) >> 11));
			ws[(8 * 6) + i] = (((int) (t11 - t2) >> 11));
			ws[(8 * 2) + i] = (((int) (t12 + t1) >> 11));
			ws[(8 * 5) + i] = (((int) (t12 - t1) >> 11));
			ws[(8 * 3) + i] = (((int) (t13 + t0) >> 11));
			ws[(8 * 4) + i] = (((int) (t13 - t0) >> 11));
		}
	}
	for (i = 0; i <= (64 - 8); i += 8) {
		z2 = ws[i + 2];
		z3 = ws[i + 6];
		z1 = (z2 + z3) * 4433;
		t2 = z1 + (z3 * (0 - 15137));
		t3 = z1 + (z2 * 6270);
		t0 = ((unsigned) ((ws[i]) + (ws[i + 4])) << 13);
		t1 = ((unsigned) ((ws[i]) - (ws[i + 4])) << 13);
		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) * 9633;
		t0 = t0 * 2446;
		t1 = t1 * 16819;
		t2 = t2 * 25172;
		t3 = t3 * 12299;
		z1 = z1 * (0 - 7373);
		z2 = z2 * (0 - 20995);
		z3 = z3 * (0 - 16069);
		z4 = z4 * (0 - 3196);
		z3 += z5;
		z4 += z5;
		t0 = (t0 + z1) + z3;
		t1 = (t1 + z2) + z4;
		t2 = (t2 + z2) + z3;
		t3 = (t3 + z1) + z4;
		v = (((int) (t10 + t3) >> 18)) + 127;
		v = ((v < 255) ? v : 255);
		v = ((v < 0) ? 0 : v);
		anArray[i] = v;
		v = (((int) (t10 - t3) >> 18)) + 127;
		v = ((v < 255) ? v : 255);
		v = ((v < 0) ? 0 : v);
		anArray[i + 7] = v;
		v = (((int) (t11 + t2) >> 18)) + 127;
		v = ((v < 255) ? v : 255);
		v = ((v < 0) ? 0 : v);
		anArray[i + 1] = v;
		v = (((int) (t11 - t2) >> 18)) + 127;
		v = ((v < 255) ? v : 255);
		v = ((v < 0) ? 0 : v);
		anArray[i + 6] = v;
		v = (((int) (t12 + t1) >> 18)) + 127;
		v = ((v < 255) ? v : 255);
		v = ((v < 0) ? 0 : v);
		anArray[i + 2] = v;
		v = (((int) (t12 - t1) >> 18)) + 127;
		v = ((v < 255) ? v : 255);
		v = ((v < 0) ? 0 : v);
		anArray[i + 5] = v;
		v = (((int) (t13 + t0) >> 18)) + 127;
		v = ((v < 255) ? v : 255);
		v = ((v < 0) ? 0 : v);
		anArray[i + 3] = v;
		v = (((int) (t13 - t0) >> 18)) + 127;
		v = ((v < 255) ? v : 255);
		v = ((v < 0) ? 0 : v);
		anArray[i + 4] = v;
	}
}


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

static int jpegDecodeValueFromsize(int *table, int tableSize) {
    int bits;
    int bitsNeeded;
    int tableIndex;
    int index;
    int value;


	/* Initial bits needed */

	bitsNeeded = ((unsigned) (table[0])) >> 24;
	if (bitsNeeded > 16) {
		return -1;
	}

	/* First real table */

	tableIndex = 2;
	while (1) {

		/* Get bits */

		bits = getBits(bitsNeeded);
		if (bits < 0) {
			return -1;
		}
		index = (tableIndex + bits) - 1;
		if (index >= tableSize) {
			return -1;
		}

		/* Lookup entry in table */

		value = table[index];
		if ((value & 1056964608) == 0) {
			return value;
		}

		/* Table offset in low 16 bit */

		tableIndex = value & 65535;

		/* Additional bits in high 8 bit */

		bitsNeeded = (((unsigned) value) >> 24) & 255;
		if (bitsNeeded > 16) {
			return -1;
		}
	}
	return -1;
}

static int loadJPEGStreamFrom(int streamOop) {
    int oop;
    int sz;

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

static int nextSampleCb(void) {
    int sampleIndex;
    int blockIndex;
    int dx;
    int sx;
    int sy;
    int dy;
    int curX;
    int sample;

	dx = curX = cbComponent[0];
	dy = cbComponent[1];
	sx = cbComponent[2];
	sy = cbComponent[3];
	if (!((sx == 0) && (sy == 0))) {
		dx = dx / sx;
		dy = dy / sy;
	}
	blockIndex = ((((unsigned) dy >> 3)) * (cbComponent[5])) + (((unsigned) dx >> 3));
	sampleIndex = (((unsigned) (dy & 7) << 3)) + (dx & 7);
	sample = (cbBlocks[blockIndex])[sampleIndex];
	curX += 1;
	if (curX < ((cbComponent[8]) * 8)) {
		cbComponent[0] = curX;
	} else {
		cbComponent[0] = 0;
		cbComponent[1] = ((cbComponent[1]) + 1);
	}
	return sample;
}

static int nextSampleCr(void) {
    int sampleIndex;
    int blockIndex;
    int dx;
    int sx;
    int sy;
    int dy;
    int curX;
    int sample;

	dx = curX = crComponent[0];
	dy = crComponent[1];
	sx = crComponent[2];
	sy = crComponent[3];
	if (!((sx == 0) && (sy == 0))) {
		dx = dx / sx;
		dy = dy / sy;
	}
	blockIndex = ((((unsigned) dy >> 3)) * (crComponent[5])) + (((unsigned) dx >> 3));
	sampleIndex = (((unsigned) (dy & 7) << 3)) + (dx & 7);
	sample = (crBlocks[blockIndex])[sampleIndex];
	curX += 1;
	if (curX < ((crComponent[8]) * 8)) {
		crComponent[0] = curX;
	} else {
		crComponent[0] = 0;
		crComponent[1] = ((crComponent[1]) + 1);
	}
	return sample;
}

static int nextSampleFromblocks(int * aComponent, int ** aBlockArray) {
    int sampleIndex;
    int blockIndex;
    int dx;
    int sx;
    int sy;
    int dy;
    int curX;
    int sample;

	dx = curX = aComponent[0];
	dy = aComponent[1];
	sx = aComponent[2];
	sy = aComponent[3];
	if (!((sx == 0) && (sy == 0))) {
		dx = dx / sx;
		dy = dy / sy;
	}
	blockIndex = ((((unsigned) dy >> 3)) * (aComponent[5])) + (((unsigned) dx >> 3));
	sampleIndex = (((unsigned) (dy & 7) << 3)) + (dx & 7);
	sample = (aBlockArray[blockIndex])[sampleIndex];
	curX += 1;
	if (curX < ((aComponent[8]) * 8)) {
		aComponent[0] = curX;
	} else {
		aComponent[0] = 0;
		aComponent[1] = ((aComponent[1]) + 1);
	}
	return sample;
}

static int nextSampleY(void) {
    int sampleIndex;
    int blockIndex;
    int dx;
    int sx;
    int sy;
    int dy;
    int curX;
    int sample;

	dx = curX = yComponent[0];
	dy = yComponent[1];
	sx = yComponent[2];
	sy = yComponent[3];
	if (!((sx == 0) && (sy == 0))) {
		dx = dx / sx;
		dy = dy / sy;
	}
	blockIndex = ((((unsigned) dy >> 3)) * (yComponent[5])) + (((unsigned) dx >> 3));
	sampleIndex = (((unsigned) (dy & 7) << 3)) + (dx & 7);
	sample = (yBlocks[blockIndex])[sampleIndex];
	curX += 1;
	if (curX < ((yComponent[8]) * 8)) {
		yComponent[0] = curX;
	} else {
		yComponent[0] = 0;
		yComponent[1] = ((yComponent[1]) + 1);
	}
	return sample;
}


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

EXPORT(int) JPEGReaderPlugin_primitiveColorConvertGrayscaleMCU(void) {
    int arrayOop;
    int y;
    int i;
    int sampleIndex;
    int blockIndex;
    int dx;
    int sx;
    int sy;
    int dy;
    int curX;
    int sample;

	stInit();
	if (!((interpreterProxy->methodArgumentCount()) == 4)) {
		return interpreterProxy->primitiveFail();
	}
	ditherMask = interpreterProxy->stackIntegerValue(0);
	arrayOop = interpreterProxy->stackObjectValue(1);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!((interpreterProxy->isWords(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == 3))) {
		return interpreterProxy->primitiveFail();
	}
	residuals = interpreterProxy->firstIndexableField(arrayOop);
	arrayOop = interpreterProxy->stackObjectValue(2);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!(interpreterProxy->isWords(arrayOop))) {
		return interpreterProxy->primitiveFail();
	}
	jpegBitsSize = interpreterProxy->slotSizeOf(arrayOop);
	jpegBits = interpreterProxy->firstIndexableField(arrayOop);
	arrayOop = interpreterProxy->stackObjectValue(3);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!((colorComponentfrom(yComponent, arrayOop)) && (colorComponentBlocksfrom(yBlocks, arrayOop)))) {
		return interpreterProxy->primitiveFail();
	}
	/* begin colorConvertGrayscaleMCU */
	yComponent[0] = 0;
	yComponent[1] = 0;
	for (i = 0; i <= (jpegBitsSize - 1); i += 1) {
		/* begin nextSampleY */
		dx = curX = yComponent[0];
		dy = yComponent[1];
		sx = yComponent[2];
		sy = yComponent[3];
		if (!((sx == 0) && (sy == 0))) {
			dx = dx / sx;
			dy = dy / sy;
		}
		blockIndex = ((((unsigned) dy >> 3)) * (yComponent[5])) + (((unsigned) dx >> 3));
		sampleIndex = (((unsigned) (dy & 7) << 3)) + (dx & 7);
		sample = (yBlocks[blockIndex])[sampleIndex];
		curX += 1;
		if (curX < ((yComponent[8]) * 8)) {
			yComponent[0] = curX;
		} else {
			yComponent[0] = 0;
			yComponent[1] = ((yComponent[1]) + 1);
		}
		y = sample;
		y += residuals[1];
		y = ((y < 255) ? y : 255);
		residuals[1] = (y & ditherMask);
		y = y & (255 - ditherMask);
		y = ((y < 1) ? 1 : y);
		jpegBits[i] = (((4278190080U + (y << 16)) + (y << 8)) + y);
	}
	interpreterProxy->pop(4);
}


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

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

	stInit();
	if (!((interpreterProxy->methodArgumentCount()) == 4)) {
		return interpreterProxy->primitiveFail();
	}
	ditherMask = interpreterProxy->stackIntegerValue(0);
	arrayOop = interpreterProxy->stackObjectValue(1);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!((interpreterProxy->isWords(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == 3))) {
		return interpreterProxy->primitiveFail();
	}
	residuals = interpreterProxy->firstIndexableField(arrayOop);
	arrayOop = interpreterProxy->stackObjectValue(2);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!(interpreterProxy->isWords(arrayOop))) {
		return interpreterProxy->primitiveFail();
	}
	jpegBitsSize = interpreterProxy->slotSizeOf(arrayOop);
	jpegBits = interpreterProxy->firstIndexableField(arrayOop);
	arrayOop = interpreterProxy->stackObjectValue(3);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!((interpreterProxy->isPointers(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == 3))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(yColorComponentFrom(interpreterProxy->fetchPointerofObject(0, arrayOop)))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(cbColorComponentFrom(interpreterProxy->fetchPointerofObject(1, arrayOop)))) {
		return interpreterProxy->primitiveFail();
	}
	if (!(crColorComponentFrom(interpreterProxy->fetchPointerofObject(2, arrayOop)))) {
		return interpreterProxy->primitiveFail();
	}
	/* begin colorConvertMCU */
	yComponent[0] = 0;
	yComponent[1] = 0;
	cbComponent[0] = 0;
	cbComponent[1] = 0;
	crComponent[0] = 0;
	crComponent[1] = 0;
	for (i = 0; i <= (jpegBitsSize - 1); i += 1) {
		/* begin nextSampleY */
		dx = curX = yComponent[0];
		dy = yComponent[1];
		sx = yComponent[2];
		sy = yComponent[3];
		if (!((sx == 0) && (sy == 0))) {
			dx = dx / sx;
			dy = dy / sy;
		}
		blockIndex = ((((unsigned) dy >> 3)) * (yComponent[5])) + (((unsigned) dx >> 3));
		sampleIndex = (((unsigned) (dy & 7) << 3)) + (dx & 7);
		sample = (yBlocks[blockIndex])[sampleIndex];
		curX += 1;
		if (curX < ((yComponent[8]) * 8)) {
			yComponent[0] = curX;
		} else {
			yComponent[0] = 0;
			yComponent[1] = ((yComponent[1]) + 1);
		}
		y = sample;
		/* begin nextSampleCb */
		dx1 = curX1 = cbComponent[0];
		dy1 = cbComponent[1];
		sx1 = cbComponent[2];
		sy1 = cbComponent[3];
		if (!((sx1 == 0) && (sy1 == 0))) {
			dx1 = dx1 / sx1;
			dy1 = dy1 / sy1;
		}
		blockIndex1 = ((((unsigned) dy1 >> 3)) * (cbComponent[5])) + (((unsigned) dx1 >> 3));
		sampleIndex1 = (((unsigned) (dy1 & 7) << 3)) + (dx1 & 7);
		sample1 = (cbBlocks[blockIndex1])[sampleIndex1];
		curX1 += 1;
		if (curX1 < ((cbComponent[8]) * 8)) {
			cbComponent[0] = curX1;
		} else {
			cbComponent[0] = 0;
			cbComponent[1] = ((cbComponent[1]) + 1);
		}
		cb = sample1;
		cb -= 127;
		/* begin nextSampleCr */
		dx2 = curX2 = crComponent[0];
		dy2 = crComponent[1];
		sx2 = crComponent[2];
		sy2 = crComponent[3];
		if (!((sx2 == 0) && (sy2 == 0))) {
			dx2 = dx2 / sx2;
			dy2 = dy2 / sy2;
		}
		blockIndex2 = ((((unsigned) dy2 >> 3)) * (crComponent[5])) + (((unsigned) dx2 >> 3));
		sampleIndex2 = (((unsigned) (dy2 & 7) << 3)) + (dx2 & 7);
		sample2 = (crBlocks[blockIndex2])[sampleIndex2];
		curX2 += 1;
		if (curX2 < ((crComponent[8]) * 8)) {
			crComponent[0] = curX2;
		} else {
			crComponent[0] = 0;
			crComponent[1] = ((crComponent[1]) + 1);
		}
		cr = sample2;
		cr -= 127;
		red = (y + (((int) (91881 * cr) >> 16))) + (residuals[0]);
		red = ((red < 255) ? red : 255);
		red = ((red < 0) ? 0 : red);
		residuals[0] = (red & ditherMask);
		red = red & (255 - ditherMask);
		red = ((red < 1) ? 1 : red);
		green = ((y - (((int) (22554 * cb) >> 16))) - (((int) (46802 * cr) >> 16))) + (residuals[1]);
		green = ((green < 255) ? green : 255);
		green = ((green < 0) ? 0 : green);
		residuals[1] = (green & ditherMask);
		green = green & (255 - ditherMask);
		green = ((green < 1) ? 1 : green);
		blue = (y + (((int) (116130 * cb) >> 16))) + (residuals[2]);
		blue = ((blue < 255) ? blue : 255);
		blue = ((blue < 0) ? 0 : blue);
		residuals[2] = (blue & ditherMask);
		blue = blue & (255 - ditherMask);
		blue = ((blue < 1) ? 1 : blue);
		jpegBits[i] = (((4278190080U + (((unsigned) red << 16))) + (((unsigned) green << 8))) + blue);
	}
	interpreterProxy->pop(4);
}


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

EXPORT(int) JPEGReaderPlugin_primitiveDecodeMCU(void) {
    int oop;
    int * anArray;
    int arrayOop;
    int streamOop;

	;
	if (!((interpreterProxy->methodArgumentCount()) == 5)) {
		return interpreterProxy->primitiveFail();
	}
	oop = interpreterProxy->stackObjectValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!(loadJPEGStreamFrom(oop))) {
		return interpreterProxy->primitiveFail();
	}
	arrayOop = interpreterProxy->stackObjectValue(1);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!(interpreterProxy->isWords(arrayOop))) {
		return interpreterProxy->primitiveFail();
	}
	acTableSize = interpreterProxy->slotSizeOf(arrayOop);
	acTable = interpreterProxy->firstIndexableField(arrayOop);
	arrayOop = interpreterProxy->stackObjectValue(2);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!(interpreterProxy->isWords(arrayOop))) {
		return interpreterProxy->primitiveFail();
	}
	dcTableSize = interpreterProxy->slotSizeOf(arrayOop);
	dcTable = interpreterProxy->firstIndexableField(arrayOop);
	oop = interpreterProxy->stackObjectValue(3);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!(colorComponentfrom(yComponent, oop))) {
		return interpreterProxy->primitiveFail();
	}
	arrayOop = interpreterProxy->stackObjectValue(4);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!(interpreterProxy->isWords(arrayOop))) {
		return interpreterProxy->primitiveFail();
	}
	if (!((interpreterProxy->slotSizeOf(arrayOop)) == 64)) {
		return interpreterProxy->primitiveFail();
	}
	anArray = interpreterProxy->firstIndexableField(arrayOop);
	if (interpreterProxy->failed()) {
		return null;
	}
	decodeBlockIntocomponent(anArray, yComponent);
	if (interpreterProxy->failed()) {
		return null;
	}
	/* begin storeJPEGStreamOn: */
	streamOop = interpreterProxy->stackValue(0);
	interpreterProxy->storeIntegerofObjectwithValue(1, streamOop, jsPosition);
	interpreterProxy->storeIntegerofObjectwithValue(3, streamOop, jsBitBuffer);
	interpreterProxy->storeIntegerofObjectwithValue(4, streamOop, jsBitCount);
	interpreterProxy->storeIntegerofObjectwithValue(10, interpreterProxy->stackValue(3), yComponent[10]);
	interpreterProxy->pop(5);
}


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

EXPORT(int) JPEGReaderPlugin_primitiveIdctInt(void) {
    int * anArray;
    int arrayOop;
    int * qt;

	;
	if (!((interpreterProxy->methodArgumentCount()) == 2)) {
		return interpreterProxy->primitiveFail();
	}
	arrayOop = interpreterProxy->stackObjectValue(0);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!((interpreterProxy->isWords(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == 64))) {
		return interpreterProxy->primitiveFail();
	}
	qt = interpreterProxy->firstIndexableField(arrayOop);
	arrayOop = interpreterProxy->stackObjectValue(1);
	if (interpreterProxy->failed()) {
		return null;
	}
	if (!((interpreterProxy->isWords(arrayOop)) && ((interpreterProxy->slotSizeOf(arrayOop)) == 64))) {
		return interpreterProxy->primitiveFail();
	}
	anArray = interpreterProxy->firstIndexableField(arrayOop);
	idctBlockIntqt(anArray, qt);
	interpreterProxy->pop(2);
}

static int scaleAndSignExtendinFieldWidth(int aNumber, int w) {
	if (aNumber < ((((w - 1) < 0) ? ((unsigned) 1 >> -(w - 1)) : ((unsigned) 1 << (w - 1))))) {
		return (aNumber - (((w < 0) ? ((unsigned) 1 >> -w) : ((unsigned) 1 << w)))) + 1;
	} else {
		return aNumber;
	}
}


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

EXPORT(int) JPEGReaderPlugin_setInterpreter(struct VirtualMachine* anInterpreter) {
    int ok;

	interpreterProxy = anInterpreter;
	ok = interpreterProxy->majorVersion() == VM_PROXY_MAJOR;
	if (ok == 0) {
		return 0;
	}
	ok = interpreterProxy->minorVersion() >= VM_PROXY_MINOR;
	return ok;
}

static int stInit(void) {
	;
}

static int storeJPEGStreamOn(int streamOop) {
	interpreterProxy->storeIntegerofObjectwithValue(1, streamOop, jsPosition);
	interpreterProxy->storeIntegerofObjectwithValue(3, streamOop, jsBitBuffer);
	interpreterProxy->storeIntegerofObjectwithValue(4, streamOop, jsBitCount);
}

static int yColorComponentFrom(int oop) {
	return (colorComponentfrom(yComponent, oop)) && (colorComponentBlocksfrom(yBlocks, oop));
}
