// The first three bytes should be FF, SOI, FF
if (((buffer.buf[0] & 0xff) != 0xff)
|| ((buffer.buf[1] & 0xff) != JPEG.SOI)
|| ((buffer.buf[2] & 0xff) != 0xff)) {
throw new IIOException ("Image format error");
}
boolean done = false;
buffer.bufAvail -=2; // Next byte should be the ff before a marker
buffer.bufPtr = 2;
MarkerSegment newGuy = null;
while (!done) {
byte [] buf;
int ptr;
buffer.loadBuf(1);
if (debug) {
System.out.println("top of loop");
buffer.print(10);
}
buffer.scanForFF(reader);
switch (buffer.buf[buffer.bufPtr] & 0xff) {
case 0:
if (debug) {
System.out.println("Skipping 0");
}
buffer.bufAvail--;
buffer.bufPtr++;
break;
case JPEG.SOF0:
case JPEG.SOF1:
case JPEG.SOF2:
if (isStream) {
throw new IIOException
("SOF not permitted in stream metadata");
}
newGuy = new SOFMarkerSegment(buffer);
break;
case JPEG.DQT:
newGuy = new DQTMarkerSegment(buffer);
break;
case JPEG.DHT:
newGuy = new DHTMarkerSegment(buffer);
break;
case JPEG.DRI:
newGuy = new DRIMarkerSegment(buffer);
break;
case JPEG.APP0:
// Either JFIF, JFXX, or unknown APP0
buffer.loadBuf(8); // tag, length, id
buf = buffer.buf;
ptr = buffer.bufPtr;
if ((buf[ptr+3] == 'J')
&& (buf[ptr+4] == 'F')
&& (buf[ptr+5] == 'I')
&& (buf[ptr+6] == 'F')
&& (buf[ptr+7] == 0)) {
if (inThumb) {
reader.warningOccurred
(JPEGImageReader.WARNING_NO_JFIF_IN_THUMB);
// Leave newGuy null
// Read a dummy to skip the segment
JFIFMarkerSegment dummy =
new JFIFMarkerSegment(buffer);
} else if (isStream) {
throw new IIOException
("JFIF not permitted in stream metadata");
} else if (markerSequence.isEmpty() == false) {
throw new IIOException
("JFIF APP0 must be first marker after SOI");
} else {
newGuy = new JFIFMarkerSegment(buffer);
}
} else if ((buf[ptr+3] == 'J')
&& (buf[ptr+4] == 'F')
&& (buf[ptr+5] == 'X')
&& (buf[ptr+6] == 'X')
&& (buf[ptr+7] == 0)) {
if (isStream) {
throw new IIOException
("JFXX not permitted in stream metadata");
}
if (inThumb) {
throw new IIOException
("JFXX markers not allowed in JFIF JPEG thumbnail");
}
JFIFMarkerSegment jfif =
(JFIFMarkerSegment) findMarkerSegment
(JFIFMarkerSegment.class, true);
if (jfif == null) {
throw new IIOException
("JFXX encountered without prior JFIF!");
}
jfif.addJFXX(buffer, reader);
// newGuy remains null
} else {
newGuy = new MarkerSegment(buffer);
newGuy.loadData(buffer);
}
break;
case JPEG.APP2:
// Either an ICC profile or unknown APP2
buffer.loadBuf(15); // tag, length, id
if ((buffer.buf[buffer.bufPtr+3] == 'I')
&& (buffer.buf[buffer.bufPtr+4] == 'C')
&& (buffer.buf[buffer.bufPtr+5] == 'C')
&& (buffer.buf[buffer.bufPtr+6] == '_')
&& (buffer.buf[buffer.bufPtr+7] == 'P')
&& (buffer.buf[buffer.bufPtr+8] == 'R')
&& (buffer.buf[buffer.bufPtr+9] == 'O')
&& (buffer.buf[buffer.bufPtr+10] == 'F')
&& (buffer.buf[buffer.bufPtr+11] == 'I')
&& (buffer.buf[buffer.bufPtr+12] == 'L')
&& (buffer.buf[buffer.bufPtr+13] == 'E')
&& (buffer.buf[buffer.bufPtr+14] == 0)
) {
if (isStream) {
throw new IIOException
("ICC profiles not permitted in stream metadata");
}
JFIFMarkerSegment jfif =
(JFIFMarkerSegment) findMarkerSegment
(JFIFMarkerSegment.class, true);
if (jfif == null) {
newGuy = new MarkerSegment(buffer);
newGuy.loadData(buffer);
} else {
jfif.addICC(buffer);
}
// newGuy remains null
} else {
newGuy = new MarkerSegment(buffer);
newGuy.loadData(buffer);
}
break;
case JPEG.APP14:
// Either Adobe or unknown APP14
buffer.loadBuf(8); // tag, length, id
if ((buffer.buf[buffer.bufPtr+3] == 'A')
&& (buffer.buf[buffer.bufPtr+4] == 'd')
&& (buffer.buf[buffer.bufPtr+5] == 'o')
&& (buffer.buf[buffer.bufPtr+6] == 'b')
&& (buffer.buf[buffer.bufPtr+7] == 'e')) {
if (isStream) {
throw new IIOException
("Adobe APP14 markers not permitted in stream metadata");
}
newGuy = new AdobeMarkerSegment(buffer);
} else {
newGuy = new MarkerSegment(buffer);
newGuy.loadData(buffer);
}
break;
case JPEG.COM:
newGuy = new COMMarkerSegment(buffer);
break;
case JPEG.SOS:
if (isStream) {
throw new IIOException
("SOS not permitted in stream metadata");
}
newGuy = new SOSMarkerSegment(buffer);
break;
case JPEG.RST0:
case JPEG.RST1:
case JPEG.RST2:
case JPEG.RST3:
case JPEG.RST4:
case JPEG.RST5:
case JPEG.RST6:
case JPEG.RST7:
if (debug) {
System.out.println("Restart Marker");
}
buffer.bufPtr++; // Just skip it
buffer.bufAvail--;
break;
case JPEG.EOI:
done = true;
buffer.bufPtr++;
buffer.bufAvail--;
break;
default:
newGuy = new MarkerSegment(buffer);
newGuy.loadData(buffer);
newGuy.unknown = true;
break;
}
if (newGuy != null) {
markerSequence.add(newGuy);
if (debug) {
newGuy.print();
}
newGuy = null;
}
}
// Now that we've read up to the EOI, we need to push back
// whatever is left in the buffer, so that the next read
// in the native code will work.
buffer.pushBack();
if (!isConsistent()) {
throw new IIOException("Inconsistent metadata read from stream");
}
}