1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
|
/*
* JPEGCodec
*
* Copyright (c) 2004, 2005, 2006 Marco Schmidt.
* All rights reserved.
*/
package net.sourceforge.jiu.codecs.jpeg;
import java.io.DataInput;
import java.io.File;
import java.io.IOException;
import net.sourceforge.jiu.codecs.CodecMode;
import net.sourceforge.jiu.codecs.ImageCodec;
import net.sourceforge.jiu.codecs.InvalidFileStructureException;
import net.sourceforge.jiu.codecs.UnsupportedTypeException;
import net.sourceforge.jiu.codecs.WrongFileFormatException;
import net.sourceforge.jiu.data.PixelImage;
import net.sourceforge.jiu.ops.MissingParameterException;
import net.sourceforge.jiu.ops.OperationFailedException;
import net.sourceforge.jiu.util.ArrayConverter;
/**
* A codec for the JPEG file format.
* <h3>Supported JPEG types</h3>
* The codec is still under development.
* Nothing can be read with it right now.
* Writing JPEG files is not even in development stage.
* <h3>Credits</h3>
* "<em>JPEG Still Image Data Compression Standard</em>" by William B. Pennebaker and
* Joan L. Mitchell. Published 1993 by Van Nostrand Reinhold.
* ISBN 0-442-01272-1.
* This book is referenced as P&M throughout the source code.
* It's an invaluable resource for anything related to JPEG.
* @author Marco Schmidt
* @since 0.13.0
*/
public class JPEGCodec extends ImageCodec
{
private DataInput in;
private void decodeScan(JPEGData jpegData)
{
JPEGFrame frame = jpegData.getFrame();
int width = frame.getWidth();
int height = frame.getHeight();
/*Gray8Image image = new MemoryGray8Image(width, height);
int x = 0;
int y = 0;*/
int numMCUs = ((width + 7) / 8) * ((height + 7) / 8);
while (numMCUs > 0)
{
numMCUs--;
}
}
public String[] getFileExtensions()
{
return new String[] {".jpg", ".jpeg"};
}
public String getFormatName()
{
return "JPEG File Interchange Format";
}
public String[] getMimeTypes()
{
// image/pjpeg for progressive JPEGs is not included
// because it's not supported by this codec (yet)
return new String[] {"image/jpeg"};
}
public boolean isLoadingSupported()
{
return true;
}
public boolean isSavingSupported()
{
return false;
}
private void load() throws
OperationFailedException,
WrongFileFormatException
{
in = getInputAsDataInput();
if (in == null)
{
throw new MissingParameterException(
"Input object missing (could not retrieve via getAsDataInput).");
}
try
{
// read and check the first two bytes
byte[] data = new byte[4];
in.readFully(data, 0, 2);
int signature = ArrayConverter.getShortBEAsInt(data, 0);
if (signature != JPEGConstants.JFIF_SIGNATURE)
{
throw new WrongFileFormatException(
"Not a JFIF file (first two bytes are not 0xff 0xd8).");
}
// continuously read markers, updating a JPEGData object
JPEGData jpegData = new JPEGData();
while (true)
{
// read and decode marker type and length
in.readFully(data);
int marker = ArrayConverter.getShortBEAsInt(data, 0);
int length = ArrayConverter.getShortBEAsInt(data, 2);
// read the actual marker information
readMarker(jpegData, marker, length);
}
}
catch (IOException ioe)
{
throw new OperationFailedException("Error reading from input.");
}
finally
{
close();
}
}
public static void main(String[] args) throws Exception
{
if (args.length < 1)
{
System.err.println("Need JPEG file names as arguments.");
System.exit(1);
}
for (int i = 0; i < args.length; i++)
{
String fileName = args[i];
JPEGCodec codec = new JPEGCodec();
codec.setFile(new File(fileName), CodecMode.LOAD);
codec.process();
//PixelImage image = codec.getImage();
}
}
public void process() throws
MissingParameterException,
OperationFailedException,
WrongFileFormatException
{
initModeFromIOObjects();
if (getMode() == CodecMode.LOAD)
{
load();
}
else
if (getMode() == CodecMode.SAVE)
{
throw new OperationFailedException("Saving is not supported.");
}
else
{
throw new OperationFailedException("Unsupported codec mode.");
}
}
private void readMarker(JPEGData jpegData, int marker, int length) throws
InvalidFileStructureException,
IOException,
UnsupportedTypeException
{
// make sure marker is a valid marker
if ((marker >> 8) != 0xff)
{
// TODO: instead of giving up, search for next occurrence of 0xff (error recovery)
throw new InvalidFileStructureException("Marker " +
marker + " does not have 0xff in its top eight bits.");
}
// zero out everything but the least significant byte
marker &= 0xff;
// decrease two bytes for the marker length field
length -= 2;
// react on marker, possible reactions:
// - call corresponding method if available
// - throw exception if unsupported
// - skip otherwise (= marker is unknown)
switch(marker)
{
case(JPEGConstants.MARKER_DHT):
{
JPEGMarkerReader.readHuffmanTables(in, jpegData, length);
break;
}
case(JPEGConstants.MARKER_DQT):
{
JPEGMarkerReader.readQuantizationTables(in, jpegData, length);
break;
}
// Start of frame: Huffman Baseline DCT
case(JPEGConstants.MARKER_SOF0):
{
JPEGMarkerReader.readStartOfFrame(in, jpegData, marker, length);
break;
}
// unsupported frame types
case(JPEGConstants.MARKER_SOF1):
case(JPEGConstants.MARKER_SOF2):
case(JPEGConstants.MARKER_SOF3):
case(JPEGConstants.MARKER_SOF5):
case(JPEGConstants.MARKER_SOF6):
case(JPEGConstants.MARKER_SOF7):
case(JPEGConstants.MARKER_SOF9):
case(JPEGConstants.MARKER_SOFA):
case(JPEGConstants.MARKER_SOFB):
case(JPEGConstants.MARKER_SOFD):
case(JPEGConstants.MARKER_SOFE):
case(JPEGConstants.MARKER_SOFF):
{
throw new UnsupportedTypeException(
"Unsupported JPEG SOF type: " + Integer.toHexString(marker));
}
case(JPEGConstants.MARKER_SOS):
{
JPEGMarkerReader.readStartOfScan(in, jpegData, length);
decodeScan(jpegData);
break;
}
default:
{
System.out.println("Unknown marker: " + Integer.toHexString(marker));
// skip marker data
while (length > 0)
{
int skipped = in.skipBytes(length);
if (skipped > 0)
{
length -= skipped;
}
}
break;
}
}
}
public String suggestFileExtension(PixelImage image)
{
return ".jpg";
}
}
|