Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F2751171
jpegmeta.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
26 KB
Referenced Files
None
Subscribers
None
jpegmeta.js
View Options
/**
* This is JsJpegMeta v1.0
* From: https://code.google.com/p/jsjpegmeta/downloads/list
* From: https://github.com/bennoleslie/jsjpegmeta/blob/v1.0.0/jpegmeta.js
*
* Ported to MediaWiki ResourceLoader by Bryan Tong Minh
* Changes:
* - Add closure.
* - Add this.JpegMeta assignment to expose it as global.
*/
(
function
()
{
/*
Copyright (c) 2009 Ben Leslie
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
/*
This JavaScript library is used to parse meta-data from files
with mime-type image/jpeg.
Include it with something like:
<script type="text/javascript" src="jpegmeta.js"></script>
This adds a single 'module' object called 'JpegMeta' to the global
namespace.
Public Functions
----------------
JpegMeta.parseNum - parse unsigned integers from binary data
JpegMeta.parseSnum - parse signed integers from binary data
Public Classes
--------------
JpegMeta.Rational - A rational number class
JpegMeta.JfifSegment
JpegMeta.ExifSegment
JpegMeta.JpegFile - Primary class for Javascript parsing
*/
var
JpegMeta
=
{};
// MediaWiki: Expose as global
this
.
JpegMeta
=
JpegMeta
;
/*
parse an unsigned number of size bytes at offset in some binary string data.
If endian
is "<" parse the data as little endian, if endian
is ">" parse as big-endian.
*/
JpegMeta
.
parseNum
=
function
parseNum
(
endian
,
data
,
offset
,
size
)
{
var
i
;
var
ret
;
var
big_endian
=
(
endian
===
">"
);
if
(
offset
===
undefined
)
offset
=
0
;
if
(
size
===
undefined
)
size
=
data
.
length
-
offset
;
for
(
big_endian
?
i
=
offset
:
i
=
offset
+
size
-
1
;
big_endian
?
i
<
offset
+
size
:
i
>=
offset
;
big_endian
?
i
++
:
i
--
)
{
ret
<<=
8
;
ret
+=
data
.
charCodeAt
(
i
);
}
return
ret
;
};
/*
parse an signed number of size bytes at offset in some binary string data.
If endian
is "<" parse the data as little endian, if endian
is ">" parse as big-endian.
*/
JpegMeta
.
parseSnum
=
function
parseSnum
(
endian
,
data
,
offset
,
size
)
{
var
i
;
var
ret
;
var
neg
;
var
big_endian
=
(
endian
===
">"
);
if
(
offset
===
undefined
)
offset
=
0
;
if
(
size
===
undefined
)
size
=
data
.
length
-
offset
;
for
(
big_endian
?
i
=
offset
:
i
=
offset
+
size
-
1
;
big_endian
?
i
<
offset
+
size
:
i
>=
offset
;
big_endian
?
i
++
:
i
--
)
{
if
(
neg
===
undefined
)
{
/* Negative if top bit is set */
neg
=
(
data
.
charCodeAt
(
i
)
&
0x80
)
===
0x80
;
}
ret
<<=
8
;
/* If it is negative we invert the bits */
ret
+=
neg
?
~
data
.
charCodeAt
(
i
)
&
0xff
:
data
.
charCodeAt
(
i
);
}
if
(
neg
)
{
/* If it is negative we do two's complement */
ret
+=
1
;
ret
*=
-
1
;
}
return
ret
;
};
/* Rational number class */
JpegMeta
.
Rational
=
function
Rational
(
num
,
den
)
{
this
.
num
=
num
;
this
.
den
=
den
||
1
;
return
this
;
};
/* Rational number methods */
JpegMeta
.
Rational
.
prototype
.
toString
=
function
toString
()
{
if
(
this
.
num
===
0
)
{
return
""
+
this
.
num
;
}
if
(
this
.
den
===
1
)
{
return
""
+
this
.
num
;
}
if
(
this
.
num
===
1
)
{
return
this
.
num
+
" / "
+
this
.
den
;
}
return
this
.
num
/
this
.
den
;
// + "/" + this.den;
};
JpegMeta
.
Rational
.
prototype
.
asFloat
=
function
asFloat
()
{
return
this
.
num
/
this
.
den
;
};
/* MetaGroup class */
JpegMeta
.
MetaGroup
=
function
MetaGroup
(
fieldName
,
description
)
{
this
.
fieldName
=
fieldName
;
this
.
description
=
description
;
this
.
metaProps
=
{};
return
this
;
};
JpegMeta
.
MetaGroup
.
prototype
.
_addProperty
=
function
_addProperty
(
fieldName
,
description
,
value
)
{
var
property
=
new
JpegMeta
.
MetaProp
(
fieldName
,
description
,
value
);
this
[
property
.
fieldName
]
=
property
;
this
.
metaProps
[
property
.
fieldName
]
=
property
;
};
JpegMeta
.
MetaGroup
.
prototype
.
toString
=
function
toString
()
{
return
"[MetaGroup "
+
this
.
description
+
"]"
;
};
/* MetaProp class */
JpegMeta
.
MetaProp
=
function
MetaProp
(
fieldName
,
description
,
value
)
{
this
.
fieldName
=
fieldName
;
this
.
description
=
description
;
this
.
value
=
value
;
return
this
;
};
JpegMeta
.
MetaProp
.
prototype
.
toString
=
function
toString
()
{
return
""
+
this
.
value
;
};
/* JpegFile class */
JpegMeta
.
JpegFile
=
function
JpegFile
(
binary_data
,
filename
)
{
/* Change this to EOI if we want to parse. */
var
break_segment
=
this
.
_SOS
;
this
.
metaGroups
=
{};
this
.
_binary_data
=
binary_data
;
this
.
filename
=
filename
;
/* Go through and parse. */
var
pos
=
0
;
var
pos_start_of_segment
=
0
;
var
delim
;
var
mark
;
var
_mark
;
var
segsize
;
var
headersize
;
var
mark_code
;
var
mark_fn
;
/* Check to see if this looks like a JPEG file */
if
(
this
.
_binary_data
.
slice
(
0
,
2
)
!==
this
.
_SOI_MARKER
)
{
throw
new
Error
(
"Doesn't look like a JPEG file. First two bytes are "
+
this
.
_binary_data
.
charCodeAt
(
0
)
+
","
+
this
.
_binary_data
.
charCodeAt
(
1
)
+
"."
);
}
pos
+=
2
;
while
(
pos
<
this
.
_binary_data
.
length
)
{
delim
=
this
.
_binary_data
.
charCodeAt
(
pos
++
);
mark
=
this
.
_binary_data
.
charCodeAt
(
pos
++
);
pos_start_of_segment
=
pos
;
if
(
delim
!=
this
.
_DELIM
)
{
break
;
}
if
(
mark
===
break_segment
)
{
break
;
}
headersize
=
JpegMeta
.
parseNum
(
">"
,
this
.
_binary_data
,
pos
,
2
);
/* Find the end */
pos
+=
headersize
;
while
(
pos
<
this
.
_binary_data
.
length
)
{
delim
=
this
.
_binary_data
.
charCodeAt
(
pos
++
);
if
(
delim
==
this
.
_DELIM
)
{
_mark
=
this
.
_binary_data
.
charCodeAt
(
pos
++
);
if
(
_mark
!=
0x0
)
{
pos
-=
2
;
break
;
}
}
}
segsize
=
pos
-
pos_start_of_segment
;
if
(
this
.
_markers
[
mark
])
{
mark_code
=
this
.
_markers
[
mark
][
0
];
mark_fn
=
this
.
_markers
[
mark
][
1
];
}
else
{
mark_code
=
"UNKN"
;
mark_fn
=
undefined
;
}
if
(
mark_fn
)
{
this
[
mark_fn
](
mark
,
pos_start_of_segment
+
2
);
}
}
if
(
this
.
general
===
undefined
)
{
throw
Error
(
"Invalid JPEG file."
);
}
return
this
;
};
this
.
JpegMeta
.
JpegFile
.
prototype
.
toString
=
function
()
{
return
"[JpegFile "
+
this
.
filename
+
" "
+
this
.
general
.
type
+
" "
+
this
.
general
.
pixelWidth
+
"x"
+
this
.
general
.
pixelHeight
+
" Depth: "
+
this
.
general
.
depth
+
"]"
;
};
/* Some useful constants */
this
.
JpegMeta
.
JpegFile
.
prototype
.
_SOI_MARKER
=
'\xff\xd8'
;
this
.
JpegMeta
.
JpegFile
.
prototype
.
_DELIM
=
0xff
;
this
.
JpegMeta
.
JpegFile
.
prototype
.
_EOI
=
0xd9
;
this
.
JpegMeta
.
JpegFile
.
prototype
.
_SOS
=
0xda
;
this
.
JpegMeta
.
JpegFile
.
prototype
.
_sofHandler
=
function
_sofHandler
(
mark
,
pos
)
{
if
(
this
.
general
!==
undefined
)
{
throw
Error
(
"Unexpected multiple-frame image"
);
}
this
.
_addMetaGroup
(
"general"
,
"General"
);
this
.
general
.
_addProperty
(
"depth"
,
"Depth"
,
JpegMeta
.
parseNum
(
">"
,
this
.
_binary_data
,
pos
,
1
));
this
.
general
.
_addProperty
(
"pixelHeight"
,
"Pixel Height"
,
JpegMeta
.
parseNum
(
">"
,
this
.
_binary_data
,
pos
+
1
,
2
));
this
.
general
.
_addProperty
(
"pixelWidth"
,
"Pixel Width"
,
JpegMeta
.
parseNum
(
">"
,
this
.
_binary_data
,
pos
+
3
,
2
));
this
.
general
.
_addProperty
(
"type"
,
"Type"
,
this
.
_markers
[
mark
][
2
]);
};
/* JFIF idents */
this
.
JpegMeta
.
JpegFile
.
prototype
.
_JFIF_IDENT
=
"JFIF\x00"
;
this
.
JpegMeta
.
JpegFile
.
prototype
.
_JFXX_IDENT
=
"JFXX\x00"
;
/* Exif idents */
this
.
JpegMeta
.
JpegFile
.
prototype
.
_EXIF_IDENT
=
"Exif\x00"
;
/* TIFF types */
this
.
JpegMeta
.
JpegFile
.
prototype
.
_types
=
{
/* The format is identifier : ["type name", type_size_in_bytes ] */
1
:
[
"BYTE"
,
1
],
2
:
[
"ASCII"
,
1
],
3
:
[
"SHORT"
,
2
],
4
:
[
"LONG"
,
4
],
5
:
[
"RATIONAL"
,
8
],
6
:
[
"SBYTE"
,
1
],
7
:
[
"UNDEFINED"
,
1
],
8
:
[
"SSHORT"
,
2
],
9
:
[
"SLONG"
,
4
],
10
:
[
"SRATIONAL"
,
8
],
11
:
[
"FLOAT"
,
4
],
12
:
[
"DOUBLE"
,
8
]
};
this
.
JpegMeta
.
JpegFile
.
prototype
.
_tifftags
=
{
/* A. Tags relating to image data structure */
256
:
[
"Image width"
,
"ImageWidth"
],
257
:
[
"Image height"
,
"ImageLength"
],
258
:
[
"Number of bits per component"
,
"BitsPerSample"
],
259
:
[
"Compression scheme"
,
"Compression"
,
{
1
:
"uncompressed"
,
6
:
"JPEG compression"
}],
262
:
[
"Pixel composition"
,
"PhotmetricInerpretation"
,
{
2
:
"RGB"
,
6
:
"YCbCr"
}],
274
:
[
"Orientation of image"
,
"Orientation"
,
/* FIXME: Check the mirror-image / reverse encoding and rotation */
{
1
:
"Normal"
,
2
:
"Reverse?"
,
3
:
"Upside-down"
,
4
:
"Upside-down Reverse"
,
5
:
"90 degree CW"
,
6
:
"90 degree CW reverse"
,
7
:
"90 degree CCW"
,
8
:
"90 degree CCW reverse"
}],
277
:
[
"Number of components"
,
"SamplesPerPixel"
],
284
:
[
"Image data arrangement"
,
"PlanarConfiguration"
,
{
1
:
"chunky format"
,
2
:
"planar format"
}],
530
:
[
"Subsampling ratio of Y to C"
,
"YCbCrSubSampling"
],
531
:
[
"Y and C positioning"
,
"YCbCrPositioning"
,
{
1
:
"centered"
,
2
:
"co-sited"
}],
282
:
[
"X Resolution"
,
"XResolution"
],
283
:
[
"Y Resolution"
,
"YResolution"
],
296
:
[
"Resolution Unit"
,
"ResolutionUnit"
,
{
2
:
"inches"
,
3
:
"centimeters"
}],
/* B. Tags realting to recording offset */
273
:
[
"Image data location"
,
"StripOffsets"
],
278
:
[
"Number of rows per strip"
,
"RowsPerStrip"
],
279
:
[
"Bytes per compressed strip"
,
"StripByteCounts"
],
513
:
[
"Offset to JPEG SOI"
,
"JPEGInterchangeFormat"
],
514
:
[
"Bytes of JPEG Data"
,
"JPEGInterchangeFormatLength"
],
/* C. Tags relating to image data characteristics */
301
:
[
"Transfer function"
,
"TransferFunction"
],
318
:
[
"White point chromaticity"
,
"WhitePoint"
],
319
:
[
"Chromaticities of primaries"
,
"PrimaryChromaticities"
],
529
:
[
"Color space transformation matrix coefficients"
,
"YCbCrCoefficients"
],
532
:
[
"Pair of black and white reference values"
,
"ReferenceBlackWhite"
],
/* D. Other tags */
306
:
[
"Date and time"
,
"DateTime"
],
270
:
[
"Image title"
,
"ImageDescription"
],
271
:
[
"Make"
,
"Make"
],
272
:
[
"Model"
,
"Model"
],
305
:
[
"Software"
,
"Software"
],
315
:
[
"Person who created the image"
,
"Artist"
],
316
:
[
"Host Computer"
,
"HostComputer"
],
33432
:
[
"Copyright holder"
,
"Copyright"
],
34665
:
[
"Exif tag"
,
"ExifIfdPointer"
],
34853
:
[
"GPS tag"
,
"GPSInfoIfdPointer"
]
};
this
.
JpegMeta
.
JpegFile
.
prototype
.
_exiftags
=
{
/* Tag Support Levels (2) - 0th IFX Exif Private Tags */
/* A. Tags Relating to Version */
36864
:
[
"Exif Version"
,
"ExifVersion"
],
40960
:
[
"FlashPix Version"
,
"FlashpixVersion"
],
/* B. Tag Relating to Image Data Characteristics */
40961
:
[
"Color Space"
,
"ColorSpace"
],
/* C. Tags Relating to Image Configuration */
37121
:
[
"Meaning of each component"
,
"ComponentsConfiguration"
],
37122
:
[
"Compressed Bits Per Pixel"
,
"CompressedBitsPerPixel"
],
40962
:
[
"Pixel X Dimension"
,
"PixelXDimension"
],
40963
:
[
"Pixel Y Dimension"
,
"PixelYDimension"
],
/* D. Tags Relating to User Information */
37500
:
[
"Manufacturer notes"
,
"MakerNote"
],
37510
:
[
"User comments"
,
"UserComment"
],
/* E. Tag Relating to Related File Information */
40964
:
[
"Related audio file"
,
"RelatedSoundFile"
],
/* F. Tags Relating to Date and Time */
36867
:
[
"Date Time Original"
,
"DateTimeOriginal"
],
36868
:
[
"Date Time Digitized"
,
"DateTimeDigitized"
],
37520
:
[
"DateTime subseconds"
,
"SubSecTime"
],
37521
:
[
"DateTimeOriginal subseconds"
,
"SubSecTimeOriginal"
],
37522
:
[
"DateTimeDigitized subseconds"
,
"SubSecTimeDigitized"
],
/* G. Tags Relating to Picture-Taking Conditions */
33434
:
[
"Exposure time"
,
"ExposureTime"
],
33437
:
[
"FNumber"
,
"FNumber"
],
34850
:
[
"Exposure program"
,
"ExposureProgram"
],
34852
:
[
"Spectral sensitivity"
,
"SpectralSensitivity"
],
34855
:
[
"ISO Speed Ratings"
,
"ISOSpeedRatings"
],
34856
:
[
"Optoelectric coefficient"
,
"OECF"
],
37377
:
[
"Shutter Speed"
,
"ShutterSpeedValue"
],
37378
:
[
"Aperture Value"
,
"ApertureValue"
],
37379
:
[
"Brightness"
,
"BrightnessValue"
],
37380
:
[
"Exposure Bias Value"
,
"ExposureBiasValue"
],
37381
:
[
"Max Aperture Value"
,
"MaxApertureValue"
],
37382
:
[
"Subject Distance"
,
"SubjectDistance"
],
37383
:
[
"Metering Mode"
,
"MeteringMode"
],
37384
:
[
"Light Source"
,
"LightSource"
],
37385
:
[
"Flash"
,
"Flash"
],
37386
:
[
"Focal Length"
,
"FocalLength"
],
37396
:
[
"Subject Area"
,
"SubjectArea"
],
41483
:
[
"Flash Energy"
,
"FlashEnergy"
],
41484
:
[
"Spatial Frequency Response"
,
"SpatialFrequencyResponse"
],
41486
:
[
"Focal Plane X Resolution"
,
"FocalPlaneXResolution"
],
41487
:
[
"Focal Plane Y Resolution"
,
"FocalPlaneYResolution"
],
41488
:
[
"Focal Plane Resolution Unit"
,
"FocalPlaneResolutionUnit"
],
41492
:
[
"Subject Location"
,
"SubjectLocation"
],
41493
:
[
"Exposure Index"
,
"ExposureIndex"
],
41495
:
[
"Sensing Method"
,
"SensingMethod"
],
41728
:
[
"File Source"
,
"FileSource"
],
41729
:
[
"Scene Type"
,
"SceneType"
],
41730
:
[
"CFA Pattern"
,
"CFAPattern"
],
41985
:
[
"Custom Rendered"
,
"CustomRendered"
],
41986
:
[
"Exposure Mode"
,
"Exposure Mode"
],
41987
:
[
"White Balance"
,
"WhiteBalance"
],
41988
:
[
"Digital Zoom Ratio"
,
"DigitalZoomRatio"
],
41990
:
[
"Scene Capture Type"
,
"SceneCaptureType"
],
41991
:
[
"Gain Control"
,
"GainControl"
],
41992
:
[
"Contrast"
,
"Contrast"
],
41993
:
[
"Saturation"
,
"Saturation"
],
41994
:
[
"Sharpness"
,
"Sharpness"
],
41995
:
[
"Device settings description"
,
"DeviceSettingDescription"
],
41996
:
[
"Subject distance range"
,
"SubjectDistanceRange"
],
/* H. Other Tags */
42016
:
[
"Unique image ID"
,
"ImageUniqueID"
],
40965
:
[
"Interoperability tag"
,
"InteroperabilityIFDPointer"
]
};
this
.
JpegMeta
.
JpegFile
.
prototype
.
_gpstags
=
{
/* A. Tags Relating to GPS */
0
:
[
"GPS tag version"
,
"GPSVersionID"
],
1
:
[
"North or South Latitude"
,
"GPSLatitudeRef"
],
2
:
[
"Latitude"
,
"GPSLatitude"
],
3
:
[
"East or West Longitude"
,
"GPSLongitudeRef"
],
4
:
[
"Longitude"
,
"GPSLongitude"
],
5
:
[
"Altitude reference"
,
"GPSAltitudeRef"
],
6
:
[
"Altitude"
,
"GPSAltitude"
],
7
:
[
"GPS time (atomic clock)"
,
"GPSTimeStamp"
],
8
:
[
"GPS satellites usedd for measurement"
,
"GPSSatellites"
],
9
:
[
"GPS receiver status"
,
"GPSStatus"
],
10
:
[
"GPS mesaurement mode"
,
"GPSMeasureMode"
],
11
:
[
"Measurement precision"
,
"GPSDOP"
],
12
:
[
"Speed unit"
,
"GPSSpeedRef"
],
13
:
[
"Speed of GPS receiver"
,
"GPSSpeed"
],
14
:
[
"Reference for direction of movement"
,
"GPSTrackRef"
],
15
:
[
"Direction of movement"
,
"GPSTrack"
],
16
:
[
"Reference for direction of image"
,
"GPSImgDirectionRef"
],
17
:
[
"Direction of image"
,
"GPSImgDirection"
],
18
:
[
"Geodetic survey data used"
,
"GPSMapDatum"
],
19
:
[
"Reference for latitude of destination"
,
"GPSDestLatitudeRef"
],
20
:
[
"Latitude of destination"
,
"GPSDestLatitude"
],
21
:
[
"Reference for longitude of destination"
,
"GPSDestLongitudeRef"
],
22
:
[
"Longitude of destination"
,
"GPSDestLongitude"
],
23
:
[
"Reference for bearing of destination"
,
"GPSDestBearingRef"
],
24
:
[
"Bearing of destination"
,
"GPSDestBearing"
],
25
:
[
"Reference for distance to destination"
,
"GPSDestDistanceRef"
],
26
:
[
"Distance to destination"
,
"GPSDestDistance"
],
27
:
[
"Name of GPS processing method"
,
"GPSProcessingMethod"
],
28
:
[
"Name of GPS area"
,
"GPSAreaInformation"
],
29
:
[
"GPS Date"
,
"GPSDateStamp"
],
30
:
[
"GPS differential correction"
,
"GPSDifferential"
]
};
this
.
JpegMeta
.
JpegFile
.
prototype
.
_markers
=
{
/* Start Of Frame markers, non-differential, Huffman coding */
0xc0
:
[
"SOF0"
,
"_sofHandler"
,
"Baseline DCT"
],
0xc1
:
[
"SOF1"
,
"_sofHandler"
,
"Extended sequential DCT"
],
0xc2
:
[
"SOF2"
,
"_sofHandler"
,
"Progressive DCT"
],
0xc3
:
[
"SOF3"
,
"_sofHandler"
,
"Lossless (sequential)"
],
/* Start Of Frame markers, differential, Huffman coding */
0xc5
:
[
"SOF5"
,
"_sofHandler"
,
"Differential sequential DCT"
],
0xc6
:
[
"SOF6"
,
"_sofHandler"
,
"Differential progressive DCT"
],
0xc7
:
[
"SOF7"
,
"_sofHandler"
,
"Differential lossless (sequential)"
],
/* Start Of Frame markers, non-differential, arithmetic coding */
0xc8
:
[
"JPG"
,
null
,
"Reserved for JPEG extensions"
],
0xc9
:
[
"SOF9"
,
"_sofHandler"
,
"Extended sequential DCT"
],
0xca
:
[
"SOF10"
,
"_sofHandler"
,
"Progressive DCT"
],
0xcb
:
[
"SOF11"
,
"_sofHandler"
,
"Lossless (sequential)"
],
/* Start Of Frame markers, differential, arithmetic coding */
0xcd
:
[
"SOF13"
,
"_sofHandler"
,
"Differential sequential DCT"
],
0xce
:
[
"SOF14"
,
"_sofHandler"
,
"Differential progressive DCT"
],
0xcf
:
[
"SOF15"
,
"_sofHandler"
,
"Differential lossless (sequential)"
],
/* Huffman table specification */
0xc4
:
[
"DHT"
,
null
,
"Define Huffman table(s)"
],
0xcc
:
[
"DAC"
,
null
,
"Define arithmetic coding conditioning(s)"
],
/* Restart interval termination" */
0xd0
:
[
"RST0"
,
null
,
"Restart with modulo 8 count “0”"
],
0xd1
:
[
"RST1"
,
null
,
"Restart with modulo 8 count “1”"
],
0xd2
:
[
"RST2"
,
null
,
"Restart with modulo 8 count “2”"
],
0xd3
:
[
"RST3"
,
null
,
"Restart with modulo 8 count “3”"
],
0xd4
:
[
"RST4"
,
null
,
"Restart with modulo 8 count “4”"
],
0xd5
:
[
"RST5"
,
null
,
"Restart with modulo 8 count “5”"
],
0xd6
:
[
"RST6"
,
null
,
"Restart with modulo 8 count “6”"
],
0xd7
:
[
"RST7"
,
null
,
"Restart with modulo 8 count “7”"
],
/* Other markers */
0xd8
:
[
"SOI"
,
null
,
"Start of image"
],
0xd9
:
[
"EOI"
,
null
,
"End of image"
],
0xda
:
[
"SOS"
,
null
,
"Start of scan"
],
0xdb
:
[
"DQT"
,
null
,
"Define quantization table(s)"
],
0xdc
:
[
"DNL"
,
null
,
"Define number of lines"
],
0xdd
:
[
"DRI"
,
null
,
"Define restart interval"
],
0xde
:
[
"DHP"
,
null
,
"Define hierarchical progression"
],
0xdf
:
[
"EXP"
,
null
,
"Expand reference component(s)"
],
0xe0
:
[
"APP0"
,
"_app0Handler"
,
"Reserved for application segments"
],
0xe1
:
[
"APP1"
,
"_app1Handler"
],
0xe2
:
[
"APP2"
,
null
],
0xe3
:
[
"APP3"
,
null
],
0xe4
:
[
"APP4"
,
null
],
0xe5
:
[
"APP5"
,
null
],
0xe6
:
[
"APP6"
,
null
],
0xe7
:
[
"APP7"
,
null
],
0xe8
:
[
"APP8"
,
null
],
0xe9
:
[
"APP9"
,
null
],
0xea
:
[
"APP10"
,
null
],
0xeb
:
[
"APP11"
,
null
],
0xec
:
[
"APP12"
,
null
],
0xed
:
[
"APP13"
,
null
],
0xee
:
[
"APP14"
,
null
],
0xef
:
[
"APP15"
,
null
],
0xf0
:
[
"JPG0"
,
null
],
/* Reserved for JPEG extensions */
0xf1
:
[
"JPG1"
,
null
],
0xf2
:
[
"JPG2"
,
null
],
0xf3
:
[
"JPG3"
,
null
],
0xf4
:
[
"JPG4"
,
null
],
0xf5
:
[
"JPG5"
,
null
],
0xf6
:
[
"JPG6"
,
null
],
0xf7
:
[
"JPG7"
,
null
],
0xf8
:
[
"JPG8"
,
null
],
0xf9
:
[
"JPG9"
,
null
],
0xfa
:
[
"JPG10"
,
null
],
0xfb
:
[
"JPG11"
,
null
],
0xfc
:
[
"JPG12"
,
null
],
0xfd
:
[
"JPG13"
,
null
],
0xfe
:
[
"COM"
,
null
],
/* Comment */
/* Reserved markers */
0x01
:
[
"JPG13"
,
null
]
/* For temporary private use in arithmetic coding */
/* 02 -> bf are reserverd */
};
/* Private methods */
this
.
JpegMeta
.
JpegFile
.
prototype
.
_addMetaGroup
=
function
_addMetaGroup
(
name
,
description
)
{
var
group
=
new
JpegMeta
.
MetaGroup
(
name
,
description
);
this
[
group
.
fieldName
]
=
group
;
this
.
metaGroups
[
group
.
fieldName
]
=
group
;
return
group
;
};
this
.
JpegMeta
.
JpegFile
.
prototype
.
_parseIfd
=
function
_parseIfd
(
endian
,
_binary_data
,
base
,
ifd_offset
,
tags
,
name
,
description
)
{
var
num_fields
=
JpegMeta
.
parseNum
(
endian
,
_binary_data
,
base
+
ifd_offset
,
2
);
/* Per tag variables */
var
i
,
j
;
var
tag_base
;
var
tag_field
;
var
type
,
type_field
,
type_size
;
var
num_values
;
var
value_offset
;
var
value
;
var
_val
;
var
num
;
var
den
;
var
group
;
group
=
this
.
_addMetaGroup
(
name
,
description
);
for
(
var
i
=
0
;
i
<
num_fields
;
i
++
)
{
/* parse the field */
tag_base
=
base
+
ifd_offset
+
2
+
(
i
*
12
);
tag_field
=
JpegMeta
.
parseNum
(
endian
,
_binary_data
,
tag_base
,
2
);
type_field
=
JpegMeta
.
parseNum
(
endian
,
_binary_data
,
tag_base
+
2
,
2
);
num_values
=
JpegMeta
.
parseNum
(
endian
,
_binary_data
,
tag_base
+
4
,
4
);
value_offset
=
JpegMeta
.
parseNum
(
endian
,
_binary_data
,
tag_base
+
8
,
4
);
if
(
this
.
_types
[
type_field
]
===
undefined
)
{
continue
;
}
type
=
this
.
_types
[
type_field
][
0
];
type_size
=
this
.
_types
[
type_field
][
1
];
if
(
type_size
*
num_values
<=
4
)
{
/* Data is in-line */
value_offset
=
tag_base
+
8
;
}
else
{
value_offset
=
base
+
value_offset
;
}
/* Read the value */
if
(
type
==
"UNDEFINED"
)
{
value
=
_binary_data
.
slice
(
value_offset
,
value_offset
+
num_values
);
}
else
if
(
type
==
"ASCII"
)
{
value
=
_binary_data
.
slice
(
value_offset
,
value_offset
+
num_values
);
value
=
value
.
split
(
'\x00'
)[
0
];
/* strip trail nul */
}
else
{
value
=
new
Array
();
for
(
j
=
0
;
j
<
num_values
;
j
++
,
value_offset
+=
type_size
)
{
if
(
type
==
"BYTE"
||
type
==
"SHORT"
||
type
==
"LONG"
)
{
value
.
push
(
JpegMeta
.
parseNum
(
endian
,
_binary_data
,
value_offset
,
type_size
));
}
if
(
type
==
"SBYTE"
||
type
==
"SSHORT"
||
type
==
"SLONG"
)
{
value
.
push
(
JpegMeta
.
parseSnum
(
endian
,
_binary_data
,
value_offset
,
type_size
));
}
if
(
type
==
"RATIONAL"
)
{
num
=
JpegMeta
.
parseNum
(
endian
,
_binary_data
,
value_offset
,
4
);
den
=
JpegMeta
.
parseNum
(
endian
,
_binary_data
,
value_offset
+
4
,
4
);
value
.
push
(
new
JpegMeta
.
Rational
(
num
,
den
));
}
if
(
type
==
"SRATIONAL"
)
{
num
=
JpegMeta
.
parseSnum
(
endian
,
_binary_data
,
value_offset
,
4
);
den
=
JpegMeta
.
parseSnum
(
endian
,
_binary_data
,
value_offset
+
4
,
4
);
value
.
push
(
new
JpegMeta
.
Rational
(
num
,
den
));
}
value
.
push
();
}
if
(
num_values
===
1
)
{
value
=
value
[
0
];
}
}
if
(
tags
[
tag_field
]
!==
undefined
)
{
group
.
_addProperty
(
tags
[
tag_field
][
1
],
tags
[
tag_field
][
0
],
value
);
}
}
};
this
.
JpegMeta
.
JpegFile
.
prototype
.
_jfifHandler
=
function
_jfifHandler
(
mark
,
pos
)
{
if
(
this
.
jfif
!==
undefined
)
{
throw
Error
(
"Multiple JFIF segments found"
);
}
this
.
_addMetaGroup
(
"jfif"
,
"JFIF"
);
this
.
jfif
.
_addProperty
(
"version_major"
,
"Version Major"
,
this
.
_binary_data
.
charCodeAt
(
pos
+
5
));
this
.
jfif
.
_addProperty
(
"version_minor"
,
"Version Minor"
,
this
.
_binary_data
.
charCodeAt
(
pos
+
6
));
this
.
jfif
.
_addProperty
(
"version"
,
"JFIF Version"
,
this
.
jfif
.
version_major
.
value
+
"."
+
this
.
jfif
.
version_minor
.
value
);
this
.
jfif
.
_addProperty
(
"units"
,
"Density Unit"
,
this
.
_binary_data
.
charCodeAt
(
pos
+
7
));
this
.
jfif
.
_addProperty
(
"Xdensity"
,
"X density"
,
JpegMeta
.
parseNum
(
">"
,
this
.
_binary_data
,
pos
+
8
,
2
));
this
.
jfif
.
_addProperty
(
"Ydensity"
,
"Y Density"
,
JpegMeta
.
parseNum
(
">"
,
this
.
_binary_data
,
pos
+
10
,
2
));
this
.
jfif
.
_addProperty
(
"Xthumbnail"
,
"X Thumbnail"
,
JpegMeta
.
parseNum
(
">"
,
this
.
_binary_data
,
pos
+
12
,
1
));
this
.
jfif
.
_addProperty
(
"Ythumbnail"
,
"Y Thumbnail"
,
JpegMeta
.
parseNum
(
">"
,
this
.
_binary_data
,
pos
+
13
,
1
));
};
/* Handle app0 segments */
this
.
JpegMeta
.
JpegFile
.
prototype
.
_app0Handler
=
function
app0Handler
(
mark
,
pos
)
{
var
ident
=
this
.
_binary_data
.
slice
(
pos
,
pos
+
5
);
if
(
ident
==
this
.
_JFIF_IDENT
)
{
this
.
_jfifHandler
(
mark
,
pos
);
}
else
if
(
ident
==
this
.
_JFXX_IDENT
)
{
/* Don't handle JFXX Ident yet */
}
else
{
/* Don't know about other idents */
}
};
/* Handle app1 segments */
this
.
JpegMeta
.
JpegFile
.
prototype
.
_app1Handler
=
function
_app1Handler
(
mark
,
pos
)
{
var
ident
=
this
.
_binary_data
.
slice
(
pos
,
pos
+
5
);
if
(
ident
==
this
.
_EXIF_IDENT
)
{
this
.
_exifHandler
(
mark
,
pos
+
6
);
}
else
{
/* Don't know about other idents */
}
};
/* Handle exif segments */
JpegMeta
.
JpegFile
.
prototype
.
_exifHandler
=
function
_exifHandler
(
mark
,
pos
)
{
if
(
this
.
exif
!==
undefined
)
{
throw
new
Error
(
"Multiple JFIF segments found"
);
}
/* Parse this TIFF header */
var
endian
;
var
magic_field
;
var
ifd_offset
;
var
primary_ifd
,
exif_ifd
,
gps_ifd
;
var
endian_field
=
this
.
_binary_data
.
slice
(
pos
,
pos
+
2
);
/* Trivia: This 'I' is for Intel, the 'M' is for Motorola */
if
(
endian_field
===
"II"
)
{
endian
=
"<"
;
}
else
if
(
endian_field
===
"MM"
)
{
endian
=
">"
;
}
else
{
throw
new
Error
(
"Malformed TIFF meta-data. Unknown endianess: "
+
endian_field
);
}
magic_field
=
JpegMeta
.
parseNum
(
endian
,
this
.
_binary_data
,
pos
+
2
,
2
);
if
(
magic_field
!==
42
)
{
throw
new
Error
(
"Malformed TIFF meta-data. Bad magic: "
+
magic_field
);
}
ifd_offset
=
JpegMeta
.
parseNum
(
endian
,
this
.
_binary_data
,
pos
+
4
,
4
);
/* Parse 0th IFD */
this
.
_parseIfd
(
endian
,
this
.
_binary_data
,
pos
,
ifd_offset
,
this
.
_tifftags
,
"tiff"
,
"TIFF"
);
if
(
this
.
tiff
.
ExifIfdPointer
)
{
this
.
_parseIfd
(
endian
,
this
.
_binary_data
,
pos
,
this
.
tiff
.
ExifIfdPointer
.
value
,
this
.
_exiftags
,
"exif"
,
"Exif"
);
}
if
(
this
.
tiff
.
GPSInfoIfdPointer
)
{
this
.
_parseIfd
(
endian
,
this
.
_binary_data
,
pos
,
this
.
tiff
.
GPSInfoIfdPointer
.
value
,
this
.
_gpstags
,
"gps"
,
"GPS"
);
if
(
this
.
gps
.
GPSLatitude
)
{
var
latitude
;
latitude
=
this
.
gps
.
GPSLatitude
.
value
[
0
].
asFloat
()
+
(
1
/
60
)
*
this
.
gps
.
GPSLatitude
.
value
[
1
].
asFloat
()
+
(
1
/
3600
)
*
this
.
gps
.
GPSLatitude
.
value
[
2
].
asFloat
();
if
(
this
.
gps
.
GPSLatitudeRef
.
value
===
"S"
)
{
latitude
=
-
latitude
;
}
this
.
gps
.
_addProperty
(
"latitude"
,
"Dec. Latitude"
,
latitude
);
}
if
(
this
.
gps
.
GPSLongitude
)
{
var
longitude
;
longitude
=
this
.
gps
.
GPSLongitude
.
value
[
0
].
asFloat
()
+
(
1
/
60
)
*
this
.
gps
.
GPSLongitude
.
value
[
1
].
asFloat
()
+
(
1
/
3600
)
*
this
.
gps
.
GPSLongitude
.
value
[
2
].
asFloat
();
if
(
this
.
gps
.
GPSLongitudeRef
.
value
===
"W"
)
{
longitude
=
-
longitude
;
}
this
.
gps
.
_addProperty
(
"longitude"
,
"Dec. Longitude"
,
longitude
);
}
}
};
}()
);
File Metadata
Details
Attached
Mime Type
text/html
Expires
Fri, Jul 3, 17:59 (1 d, 4 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
fb/5b/93fd0cf760edfb96634d330287ba
Default Alt Text
jpegmeta.js (26 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment