
fixes for map center computation, DB & filter chip update on metadata changes, offscreen marker generation
646 lines
16 KiB
Dart
646 lines
16 KiB
Dart
class Exif {
|
||
// constants used by GPS related Exif tags
|
||
// they are locale independent
|
||
static const String latitudeNorth = 'N';
|
||
static const String latitudeSouth = 'S';
|
||
static const String longitudeEast = 'E';
|
||
static const String longitudeWest = 'W';
|
||
|
||
static String getColorSpaceDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return 'sRGB';
|
||
case 65535:
|
||
return 'Uncalibrated';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getContrastDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Normal';
|
||
case 1:
|
||
return 'Soft';
|
||
case 2:
|
||
return 'Hard';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
// adapted from `metadata-extractor`
|
||
static String getCompressionDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return 'Uncompressed';
|
||
case 2:
|
||
return 'CCITT 1D';
|
||
case 3:
|
||
return 'T4/Group 3 Fax';
|
||
case 4:
|
||
return 'T6/Group 4 Fax';
|
||
case 5:
|
||
return 'LZW';
|
||
case 6:
|
||
return 'JPEG (old-style)';
|
||
case 7:
|
||
return 'JPEG';
|
||
case 8:
|
||
return 'Adobe Deflate';
|
||
case 9:
|
||
return 'JBIG B&W';
|
||
case 10:
|
||
return 'JBIG Color';
|
||
case 99:
|
||
return 'JPEG';
|
||
case 262:
|
||
return 'Kodak 262';
|
||
case 32766:
|
||
return 'Next';
|
||
case 32767:
|
||
return 'Sony ARW Compressed';
|
||
case 32769:
|
||
return 'Packed RAW';
|
||
case 32770:
|
||
return 'Samsung SRW Compressed';
|
||
case 32771:
|
||
return 'CCIRLEW';
|
||
case 32772:
|
||
return 'Samsung SRW Compressed 2';
|
||
case 32773:
|
||
return 'PackBits';
|
||
case 32809:
|
||
return 'Thunderscan';
|
||
case 32867:
|
||
return 'Kodak KDC Compressed';
|
||
case 32895:
|
||
return 'IT8CTPAD';
|
||
case 32896:
|
||
return 'IT8LW';
|
||
case 32897:
|
||
return 'IT8MP';
|
||
case 32898:
|
||
return 'IT8BL';
|
||
case 32908:
|
||
return 'PixarFilm';
|
||
case 32909:
|
||
return 'PixarLog';
|
||
case 32946:
|
||
return 'Deflate';
|
||
case 32947:
|
||
return 'DCS';
|
||
case 34661:
|
||
return 'JBIG';
|
||
case 34676:
|
||
return 'SGILog';
|
||
case 34677:
|
||
return 'SGILog24';
|
||
case 34712:
|
||
return 'JPEG 2000';
|
||
case 34713:
|
||
return 'Nikon NEF Compressed';
|
||
case 34715:
|
||
return 'JBIG2 TIFF FX';
|
||
case 34718:
|
||
return 'Microsoft Document Imaging (MDI) Binary Level Codec';
|
||
case 34719:
|
||
return 'Microsoft Document Imaging (MDI) Progressive Transform Codec';
|
||
case 34720:
|
||
return 'Microsoft Document Imaging (MDI) Vector';
|
||
case 34892:
|
||
return 'Lossy JPEG';
|
||
case 65000:
|
||
return 'Kodak DCR Compressed';
|
||
case 65535:
|
||
return 'Pentax PEF Compressed';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getCustomRenderedDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Normal process';
|
||
case 1:
|
||
return 'Custom process';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getExifVersionDescription(String valueString) {
|
||
if (valueString.length == 4) {
|
||
final major = int.tryParse(valueString.substring(0, 2));
|
||
final minor = int.tryParse(valueString.substring(2, 4));
|
||
if (major != null && minor != null) {
|
||
return '$major.$minor';
|
||
}
|
||
}
|
||
return valueString;
|
||
}
|
||
|
||
static String getExposureModeDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Auto exposure';
|
||
case 1:
|
||
return 'Manual exposure';
|
||
case 2:
|
||
return 'Auto bracket';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getExposureProgramDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return 'Manual';
|
||
case 2:
|
||
return 'Normal program';
|
||
case 3:
|
||
return 'Aperture priority';
|
||
case 4:
|
||
return 'Shutter priority';
|
||
case 5:
|
||
return 'Creative program';
|
||
case 6:
|
||
return 'Action program';
|
||
case 7:
|
||
return 'Portrait mode';
|
||
case 8:
|
||
return 'Landscape mode';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
// adapted from `metadata-extractor`
|
||
static String getFileSourceDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return 'Film Scanner';
|
||
case 2:
|
||
return 'Reflection Print Scanner';
|
||
case 3:
|
||
return 'Digital Still Camera (DSC)';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getLightSourceDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Unknown';
|
||
case 1:
|
||
return 'Daylight';
|
||
case 2:
|
||
return 'Fluorescent';
|
||
case 3:
|
||
return 'Tungsten (Incandescent)';
|
||
case 4:
|
||
return 'Flash';
|
||
case 9:
|
||
return 'Fine Weather';
|
||
case 10:
|
||
return 'Cloudy Weather';
|
||
case 11:
|
||
return 'Shade';
|
||
case 12:
|
||
return 'Daylight Fluorescent (D 5700 – 7100K)';
|
||
case 13:
|
||
return 'Day White Fluorescent (N 4600 – 5400K)';
|
||
case 14:
|
||
return 'Cool White Fluorescent (W 3900 – 4500K)';
|
||
case 15:
|
||
return 'White Fluorescent (WW 3200 – 3700K)';
|
||
case 16:
|
||
return 'Warm White Fluorescent (WW 2600 - 3250K)';
|
||
case 17:
|
||
return 'Standard light A';
|
||
case 18:
|
||
return 'Standard light B';
|
||
case 19:
|
||
return 'Standard light C';
|
||
case 20:
|
||
return 'D55';
|
||
case 21:
|
||
return 'D65';
|
||
case 22:
|
||
return 'D75';
|
||
case 23:
|
||
return 'D50';
|
||
case 24:
|
||
return 'ISO Studio Tungsten';
|
||
case 255:
|
||
return 'Other';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
// adapted from `metadata-extractor`
|
||
static String getOrientationDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return 'Top, left side (Horizontal / normal)';
|
||
case 2:
|
||
return 'Top, right side (Mirror horizontal)';
|
||
case 3:
|
||
return 'Bottom, right side (Rotate 180)';
|
||
case 4:
|
||
return 'Bottom, left side (Mirror vertical)';
|
||
case 5:
|
||
return 'Left side, top (Mirror horizontal and rotate 270 CW)';
|
||
case 6:
|
||
return 'Right side, top (Rotate 90 CW)';
|
||
case 7:
|
||
return 'Right side, bottom (Mirror horizontal and rotate 90 CW)';
|
||
case 8:
|
||
return 'Left side, bottom (Rotate 270 CW)';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
// adapted from `metadata-extractor`
|
||
static String getPhotometricInterpretationDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'WhiteIsZero';
|
||
case 1:
|
||
return 'BlackIsZero';
|
||
case 2:
|
||
return 'RGB';
|
||
case 3:
|
||
return 'RGB Palette';
|
||
case 4:
|
||
return 'Transparency Mask';
|
||
case 5:
|
||
return 'CMYK';
|
||
case 6:
|
||
return 'YCbCr';
|
||
case 8:
|
||
return 'CIELab';
|
||
case 9:
|
||
return 'ICCLab';
|
||
case 10:
|
||
return 'ITULab';
|
||
case 32803:
|
||
return 'Color Filter Array';
|
||
case 32844:
|
||
return 'Pixar LogL';
|
||
case 32845:
|
||
return 'Pixar LogLuv';
|
||
case 32892:
|
||
return 'Linear Raw';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
// adapted from `metadata-extractor`
|
||
static String getPlanarConfigurationDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return 'Chunky (contiguous for each subsampling pixel)';
|
||
case 2:
|
||
return 'Separate (Y-plane/Cb-plane/Cr-plane format)';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
// adapted from `metadata-extractor`
|
||
static String getResolutionUnitDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return '(No unit)';
|
||
case 2:
|
||
return 'Inch';
|
||
case 3:
|
||
return 'cm';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getGainControlDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'None';
|
||
case 1:
|
||
return 'Low gain up';
|
||
case 2:
|
||
return 'High gain up';
|
||
case 3:
|
||
return 'Low gain down';
|
||
case 4:
|
||
return 'High gain down';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getMeteringModeDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Unknown';
|
||
case 1:
|
||
return 'Average';
|
||
case 2:
|
||
return 'Center weighted average';
|
||
case 3:
|
||
return 'Spot';
|
||
case 4:
|
||
return 'Multi-spot';
|
||
case 5:
|
||
return 'Pattern';
|
||
case 6:
|
||
return 'Partial';
|
||
case 255:
|
||
return 'Other';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getSaturationDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Normal';
|
||
case 1:
|
||
return 'Low saturation';
|
||
case 2:
|
||
return 'High saturation';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getSceneCaptureTypeDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Standard';
|
||
case 1:
|
||
return 'Landscape';
|
||
case 2:
|
||
return 'Portrait';
|
||
case 3:
|
||
return 'Night scene';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getSceneTypeDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return 'Directly photographed image';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getSensingMethodDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return 'Not defined';
|
||
case 2:
|
||
return 'One-chip colour area sensor';
|
||
case 3:
|
||
return 'Two-chip colour area sensor';
|
||
case 4:
|
||
return 'Three-chip colour area sensor';
|
||
case 5:
|
||
return 'Colour sequential area sensor';
|
||
case 7:
|
||
return 'Trilinear sensor';
|
||
case 8:
|
||
return 'Colour sequential linear sensor';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getSharpnessDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Normal';
|
||
case 1:
|
||
return 'Soft';
|
||
case 2:
|
||
return 'Hard';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getSubjectDistanceRangeDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Unknown';
|
||
case 1:
|
||
return 'Macro';
|
||
case 2:
|
||
return 'Close view';
|
||
case 3:
|
||
return 'Distant view';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getWhiteBalanceDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Auto';
|
||
case 1:
|
||
return 'Manual';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getYCbCrPositioningDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 1:
|
||
return 'Centered';
|
||
case 2:
|
||
return 'Co-sited';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
// Flash
|
||
|
||
static String getFlashModeDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Unknown';
|
||
case 1:
|
||
return 'Compulsory flash firing';
|
||
case 2:
|
||
return 'Compulsory flash suppression';
|
||
case 3:
|
||
return 'Auto mode';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getFlashReturnDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'No strobe return detection';
|
||
case 2:
|
||
return 'Strobe return light not detected';
|
||
case 3:
|
||
return 'Strobe return light detected';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
// GPS
|
||
|
||
static String getGPSAltitudeRefDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Above sea level';
|
||
case 1:
|
||
return 'Below sea level';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getGPSDifferentialDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 0:
|
||
return 'Without correction';
|
||
case 1:
|
||
return 'Correction applied';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getGPSDirectionRefDescription(String value) {
|
||
switch (value) {
|
||
case 'T':
|
||
return 'True direction';
|
||
case 'M':
|
||
return 'Magnetic direction';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getGPSMeasureModeDescription(String valueString) {
|
||
final value = int.tryParse(valueString);
|
||
if (value == null) return valueString;
|
||
switch (value) {
|
||
case 2:
|
||
return 'Two-dimensional measurement';
|
||
case 3:
|
||
return 'Three-dimensional measurement';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getGPSDestDistanceRefDescription(String value) {
|
||
switch (value) {
|
||
case 'K':
|
||
return 'kilometers';
|
||
case 'M':
|
||
return 'miles';
|
||
case 'N':
|
||
return 'knots';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getGPSSpeedRefDescription(String value) {
|
||
switch (value) {
|
||
case 'K':
|
||
return 'kilometers per hour';
|
||
case 'M':
|
||
return 'miles per hour';
|
||
case 'N':
|
||
return 'knots';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
|
||
static String getGPSStatusDescription(String value) {
|
||
switch (value) {
|
||
case 'A':
|
||
return 'Measurement in progress';
|
||
case 'V':
|
||
return 'Measurement is interoperability';
|
||
default:
|
||
return 'Unknown ($value)';
|
||
}
|
||
}
|
||
}
|