btparser/cparser/JPGTemplate.bt

1605 lines
44 KiB
Plaintext

// 010 Editor v2.02 Binary Template
//
// File : JpgTemplate.bt
// Author : Mor FTP
// Purpose : Designed for jpg files
// E-Mail : morftp AT hotmail DOT com
// LAST MODIFIED : Nov 3 2014
// This is a detailed JPEG File analysis.
//Features
// 1. Huffmann and quantization tables.
// 2. Exif (APP1) information including jpeg and other thubnail images
// 3. SOS, SOF0, JIFF and APP0 sections
//
// Note : This code doesn't parse all known sections. The reson is the application sections
// contain camera specific information and this information sometimes is not public or
// related to the camera and not important for image display softwares.
//
// New Features: Parses MakerNote for casio qv-r62
//
// 2014-11-03 SweetScape
// * fixed using FTell instead of Ftell
//
// 2012-10-04 dxp
// * added JPEG-LS marker structure.
//
// 2009-03-14 modified by Kuang-che Wu
// * fix parse fail if encounter unknown APP1
// * fix uShort typo
// * parse inlined EXIF data correctly
// * recognize more sections and fields, especially EXIF tags, GPS tags, and CIFF tags
// * and many improvements
//
//--------------------------------------
// references:
// JPEG http://www.w3.org/Graphics/JPEG/itu-t81.pdf
// JFIF http://www.w3.org/Graphics/JPEG/jfif3.pdf
// EXIF http://www.exif.org/Exif2-2.PDF
// CIFF http://xyrion.org/ciff/CIFFspecV1R04.pdf
// exiftool http://www.sno.phy.queensu.ca/~phil/exiftool/
// JPEG-LS http://www.itu.int/rec/T-REC-T.87-199806-I/en
// set left to right for both endian
LittleEndian(); BitfieldLeftToRight();
BigEndian(); BitfieldLeftToRight();
local quad JpegFileEnd = 0;
local int colorId = 0;
local int colorSelect = 0;
local DWORD clr = 0;
local DWORD jetMap[6*3] = { // blue, red green
0x0000cc,0x0000ff,0x0033ff,0x0066ff,0x0099ff,0x00ccff,
0x00ffff,0x33ffcc,0x66ff99,0x99ff66,0xccff33,0xffff00,
0xffcc00,0xff9900,0xff6600,0xff3300,0xff0000,0xcc0000
};
local char CameraMake[32];
local char CameraModel[40];
local string stack_IFD_dirtype = "";
enum IFD_dirtype {
IFD_TYPE_EXIF = 1,
IFD_TYPE_GEOTAG,
IFD_TYPE_CASIO_QV_R62,
};
// ------------------------------------------------------------
// helper functions
void Stack_push(string &s, int x)
{
s += (char)x;
}
void Stack_pop(string &s)
{
s = SubStr(s, 0, Strlen(s) - 1);
}
int Stack_top(string &s)
{
return s[Strlen(s) - 1];
}
string ReadStringN(int64 pos, int n)
{
local uchar s[n];
ReadBytes(s, pos, n);
return s;
}
// ------------------------------------------------------------
void ChangeColor(byte bChangeColor) {
if(bChangeColor == 1) {colorSelect++; colorId = 0;}
clr = jetMap[(colorSelect%3)*6+(colorId%6)];
SetBackColor(clr);
//Printf("clrIdx = [%d %d], RGB(%d,%d,%d)\n",colorSelect,colorId,(clr>>16),(clr>>8)&0x00FF,clr&0x0000FF);
colorId++;
}
// ------------------------------------------------------------
// JPEG
typedef enum <WORD> tagID
{
M_SOF0 = 0xFFC0, // Start Of Frame N
M_SOF1,// N indicates which compression process
M_SOF2,// Only SOF0-SOF2 are now in common use
M_SOF3,
M_DHT, //Huffman Table
M_SOF5,
M_SOF6,
M_SOF7,
M_JPG,
M_SOF9,
M_SOF10,
M_SOF11,
M_DAC = 0xffcc,
M_SOF13,
M_SOF14,
M_SOF15,
M_RST0 = 0xffd0,
M_RST1, M_RST2, M_RST3, M_RST4, M_RST5, M_RST6, M_RST7,
M_SOI = 0xFFD8, // Start Of Image
M_EOI,// End Of Image
M_SOS,// Start Of Scan (begins compressed data)
M_DQT,
M_DNL,
M_DRI,
M_DHP,
M_EXP,
M_APP0 = 0xFFE0, // Jfif marker
M_APP1,// Exif marker
M_APP2,
M_APP3,
M_APP4,
M_APP5,
M_APP6,
M_APP7,
M_APP8,
M_APP9,
M_APP10,
M_APP11,
M_APP12,
M_APP13,
M_APP14,
M_APP15,
M_JPG0 = 0xfff0,
M_JPG1, M_JPG2, M_JPG3, M_JPG4, M_JPG5, M_JPG6, M_JPGLS,
M_JPG8, M_JPG9, M_JPG10, M_JPG11, M_JPG12, M_JPG13, M_JPG14, M_JPG15,
M_COMM = 0xFFFE // Comment
} M_ID <format=hex>;
// ------------------------------------------------------------
// EXIF tags
typedef enum <WORD> tagExifTag {
/////////////////////////////////// Format Comp Description
InteropIndex = 0x0001,
InteropVersion = 0x0002,
SubfileType = 0x00fe,
OldSubfileType = 0x00ff,
ImageWidth = 0x0100,
ImageHeight = 0x0101,
BitsPerSample = 0x0102,
Compression = 0x0103,
PhotometricInterpretation = 0x0106,
Thresholding = 0x0107,
CellWidth = 0x0108,
CellLength = 0x0109,
FillOrder = 0x010a,
DocumentName = 0x010d,
ImageDescription = 0x010e,
Make = 0x010f,
Model = 0x0110,
StripOffsets = 0x0111,
Orientation = 0x0112,
SamplesPerPixel = 0x0115,
RowsPerStrip = 0x0116,
StripByteCounts = 0x0117,
MinSampleValue = 0x0118,
MaxSampleValue = 0x0119,
XResolution = 0x011a,
YResolution = 0x011b,
PlanarConfiguration = 0x011c,
PageName = 0x011d,
XPosition = 0x011e,
YPosition = 0x011f,
FreeOffsets = 0x0120,
FreeByteCounts = 0x0121,
GrayResponseUnit = 0x0122,
GrayResponseCurve = 0x0123,
T4Options = 0x0124,
T6Options = 0x0125,
ResolutionUnit = 0x0128,
PageNumber = 0x0129,
ColorResponseUnit = 0x012c,
TransferFunction = 0x012d,
Software = 0x0131,
ModifyDate = 0x0132,
Artist = 0x013b,
HostComputer = 0x013c,
Predictor = 0x013d,
WhitePoint = 0x013e,
PrimaryChromaticities = 0x013f,
ColorMap = 0x0140,
HalftoneHints = 0x0141,
TileWidth = 0x0142,
TileLength = 0x0143,
TileOffsets = 0x0144,
TileByteCounts = 0x0145,
BadFaxLines = 0x0146,
CleanFaxData = 0x0147,
ConsecutiveBadFaxLines = 0x0148,
SubIFD = 0x014a,
InkSet = 0x014c,
InkNames = 0x014d,
NumberofInks = 0x014e,
DotRange = 0x0150,
TargetPrinter = 0x0151,
ExtraSamples = 0x0152,
SampleFormat = 0x0153,
SMinSampleValue = 0x0154,
SMaxSampleValue = 0x0155,
TransferRange = 0x0156,
ClipPath = 0x0157,
XClipPathUnits = 0x0158,
YClipPathUnits = 0x0159,
Indexed = 0x015a,
JPEGTables = 0x015b,
OPIProxy = 0x015f,
GlobalParametersIFD = 0x0190,
ProfileType = 0x0191,
FaxProfile = 0x0192,
CodingMethods = 0x0193,
VersionYear = 0x0194,
ModeNumber = 0x0195,
Decode = 0x01b1,
DefaultImageColor = 0x01b2,
JPEGProc = 0x0200,
ThumbnailOffset = 0x0201,
ThumbnailLength = 0x0202,
JPEGRestartInterval = 0x0203,
JPEGLosslessPredictors = 0x0205,
JPEGPointTransforms = 0x0206,
JPEGQTables = 0x0207,
JPEGDCTables = 0x0208,
JPEGACTables = 0x0209,
YCbCrCoefficients = 0x0211,
YCbCrSubSampling = 0x0212,
YCbCrPositioning = 0x0213,
ReferenceBlackWhite = 0x0214,
StripRowCounts = 0x022f,
ApplicationNotes = 0x02bc,
RelatedImageFileFormat = 0x1000,
RelatedImageWidth = 0x1001,
RelatedImageLength = 0x1002,
ImageID = 0x800d,
WangAnnotation = 0x80a4,
Matteing = 0x80e3,
DataType = 0x80e4,
ImageDepth = 0x80e5,
TileDepth = 0x80e6,
Model2 = 0x827d,
CFARepeatPatternDim = 0x828d,
CFAPattern2 = 0x828e,
BatteryLevel = 0x828f,
Copyright = 0x8298,
ExposureTime = 0x829a,
FNumber = 0x829d,
PixelScale = 0x830e,
IPTC_NAA = 0x83bb,
IntergraphPacketData = 0x8474,
IntergraphFlagRegisters = 0x847f,
IntergraphMatrix = 0x8480,
ModelTiePoint = 0x8482,
Site = 0x84e0,
ColorSequence = 0x84e1,
IT8Header = 0x84e2,
RasterPadding = 0x84e3,
BitsPerRunLength = 0x84e4,
BitsPerExtendedRunLength = 0x84e5,
ColorTable = 0x84e6,
ImageColorIndicator = 0x84e7,
BackgroundColorIndicator = 0x84e8,
ImageColorValue = 0x84e9,
BackgroundColorValue = 0x84ea,
PixelIntensityRange = 0x84eb,
TransparencyIndicator = 0x84ec,
ColorCharacterization = 0x84ed,
HCUsage = 0x84ee,
IPTC_NAA2 = 0x8568,
ModelTransform = 0x85d8,
PhotoshopSettings = 0x8649,
ExifOffset = 0x8769,
ICC_Profile = 0x8773,
ImageLayer = 0x87ac,
GeoTiffDirectory = 0x87af,
GeoTiffDoubleParams = 0x87b0,
GeoTiffAsciiParams = 0x87b1,
ExposureProgram = 0x8822,
SpectralSensitivity = 0x8824,
GPSInfo = 0x8825,
ISO = 0x8827,
OptoElectricConvFactor = 0x8828,
Interlace = 0x8829,
TimeZoneOffset = 0x882a,
SelfTimerMode = 0x882b,
FaxRecvParams = 0x885c,
FaxSubAddress = 0x885d,
FaxRecvTime = 0x885e,
ExifVersion = 0x9000,
DateTimeOriginal = 0x9003,
CreateDate = 0x9004,
ComponentsConfiguration = 0x9101,
CompressedBitsPerPixel = 0x9102,
ShutterSpeedValue = 0x9201,
ApertureValue = 0x9202,
BrightnessValue = 0x9203,
ExposureCompensation = 0x9204,
MaxApertureValue = 0x9205,
SubjectDistance = 0x9206,
MeteringMode = 0x9207,
LightSource = 0x9208,
Flash = 0x9209,
FocalLength = 0x920a,
FlashEnergy = 0x920b,
SpatialFrequencyResponse = 0x920c,
Noise = 0x920d,
FocalPlaneXResolution = 0x920e,
FocalPlaneYResolution = 0x920f,
FocalPlaneResolutionUnit = 0x9210,
ImageNumber = 0x9211,
SecurityClassification = 0x9212,
ImageHistory = 0x9213,
SubjectLocation = 0x9214,
ExposureIndex = 0x9215,
TIFF_EPStandardID = 0x9216,
SensingMethod = 0x9217,
StoNits = 0x923f,
MakerNote = 0x927c,
UserComment = 0x9286,
SubSecTime = 0x9290,
SubSecTimeOriginal = 0x9291,
SubSecTimeDigitized = 0x9292,
ImageSourceData = 0x935c,
XPTitle = 0x9c9b,
XPComment = 0x9c9c,
XPAuthor = 0x9c9d,
XPKeywords = 0x9c9e,
XPSubject = 0x9c9f,
FlashpixVersion = 0xa000,
ColorSpace = 0xa001,
ExifImageWidth = 0xa002,
ExifImageLength = 0xa003,
RelatedSoundFile = 0xa004,
InteropOffset = 0xa005,
FlashEnergy2 = 0xa20b,
SpatialFrequencyResponse2 = 0xa20c,
Noise2 = 0xa20d,
FocalPlaneXResolution2 = 0xa20e,
FocalPlaneYResolution2 = 0xa20f,
FocalPlaneResolutionUnit2 = 0xa210,
ImageNumber2 = 0xa211,
SecurityClassification2 = 0xa212,
ImageHistory2 = 0xa213,
SubjectLocation2 = 0xa214,
ExposureIndex2 = 0xa215,
TIFF_EPStandardID2 = 0xa216,
SensingMethod2 = 0xa217,
FileSource = 0xa300,
SceneType = 0xa301,
CFAPattern = 0xa302,
CustomRendered = 0xa401,
ExposureMode = 0xa402,
WhiteBalance = 0xa403,
DigitalZoomRatio = 0xa404,
FocalLengthIn35mmFormat = 0xa405,
SceneCaptureType = 0xa406,
GainControl = 0xa407,
Contrast = 0xa408,
Saturation = 0xa409,
Sharpness = 0xa40a,
DeviceSettingDescription = 0xa40b,
SubjectDistanceRange = 0xa40c,
ImageUniqueID = 0xa420,
GDALMetadata = 0xa480,
GDALNoData = 0xa481,
Gamma = 0xa500,
FilmProductCode = 0xc350,
ImageSourceEK = 0xc351,
CaptureConditionsPAR = 0xc352,
CameraOwner = 0xc353,
SerialNumber = 0xc354,
UserSelectGroupTitle = 0xc355,
DealerIDNumber = 0xc356,
CaptureDeviceFID = 0xc357,
EnvelopeNumber = 0xc358,
FrameNumber = 0xc359,
FilmCategory = 0xc35a,
FilmGencode = 0xc35b,
ModelAndVersion = 0xc35c,
FilmSize = 0xc35d,
SBA_RGBShifts = 0xc35e,
SBAInputImageColorspace = 0xc35f,
SBAInputImageBitDepth = 0xc360,
SBAExposureRecord = 0xc361,
UserAdjSBA_RGBShifts = 0xc362,
ImageRotationStatus = 0xc363,
RollGuidElements = 0xc364,
MetadataNumber = 0xc365,
EditTagArray = 0xc366,
Magnification = 0xc367,
NativeXResolution = 0xc36c,
NativeYResolution = 0xc36d,
KodakEffectsIFD = 0xc36e,
KodakBordersIFD = 0xc36f,
NativeResolutionUnit = 0xc37a,
SourceImageDirectory = 0xc418,
SourceImageFileName = 0xc419,
SourceImageVolumeName = 0xc41a,
OceScanjobDesc = 0xc427,
OceApplicationSelector = 0xc428,
OceIDNumber = 0xc429,
OceImageLogic = 0xc42a,
Annotations = 0xc44f,
PrintQuality = 0xc46c,
ImagePrintStatus = 0xc46e,
PrintIM = 0xc4a5,
DNGVersion = 0xc612,
DNGBackwardVersion = 0xc613,
UniqueCameraModel = 0xc614,
LocalizedCameraModel = 0xc615,
CFAPlaneColor = 0xc616,
CFALayout = 0xc617,
LinearizationTable = 0xc618,
BlackLevelRepeatDim = 0xc619,
BlackLevel = 0xc61a,
BlackLevelDeltaH = 0xc61b,
BlackLevelDeltaV = 0xc61c,
WhiteLevel = 0xc61d,
DefaultScale = 0xc61e,
DefaultCropOrigin = 0xc61f,
DefaultCropSize = 0xc620,
ColorMatrix1 = 0xc621,
ColorMatrix2 = 0xc622,
CameraCalibration1 = 0xc623,
CameraCalibration2 = 0xc624,
ReductionMatrix1 = 0xc625,
ReductionMatrix2 = 0xc626,
AnalogBalance = 0xc627,
AsShotNeutral = 0xc628,
AsShotWhiteXY = 0xc629,
BaselineExposure = 0xc62a,
BaselineNoise = 0xc62b,
BaselineSharpness = 0xc62c,
BayerGreenSplit = 0xc62d,
LinearResponseLimit = 0xc62e,
DNGCameraSerialNumber = 0xc62f,
DNGLensInfo = 0xc630,
ChromaBlurRadius = 0xc631,
AntiAliasStrength = 0xc632,
ShadowScale = 0xc633,
DNGPrivateData = 0xc634,
MakerNoteSafety = 0xc635,
CalibrationIlluminant1 = 0xc65a,
CalibrationIlluminant2 = 0xc65b,
BestQualityScale = 0xc65c,
AliasLayerMetadata = 0xc660,
OwnerName = 0xfde8,
SerialNumber2 = 0xfde9,
Lens = 0xfdea,
RawFile = 0xfe4c,
Converter = 0xfe4d,
WhiteBalance2 = 0xfe4e,
Exposure = 0xfe51,
Shadows = 0xfe52,
Brightness = 0xfe53,
Contrast2 = 0xfe54,
Saturation2 = 0xfe55,
Sharpness2 = 0xfe56,
Smoothness = 0xfe57,
MoireFilter = 0xfe58,
} ExifTag;
enum <WORD> GeoTag {
GPSVersionID,
GPSLatitudeRef,
GPSLatitude,
GPSLongitudeRef,
GPSLongitude,
GPSAltitudeRef,
GPSAltitude,
GPSTimeStamp,
GPSSatellites,
GPSStatus,
GPSMeasureMode,
GPSDOP,
GPSSpeedRef,
GPSSpeed,
GPSTrackRef,
GPSTrack,
GPSImgDirectionRef,
GPSImgDirection,
GPSMapDatum,
GPSDestLatitudeRef,
GPSDestLatitude,
GPSDestLongitudeRef,
GPSDestLongitude,
GPSDestBearingRef,
GPSDestBearing,
GPSDestDistanceRef,
GPSDestDistance,
GPSProcessingMehotd,
GPSAreaInformation,
GPSDateStamp,
GPSDifferential,
};
// ------------------------------------------------------------
// Casio tag
typedef enum <WORD> tagCasioTag2 {
PreviewThumbnailDimensions = 0x0002,//Numeric 2 values - x,y dimensions in pixels
PreviewThumbnailSize = 0x0003,//Numeric Size in bytes
PreviewThumbnailOffset = 0x0004,//Numeric Offset of Preview Thumbnail
CSQualityMode = 0x0008,//Numeric Lookup 1 = Fine 2 = Super Fine
CsImageSize = 0x0009,//Numeric Lookup 0 = 640 x 480 pixels 4 = 1600 x 1200 pixels 5 = 2048 x 1536 pixels 20 = 2288 x 1712 pixels 21 = 2592 x 1944 pixels 22 = 2304 x 1728 pixels 36 = 3008 x 2008 pixels
CSFocusMode = 0x000D,//Numeric Lookup 0 = Normal 1 = Macro
CsIsoSensitivity = 0x0014,//Numeric Lookup 3 = 50 4 = 64 6 = 100 9 = 200
CsWhiteBalance = 0x0019,//Numeric Lookup 0 = Auto 1 = Daylight 2 = Shade 3 = Tungsten 4 = Fluorescent 5 = Manual
CsFocalLength = 0x001D,//Numeric Units are tenths of a millimetre
CsSaturation = 0x001F,//Numeric Lookup 0 = -1 1 = Normal 2 = +1
CsContrast = 0x0020,//Numeric Lookup 0 = -1 1 = Normal 2 = +1
CsSharpness = 0x0021,//Numeric Lookup 0 = -1 1 = Normal 2 = +1
CsPrintImageMatchingInfo = 0x0E00,//PIM See Print Image Matching for specification
CasioPreviewThumbnail = 0x2000,//Numeric Alternate thumbnail offset
CsWhiteBalanceBias = 0x2011,//Numeric
CsFlashMode = 0x2012,//Numeric Lookup 12 = Flash 0 = Manual 1 = Auto? 4 = Flash?
CsObjectDistance = 0x2022,//Numeric Units are millimetres
CsFlashDistance = 0x2034,//Numeric 0 = Off
CsRecordMode = 0x3000,//Numeric Lookup 2 = Normal Mode
CsSelfTimer = 0x3001,//Numeric Lookup 1 = Off?
CsQuality = 0x3002,//Numeric Lookup 3 = Fine
CsMeteringMode2 = 0x3003,//Numeric Lookup 1 = Fixation 6 = Multi-Area Auto Focus
CsTimeZone = 0x3006,//String
CsBestshotMode = 0x3007,//Numeric Lookup 0 = Off 1 = On?
CsCCDISOSensitivity = 0x3014,//Numeric
CsColourMode = 0x3015,//Numeric Lookup 0 = Off
CsEnhancement = 0x3016,//Numeric Lookup 0 = Off
CsFilter = 0x3017,//Numeric Lookup 0 = Off
} CasioTag2;
// ------------------------------------------------------------
// Canon CIFF
typedef uint32 DC_UINT32;
typedef int32 DC_SINT32;
typedef float DC_FLOAT32;
typedef struct tgCifDirEntry {
uint16 storage_method : 2; // 00 in heap, 01 in entry
uint16 data_type : 3;
uint16 id_code : 11 <format=hex>;
if (storage_method == kStg_InHeapSpace) {
DWORD sData; // Data Size (Bytes)
DWORD oData; // Data Offset
} else {
switch (data_type << 11 | id_code) {
case kTC_ImageFormat:
DC_UINT32 fileFormat;
DC_FLOAT32 targetCompressionRatio;
break;
default:
byte data[8];
break;
}
}
} CifDirEntry <read=ReadCifDirEntry>;
enum CIFFTagStg {
kStg_InHeapSpace,
kStg_InRecordEntry,
kStg_reversed2,
kStg_reversed3,
};
enum CIFFTagDataType {
kDT_BYTE = 0x0000,
kDT_ASCII = 0x0800,
kDT_WORD = 0x1000,
kDT_DWORD = 0x1800,
kDT_BYTE2 = 0x2000,
kDT_HeapTypeProperty1 = 0x2800,
kDT_HeapTypeProperty2 = 0x3000,
};
enum <uint16> CIFFTagType {
kTC_Null = 0,
kTC_Free,
kTC_ExFree,
kTC_Description = 0x0805,//kDT_ASCII | 0x0005,
kTC_ModelName = 0x080a,//kDT_ASCII | 0x000a,
kTC_FirmwareVersion = 0x080b,//kDT_ASCII | 0x000b,
kTC_ComponentVersion = 0x080c,//kDT_ASCII | 0x000c,
kTC_ROMOperationMode = 0x080d,//kDT_ASCII | 0x000d,
kTC_OwnerName = 0x0810,//kDT_ASCII | 0x0010,
kTC_ImageFileName = 0x0816,//kDT_ASCII | 0x0016,
kTC_ThumbnailFileName = 0x0817,//kDT_ASCII | 0x0017,
kTC_TargetImageType = 0x100a,//kDT_WORD | 0x000a,
kTC_SR_ReleaseMethod = 0x1010,//kDT_WORD | 0x0010,
kTC_SR_ReleaseTiming = 0x1011,//kDT_WORD | 0x0011,
kTC_ReleaseSetting = 0x1016,//kDT_WORD | 0x0016,
kTC_BodySensitivity = 0x101c,//kDT_WORD | 0x001c,
kTC_ImageFormat = 0x1803,//kDT_DWORD | 0x0003,
kTC_RecordID = 0x1804,//kDT_DWORD | 0x0004,
kTC_SelfTimerTime = 0x1806,//kDT_DWORD | 0x0006,
kTC_SR_TargetDistanceSetting = 0x1807,//kDT_DWORD | 0x0007,
kTC_BodyID = 0x180b,//kDT_DWORD | 0x000b,
kTC_CapturedTime = 0x180e,//kDT_DWORD | 0x000e,
kTC_ImageSpec = 0x1810,//kDT_DWORD | 0x0010,
kTC_SR_EF = 0x1813,//kDT_DWORD | 0x0013,
kTC_MI_EV = 0x1814,//kDT_DWORD | 0x0014,
kTC_SerialNumber = 0x1817,//kDT_DWORD | 0x0017,
kTC_CameraObject = 0x2807,//0x0007 | kDT_HeapTypeProperty1,
kTC_ShootingRecord = 0x3002,//0x0002 | kDT_HeapTypeProperty2,
kTC_MeasuredInfo = 0x3003,//0x0003 | kDT_HeapTypeProperty2,
kTC_CameraSpecification = 0x3004,//0x0004 | kDT_HeapTypeProperty2,
};
string ReadCifDirEntry(CifDirEntry &e)
{
local string s;
local uint16 tc = e.data_type << 11 | e.id_code;
local CIFFTagType x = (CIFFTagType) tc;
local CIFFTagStg stg = (CIFFTagStg)e.storage_method;
local CIFFTagDataType dt = (CIFFTagDataType)(e.data_type << 11);
if (EnumToString(x) != "") {
SPrintf(s, "%s, %s",
EnumToString(stg),
EnumToString(x));
} else {
SPrintf(s, "%s, %s, 0x%x",
EnumToString(stg),
EnumToString(dt),
e.id_code);
}
return s;
}
typedef struct tgCDir {
ChangeColor(0);
//Printf("off %#Lx doff %#Lx dsz %#Lx\n",cifOffset , cDirOffset ,cDirSize);
local quad myOffset = cDirOffset;
local DWORD S = ReadInt(myOffset + cDirSize - 4);
FSeek(cDirOffset + S);
//Printf("S @ %#x = %#x FTell %#Lx",S,myOffset + cDirSize - 4,FTell());
WORD nDirEntry;
//Printf(" nEntry %#x\n",nDirEntry);
ChangeColor(0);
CifDirEntry dirEntries[nDirEntry]<optimize=false>;
DWORD szValues; // = S
local int i;
for(i=0;i<nDirEntry;i++) {
//Printf("%d. Entry %#x = [ %#x %#x %#x]\n",i,dirEntries[i].Tag,dirEntries[i].Tag & 0xC000,dirEntries[i].Tag & 0x3800,dirEntries[i].Tag & 0x07FF);
if (dirEntries[i].storage_method == kStg_InHeapSpace) {
// Values are stored at a different location
FSeek(myOffset + dirEntries[i].oData);
ChangeColor(0);
//Printf("%d size %#x offset %#x clrIdx = [%d %d]\n",i,dirEntries[i].sData,dirEntries[i].oData,colorSelect,colorId);
switch(dirEntries[i].data_type << 11 | dirEntries[i].id_code) {
case kTC_ImageSpec:
struct {
DC_UINT32 imageWidth;
DC_UINT32 imageHeight;
DC_FLOAT32 pixelAspectRatio;
DC_SINT32 rotationAngle;
DC_UINT32 componentBitDepth;
DC_UINT32 colorBitDepth;
DC_UINT32 colorBW;
} DC_IMAGESPEC;
break;
default:
switch(dirEntries[i].data_type << 11) {
case kDT_BYTE:
struct {
byte bData[dirEntries[i].sData];
} strBytes;
break;
case kDT_ASCII:
struct {
char sData[dirEntries[i].sData];
} strStrings;
break;
case kDT_WORD:
struct {
WORD wData[dirEntries[i].sData>>1];
} str2Bytes;
break;
case kDT_DWORD:
union {
DWORD dwData[dirEntries[i].sData>>2];
DWORD flData[dirEntries[i].sData>>2];
} str4Bytes;
break;
case kDT_HeapTypeProperty1:
case kDT_HeapTypeProperty2:
cDirOffset = dirEntries[i].oData + myOffset;
cDirSize = dirEntries[i].sData;
struct CDIR subDir;
break;
default:
struct {
char uData[dirEntries[i].sData];
} strUnknown;
break;
}
break;
}
}
//else value is samaller than 8 byte so it is stored in sData and oData of CifDirEntry struct
}
} CDIR;
// ------------------------------------------------------------
// JPEG APPx segments
const local int dataFormatLength[13] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
typedef enum <WORD> tagDataFormat {
uByte = 1,
ascString,
uShort,
uLong,
uRatio,
sByte,
undefined = 7,
sShort,
sLong = 9,
sRatio,
sFloat,
dFloat,
} DataFormat;
typedef struct tgDIRENTRY {
ChangeColor(0);
switch (Stack_top(stack_IFD_dirtype)) {
case IFD_TYPE_EXIF:
ExifTag tagNumber;
break;
case IFD_TYPE_GEOTAG:
GeoTag tagNumber;
break;
case IFD_TYPE_CASIO_QV_R62:
CasioTag2 tagNumber;
break;
}
DataFormat dataFormat;
DWORD nComponent;
local int j = 0;
local int length = -1;
if (1 <= dataFormat && dataFormat < 13)
length = dataFormatLength[dataFormat] * nComponent;
else {
//Warning("unknown dataFormat = %x", dataFormat);
}
if (1 <= dataFormat && dataFormat < 13 && 0 <= length && length <= 4) {
switch (tagNumber) {
case ExposureProgram:
enum <short> {
EP_Not_defined,
EP_Manual,
EP_Normal_program,
EP_Aperture_priority,
EP_Shutter_priority,
EP_Creative_program,
EP_Action_program,
EP_Portrait_mode,
EP_Landscape_mode,
} ExposureProgram;
break;
case MeteringMode:
enum <short> {
MM_unknown,
MM_Average,
MM_CenterWeightedAverage,
MM_Spot,
MM_MultiSpot,
MM_Pattern,
MM_Partial,
MM_other = 255,
} MeteringMode;
break;
case LightSource:
enum <short> {
LS_unknown,
LS_Daylight,
LS_Fluorescent,
LS_Tungsten,
LS_Flash,
LS_Fine_weather = 9,
LS_Cloudy_weather,
LS_Shade,
LS_Daylight_fluorescent,
LS_Day_white_fluorescent,
LS_Cool_white_fluorescent,
LS_White_fluorescent,
LS_Standard_light_A,
LS_Standard_light_B,
LS_Standard_light_C,
LS_D55,
LS_D65,
LS_D75,
LS_D50,
LS_ISO_studio_tungsten,
LS_other_light_scoure = 255,
} LightSource;
break;
case Flash:
short unused : 9;
short red_eye_mode : 1;
short flash_function : 1;
short flash_mode : 2;
short flash_return : 2;
short flash_fired : 1;
break;
case ExposureMode:
enum <short> {
EM_Auto_exposure,
EM_Manual_exposure,
EM_Auto_bracket,
} ExposureMode;
break;
case WhiteBalance:
enum <short> {
WB_Auto_white_balance,
WB_Manual_white_balance,
} WhiteBalance;
break;
case SceneCaptureType:
enum <short> {
SCT_Standard,
SCT_Landscape,
SCT_Portrait,
SCT_Night_scene,
} SceneCaptureType;
break;
case SubjectDistanceRange:
enum <short> {
SDR_unknown,
SDR_Macro,
SDR_Close_view,
SDR_Distant_view,
} SubjectDistanceRange;
break;
default:
switch (dataFormat) {
case uByte:
struct {
uchar oneByteData[nComponent];
} strAscii;
break;
case ascString:
struct StrAscii1 {
char oneByteData[nComponent];
} strAscii <read=ReadAscString1>;
break;
case undefined:
struct {
uchar oneByteData[nComponent];
} strAscii;
break;
case uShort:
for (j = 0; j < nComponent; j++)
ushort usValue;
break;
case uLong:
if (nComponent == 1)
ulong ulValue;
break;
case sByte:
struct {
char sBValue[nComponent];
} strSByte;
break;
case sShort:
struct {
short sisValue[nComponent];
} strSShort;
break;
case sLong:
if (nComponent == 1)
ulong siLValue;
break;
case sFloat:
if (nComponent == 1)
float flValue;
break;
}
break;
}
if (length != 4)
uchar padding[4 - length];
} else {
DWORD offsetData;
}
} DIRENTRY<read=ReadDirEntry>;
string ReadDirEntry(DIRENTRY &entry) {
local char no[50];
SPrintf(no,"Tag# = 0x%x (%s)",entry.tagNumber, EnumToString(entry.tagNumber));
return no;
}
typedef struct tgIFD {
WORD nDirEntry;
DIRENTRY dirEntry[nDirEntry]<optimize=false>;
DWORD nextIFDoffset;
local int i = 0;
for(i=0;i<nDirEntry;i++) {
ChangeColor(0);
switch(dirEntry[i].tagNumber) {
case Make:
ReadBytes(CameraMake,offset + dirEntry[i].offsetData,dirEntry[i].nComponent);
Printf("Maker: %s\n",CameraMake);
break;
case Model:
ReadBytes(CameraModel,offset + dirEntry[i].offsetData,dirEntry[i].nComponent);
Printf("Model: %s\n",CameraModel);
break;
}
if (!(1 <= dirEntry[i].dataFormat && dirEntry[i].dataFormat < 13))
continue;
if (dataFormatLength[dirEntry[i].dataFormat] * dirEntry[i].nComponent <= 4) {
continue;
}
FSeek(offset + dirEntry[i].offsetData);
switch(dirEntry[i].tagNumber) {
default:
switch(dirEntry[i].dataFormat) {
case ascString:
struct StrAscii {
char oneByteData[dirEntry[i].nComponent];
} strAscii <read=ReadAscString>;
break;
case undefined:
struct {
uchar oneByteData[dirEntry[i].nComponent];
} strAscii;
break;
case uShort:
struct {
ushort usValue[dirEntry[i].nComponent];
} strUShort;
break;
case uLong:
struct {
ulong ulValue[dirEntry[i].nComponent];
} strULong;
break;
case uRatio:
struct URatio {
struct {
DWORD num;
DWORD den;
} uRValue[dirEntry[i].nComponent];
} strURatio <read=ReadURatio>;
break;
case sByte:
struct {
char sBValue[dirEntry[i].nComponent];
} strSByte;
break;
case sShort:
struct {
short sisValue[dirEntry[i].nComponent];
} strSShort;
break;
case sLong:
struct {
ulong siLValue[dirEntry[i].nComponent];
} strSLong;
break;
case sRatio:
struct {
struct {
int num;
int den;
} siRValue[dirEntry[i].nComponent];
} strSRatio;
break;
case sFloat:
struct {
float flValue[dirEntry[i].nComponent];
} strsFloat;
break;
case dFloat:
struct {
double dFValue[dirEntry[i].nComponent];
} strdFloat;
break;
}
}
}
for(i=0;i<nDirEntry;i++) {
ChangeColor(0);
switch(dirEntry[i].tagNumber) {
case ExifOffset:
FSeek(offset + dirEntry[i].ulValue);
Stack_push(stack_IFD_dirtype, IFD_TYPE_EXIF);
struct IFD subDir;
Stack_pop(stack_IFD_dirtype);
break;
case GPSInfo:
FSeek(offset + dirEntry[i].ulValue);
Stack_push(stack_IFD_dirtype, IFD_TYPE_GEOTAG);
struct IFD subDir;
Stack_pop(stack_IFD_dirtype);
break;
case InteropOffset:
FSeek(offset + dirEntry[i].ulValue);
Stack_push(stack_IFD_dirtype, IFD_TYPE_EXIF);
struct IFD subDir;
Stack_pop(stack_IFD_dirtype);
break;
case MakerNote:
if(!Strncmp("CASIO COMPUTER CO.,LTD",CameraMake,22) &&
!Strncmp("QV-R62",CameraModel,6)) {
FSeek(offset + dirEntry[i].ulValue);
struct {
char Header[6];
Stack_push(stack_IFD_dirtype, IFD_TYPE_CASIO_QV_R62);
struct IFD CasioIFD;
Stack_pop(stack_IFD_dirtype);
} CasioMake;
}
break;
case CasioPreviewThumbnail:
FSeek(offset + dirEntry[i].ulValue);
Printf("Casio Thumbnail Offset = %#Lx\n",offset + dirEntry[i].ulValue);
local quad JpegFileEnd2 = JpegFileEnd;
JpegFileEnd = FTell() + dirEntry[i].nComponent;
struct JPGFILE CasioMakerThumbnail;
JpegFileEnd = JpegFileEnd2;
break;
}
}
} IFD;
string ReadAscString1(StrAscii1 &s)
{
return s.oneByteData;
}
string ReadAscString(StrAscii &s)
{
return s.oneByteData;
}
string ReadURatio(URatio &ur)
{
local int i;
local string s;
local string result = "";
for (i = 0; exists(ur.uRValue[i]); i++) {
SPrintf(s, "%d/%d", ur.uRValue[i].num, ur.uRValue[i].den);
result += s + " ";
}
return result;
}
typedef struct tagApp0 {
M_ID marker;
WORD szSection;
if (ReadStringN(FTell(), 5) == "JFIF") {
// JFIF Main
char App0Type[5];
short versionHigh:8;
short versionLow:8;
ubyte units;
WORD Xdensity;
WORD Ydensity;
ubyte xThumbnail;
ubyte yThumbnail;
if (xThumbnail != 0 && yThumbnail != 0) {
struct {
uchar r, g, b;
} rgb[(ushort)xThumbnail * yThumbnail];
}
} else if(ReadStringN(FTell(), 5) == "JFXX") {
// JFIF Extension
char App0Type[5];
byte extension_code <format=hex>;
switch (extension_code) {
case 0x10:
local quad JpegFileEnd2 = JpegFileEnd;
JpegFileEnd = FTell() + szSection - 8;
struct JPGFILE thumbnail;
JpegFileEnd = JpegFileEnd2;
break;
case 0x11:
ubyte xThumbnail;
ubyte yThumbnail;
struct {
uchar r, g, b;
} palette[256];
uchar pixel[szSection - 8];
break;
case 0x13:
ubyte xThumbnail;
ubyte yThumbnail;
struct {
uchar r, g, b;
} pixel[(ushort)xThumbnail * yThumbnail];
break;
default:
//Warning("Unknown JFXX");
char unknown[szSection - 8];
}
} else if((ReadStringN(FTell(), 2) == "II" || ReadStringN(FTell(), 2) == "MM")
&& ReadStringN(FTell() + 6, 8) == "HEAPJPGM") {
// Canon CIFF
local quad cDirSize = 0;
local quad cDirOffset = 0;
local quad cifOffset = FTell();
//CIFF Header
char ByteOrder[2];
if(!Strncmp(ByteOrder,"II",2)) LittleEndian();
DWORD HeaderLength;
char type[4]; // "HEAP"
char subtype[4]; // "JPGM"
//Ciff Directory
cDirOffset = HeaderLength + cifOffset;
cDirSize = szSection - 2 - HeaderLength;
CDIR APP0_Ciff;
BigEndian();
FSeek(cifOffset + szSection - 2);
}
else {
//Warning("Unknown APP0");
char unknown[szSection - 2];
}
} APP0;
typedef struct tgAPP1 {
M_ID marker;
WORD szSection;
if (ReadStringN(FTell(), 5) == "Exif") {
char EXIF[6];
local quad offset = FTell();
byte align[2];
if(align[0]=='I') { LittleEndian(); }
WORD tagMark; // 0x002a
DWORD offsetFirstIFD;
if(offsetFirstIFD!=8)
FSeek(offset + offsetFirstIFD);
ChangeColor(0);
Stack_push(stack_IFD_dirtype, IFD_TYPE_EXIF);
IFD ifdMainImage;
Stack_pop(stack_IFD_dirtype);
if(ifdMainImage.nextIFDoffset) {
FSeek(offset + ifdMainImage.nextIFDoffset);
ChangeColor(0);
Stack_push(stack_IFD_dirtype, IFD_TYPE_EXIF);
IFD ifdThumbnailImage;
Stack_pop(stack_IFD_dirtype);
local int i = 0;
local int thumbOffset = 0;
local int thumbLength = 0;
local int compression = 10;
for(i;i<ifdThumbnailImage.nDirEntry;i++) {
switch(ifdThumbnailImage.dirEntry[i].tagNumber) {
case Compression:
compression = ifdThumbnailImage.dirEntry[i].usValue;
break;
case ThumbnailOffset:
case StripOffsets:
thumbOffset = ifdThumbnailImage.dirEntry[i].ulValue;
break;
case ThumbnailLength:
case StripByteCounts:
thumbLength = ifdThumbnailImage.dirEntry[i].ulValue;
break;
}
}
if(thumbLength && thumbOffset) {
FSeek(offset + thumbOffset);
Printf("Thumbnail Offset = %#Lx\n",offset + thumbOffset);
if(compression == 6) {
local quad JpegFileEnd2 = JpegFileEnd;
JpegFileEnd = FTell() + thumbLength;
struct JPGFILE thumbnail;
JpegFileEnd = JpegFileEnd2;
}
else
char imageData[thumbLength];
}
}
FSeek(offset + szSection - 8);
if(align[0]=='I') { BigEndian(); }
} else if (ReadStringN(FTell(), 29) == "http://ns.adobe.com/xap/1.0/") {
// http://www.adobe.com/products/xmp/
char XAP[29];
char remain[szSection - 31];
} else {
//Warning("Unknown APP1");
char unknown[szSection - 2];
}
} APP1;
typedef struct tgAPP2 {
M_ID marker;
WORD szSection;
if (ReadStringN(FTell(), 5) == "FPXR") {
char FPXR[5];
uchar version;
char remain[szSection - 8];
//Warning("Unknown FPXR");
} else if (ReadStringN(FTell(), 12) == "ICC_PROFILE") {
char ICC_PROFILE[12];
uchar block_num;
uchar block_total;
char data[szSection - 16];
} else {
//Warning("Unknown APP2");
char unknown[szSection - 2];
}
} APP2;
typedef struct tagAPP12 {
M_ID marker;
WORD szSection;
if (ReadStringN(FTell(), 5) == "Ducky") {
// refer to ExifTool APP12.pm
char Ducky[5];
local WORD s = szSection;
while (s > 0) {
struct {
enum <uint16> {
DK_End,
DK_Quality,
DK_Comment,
DK_Copyright,
} tag;
if (tag == DK_End)
break;
uint16 len;
switch (tag) {
case DK_End:
break;
case DK_Quality:
uint32 value;
break;
case DK_Comment:
uint32 count;
char comment[len - 4];
break;
case DK_Copyright:
uint32 count;
char comment[len - 4];
break;
default:
char unknown[len];
break;
}
} entry;
if (entry.tag == DK_End)
break;
s -= sizeof(entry);
}
} else {
//Warning("Unknown APP12");
char unknown[szSection - 2];
}
} APP12;
typedef struct tagAPP13 {
M_ID marker;
WORD szSection;
if (ReadStringN(FTell(), 14) == "Photoshop 3.0") {
// refer to ExifTool Photoshop.pm
char photoshop30[14];
local int remainsize = szSection - 16;
while (remainsize > 0) {
struct {
char type[4];
if (type == "8BIM") {
} else if (type == "PHUT" || type == "DCSR" || type == "AgHg") {
} else {
char unknown[remainsize - 4];
break;
}
enum <uint16> {
PS_IPTCData = 0x0404,
PS_JPEG_Quality = 0x0406,
PS_PhotoshopBGRThumbnail = 0x0409,
PS_CopyrightFlag = 0x040a,
PS_URL = 0x040b,
PS_PhotoshopThumbnail = 0x040c,
PS_ICC_Profile = 0x040f,
PS_GlobalAltitude = 0x0419,
PS_EXIFInfo = 0x0422,
PS_XMP = 0x0424,
PS_IPTCDigest = 0x0425,
PS_ClippingPathName = 0x0bb7,
} tag;
uchar namelen;
if (namelen)
char name[namelen];
if (namelen % 2 != 1)
char padding;
uint32 size;
if (size)
char data[size];
if (size % 2 != 0)
char padding;
} block;
remainsize -= sizeof(block);
}
} else if (ReadStringN(FTell(), 9) == "Adobe_CM") {
char adobe_cm[9];
uchar AdobeCMType;
if (szSection != 12)
char unknown[szSection - 12];
} else {
//Warning("Unknown APP13");
char unknown[szSection - 2];
}
} APP13;
typedef struct tagAPP14 {
M_ID marker;
WORD szSection;
if (ReadStringN(FTell(), 5) == "Adobe") {
// http://partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf
char adobe[5];
uint16 version;
uint16 flag0;
uint16 flag1;
uchar color_transform_code;
if (FTell() < szSection + startof(szSection)) char unknown[szSection + startof(szSection) - FTell()];
} else {
//Warning("Unknown APP14");
char unknown[szSection - 2];
}
} APP14;
// ------------------------------------------------------------
// JPEG segments
typedef struct tagSOS {
M_ID marker;
WORD szSection;
ubyte nr_comp;
ChangeColor(0);
struct COMPSOS {
ubyte AC:4;
ubyte DC:4;
} comp[nr_comp];
uchar Ss;
uchar Se;
uchar Ah : 4;
uchar Al : 4;
} SOS;
typedef struct tagUNK {
M_ID UnknownMarker;
//Warning("Unknown Section 0x%08x %s", UnknownMarker, EnumToString(UnknownMarker));
WORD szSection;
if (FTell() + szSection - 2 >= JpegFileEnd) {
Warning("unknown section length pass the end of jpeg file");
ubyte unknown[JpegFileEnd - FTell()];
} else {
ubyte unknown[szSection-2];
}
} UNKNOWN;
typedef struct tagDHT {
M_ID marker;
WORD szSection;
local WORD huffsz = szSection - 2;
while(huffsz > 0) {
ChangeColor(0);
struct Huffmann_Table {
ubyte htInfo;
ubyte length[16];
local int sumLen = 0;
local int i = 0;
for(i;i<16;i++) {
sumLen += length[i];
}
ubyte HTV[sumLen];
} huff_table;
huffsz -= sizeof(huff_table);
}
} DHT;
typedef struct tagDQT {
M_ID marker;
WORD szSection;
local WORD qtsz = szSection - 2;
while(qtsz > 0) {
ChangeColor(0);
struct QuanTable {
uchar Pq : 4;
uchar Tq : 4;
if (Pq == 0)
byte qTable[64];
else
uint16 qTable[64];
} qtable;
qtsz -= sizeof(qtable);
}
} DQT;
typedef struct tagDRI {
M_ID marker;
WORD szSection;
WORD Ri;
} DRI;
typedef struct tagDHP {
M_ID marker;
WORD szSection;
uchar P;
uint16 Y;
uint16 X;
uchar Nf;
struct {
uchar id;
uchar h_factor : 4;
uchar v_factor : 4;
uchar Tq;
} component_param[Nf];
} DHP;
typedef struct tgSOFx {
M_ID marker;
WORD szSection;
ubyte precision;
WORD Y_image;
WORD X_image;
ubyte nr_comp;
ChangeColor(0);
struct COMPS {
ubyte compId;
ubyte Horz:4;
ubyte Vert:4;
ubyte compNr;
} comp[nr_comp];
} SOFx;
typedef struct tagCOMMENT {
M_ID CommentMarker;
WORD szSection;
char comment[szSection-2];
local char comments[szSection-1] = {0};
local int i = 0;
Memcpy(comments,comment,szSection-2);
for(i=0;i<szSection-1;i++) {
if(comments[i]==0) comments[i] = 'x';
}
comments[szSection-2] = 0;
Printf("\nCOMMENT :\n%s\n\n",comments);
} COMMENT<read=ReadComment>;
typedef struct tagJPGLS {
M_ID marker;
WORD szSection;
uchar precision <comment="bits per sample">;
WORD Y_numlines;
WORD X_numcols;
uchar Nf <comment="number of components in frame">;
uchar C_compID;
uchar sub_sampling;
uchar Tq <comment="always 0">;
if (11 < szSection)
uchar uknown[szSection - 11];
} JPGLS;
string ReadComment( COMMENT &com )
{
return com.comment;
}
JpegFileEnd = FileSize();
// ------------------------------------------------------------
// JPEG file
SetBackColor(jetMap[0]);
typedef struct tgJPGFile {
local int was_bigendian = IsBigEndian();
BigEndian();
local WORD NextMarker;
local quad fpos2;
local byte bEOI = 0;
while(FTell() < JpegFileEnd && !bEOI) {
// skip optional 0xff before marker
while (ReadUShort(FTell()) == 0xffff) FSkip(1);
NextMarker = ReadUShort(FTell());
switch(NextMarker) {
case M_SOI:
M_ID SOIMarker;
Printf("Start of Image Marker\n");
break;
case M_SOS:
SOS scanStart;
Printf("Start of Scan Marker\n");
NextMarker = ReadUShort(JpegFileEnd - 2);
fpos2 = 0;
while(NextMarker != M_EOI) {
NextMarker = ReadUShort(JpegFileEnd - 2 - (++fpos2));
}
char scanData[JpegFileEnd - FTell() - 2 - fpos2];
ChangeColor(1);
M_ID EOIMarker;
Printf("End of File Image\n");
if(fpos2) char unknownPadding[fpos2];
bEOI = 1;
break;
case M_APP0:
APP0 app0;
break;
case M_DHT:
DHT dht;
break;
case M_DQT:
DQT dqt;
break;
case M_DRI:
DRI dri;
break;
case M_DHP:
DHP dhp;
break;
case M_SOF0:
SOFx sof0;
break;
case M_SOF1:
SOFx sof1;
break;
case M_SOF2:
SOFx sof2;
break;
case M_APP1:
APP1 app1;
break;
case M_APP2:
APP2 app2;
break;
case M_APP12:
APP12 app12;
break;
case M_APP13:
APP13 app13;
break;
case M_APP14:
APP14 app14;
break;
case M_COMM:
COMMENT comment;
break;
case M_JPGLS:
JPGLS jpgls;
break;
default:
UNKNOWN unknownSection;
break;
}
ChangeColor(!bEOI);
}
if (!was_bigendian)
LittleEndian();
} JPGFILE;
JPGFILE jpgfile;