com.drew.metadata.exif.ExifThumbnailDescriptor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of metadata-extractor Show documentation
Show all versions of metadata-extractor Show documentation
Java library for extracting EXIF, IPTC, XMP, ICC and other metadata from image and video files.
/*
* Copyright 2002-2012 Drew Noakes
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* More information about this project is available at:
*
* http://drewnoakes.com/code/exif/
* http://code.google.com/p/metadata-extractor/
*/
package com.drew.metadata.exif;
import com.drew.lang.Rational;
import com.drew.lang.annotations.NotNull;
import com.drew.lang.annotations.Nullable;
import com.drew.metadata.TagDescriptor;
/**
* Provides human-readable string representations of tag values stored in a ExifThumbnailDirectory
.
*
* @author Drew Noakes http://drewnoakes.com
*/
public class ExifThumbnailDescriptor extends TagDescriptor
{
/**
* Dictates whether rational values will be represented in decimal format in instances
* where decimal notation is elegant (such as 1/2 -> 0.5, but not 1/3).
*/
private final boolean _allowDecimalRepresentationOfRationals = true;
public ExifThumbnailDescriptor(@NotNull ExifThumbnailDirectory directory)
{
super(directory);
}
// Note for the potential addition of brightness presentation in eV:
// Brightness of taken subject. To calculate Exposure(Ev) from BrightnessValue(Bv),
// you must add SensitivityValue(Sv).
// Ev=BV+Sv Sv=log2(ISOSpeedRating/3.125)
// ISO100:Sv=5, ISO200:Sv=6, ISO400:Sv=7, ISO125:Sv=5.32.
/**
* Returns a descriptive value of the the specified tag for this image.
* Where possible, known values will be substituted here in place of the raw
* tokens actually kept in the Exif segment. If no substitution is
* available, the value provided by getString(int) will be returned.
* @param tagType the tag to find a description for
* @return a description of the image's value for the specified tag, or
* null
if the tag hasn't been defined.
*/
@Nullable
public String getDescription(int tagType)
{
switch (tagType) {
case ExifThumbnailDirectory.TAG_ORIENTATION:
return getOrientationDescription();
case ExifThumbnailDirectory.TAG_RESOLUTION_UNIT:
return getResolutionDescription();
case ExifThumbnailDirectory.TAG_YCBCR_POSITIONING:
return getYCbCrPositioningDescription();
case ExifThumbnailDirectory.TAG_X_RESOLUTION:
return getXResolutionDescription();
case ExifThumbnailDirectory.TAG_Y_RESOLUTION:
return getYResolutionDescription();
case ExifThumbnailDirectory.TAG_THUMBNAIL_OFFSET:
return getThumbnailOffsetDescription();
case ExifThumbnailDirectory.TAG_THUMBNAIL_LENGTH:
return getThumbnailLengthDescription();
case ExifThumbnailDirectory.TAG_THUMBNAIL_IMAGE_WIDTH:
return getThumbnailImageWidthDescription();
case ExifThumbnailDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT:
return getThumbnailImageHeightDescription();
case ExifThumbnailDirectory.TAG_BITS_PER_SAMPLE:
return getBitsPerSampleDescription();
case ExifThumbnailDirectory.TAG_THUMBNAIL_COMPRESSION:
return getCompressionDescription();
case ExifThumbnailDirectory.TAG_PHOTOMETRIC_INTERPRETATION:
return getPhotometricInterpretationDescription();
case ExifThumbnailDirectory.TAG_ROWS_PER_STRIP:
return getRowsPerStripDescription();
case ExifThumbnailDirectory.TAG_STRIP_BYTE_COUNTS:
return getStripByteCountsDescription();
case ExifThumbnailDirectory.TAG_SAMPLES_PER_PIXEL:
return getSamplesPerPixelDescription();
case ExifThumbnailDirectory.TAG_PLANAR_CONFIGURATION:
return getPlanarConfigurationDescription();
case ExifThumbnailDirectory.TAG_YCBCR_SUBSAMPLING:
return getYCbCrSubsamplingDescription();
case ExifThumbnailDirectory.TAG_REFERENCE_BLACK_WHITE:
return getReferenceBlackWhiteDescription();
default:
return super.getDescription(tagType);
}
}
@Nullable
public String getReferenceBlackWhiteDescription()
{
int[] ints = _directory.getIntArray(ExifThumbnailDirectory.TAG_REFERENCE_BLACK_WHITE);
if (ints==null)
return null;
int blackR = ints[0];
int whiteR = ints[1];
int blackG = ints[2];
int whiteG = ints[3];
int blackB = ints[4];
int whiteB = ints[5];
return "[" + blackR + "," + blackG + "," + blackB + "] " +
"[" + whiteR + "," + whiteG + "," + whiteB + "]";
}
@Nullable
public String getYCbCrSubsamplingDescription()
{
int[] positions = _directory.getIntArray(ExifThumbnailDirectory.TAG_YCBCR_SUBSAMPLING);
if (positions==null || positions.length < 2)
return null;
if (positions[0] == 2 && positions[1] == 1) {
return "YCbCr4:2:2";
} else if (positions[0] == 2 && positions[1] == 2) {
return "YCbCr4:2:0";
} else {
return "(Unknown)";
}
}
@Nullable
public String getPlanarConfigurationDescription()
{
// When image format is no compression YCbCr, this value shows byte aligns of YCbCr
// data. If value is '1', Y/Cb/Cr value is chunky format, contiguous for each subsampling
// pixel. If value is '2', Y/Cb/Cr value is separated and stored to Y plane/Cb plane/Cr
// plane format.
Integer value = _directory.getInteger(ExifThumbnailDirectory.TAG_PLANAR_CONFIGURATION);
if (value==null)
return null;
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 configuration";
}
}
@Nullable
public String getSamplesPerPixelDescription()
{
String value = _directory.getString(ExifThumbnailDirectory.TAG_SAMPLES_PER_PIXEL);
return value==null ? null : value + " samples/pixel";
}
@Nullable
public String getRowsPerStripDescription()
{
final String value = _directory.getString(ExifThumbnailDirectory.TAG_ROWS_PER_STRIP);
return value==null ? null : value + " rows/strip";
}
@Nullable
public String getStripByteCountsDescription()
{
final String value = _directory.getString(ExifThumbnailDirectory.TAG_STRIP_BYTE_COUNTS);
return value==null ? null : value + " bytes";
}
@Nullable
public String getPhotometricInterpretationDescription()
{
// Shows the color space of the image data components
Integer value = _directory.getInteger(ExifThumbnailDirectory.TAG_PHOTOMETRIC_INTERPRETATION);
if (value==null)
return null;
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 colour space";
}
}
@Nullable
public String getCompressionDescription()
{
Integer value = _directory.getInteger(ExifThumbnailDirectory.TAG_THUMBNAIL_COMPRESSION);
if (value==null)
return null;
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 32766: return "Next";
case 32771: return "CCIRLEW";
case 32773: return "PackBits";
case 32809: return "Thunderscan";
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 32661: return "JBIG";
case 32676: return "SGILog";
case 32677: return "SGILog24";
case 32712: return "JPEG 2000";
case 32713: return "Nikon NEF Compressed";
default:
return "Unknown compression";
}
}
@Nullable
public String getBitsPerSampleDescription()
{
String value = _directory.getString(ExifThumbnailDirectory.TAG_BITS_PER_SAMPLE);
return value==null ? null : value + " bits/component/pixel";
}
@Nullable
public String getThumbnailImageWidthDescription()
{
String value = _directory.getString(ExifThumbnailDirectory.TAG_THUMBNAIL_IMAGE_WIDTH);
return value==null ? null : value + " pixels";
}
@Nullable
public String getThumbnailImageHeightDescription()
{
String value = _directory.getString(ExifThumbnailDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT);
return value==null ? null : value + " pixels";
}
@Nullable
public String getThumbnailLengthDescription()
{
String value = _directory.getString(ExifThumbnailDirectory.TAG_THUMBNAIL_LENGTH);
return value==null ? null : value + " bytes";
}
@Nullable
public String getThumbnailOffsetDescription()
{
String value = _directory.getString(ExifThumbnailDirectory.TAG_THUMBNAIL_OFFSET);
return value==null ? null : value + " bytes";
}
@Nullable
public String getYResolutionDescription()
{
Rational value = _directory.getRational(ExifThumbnailDirectory.TAG_Y_RESOLUTION);
if (value==null)
return null;
final String unit = getResolutionDescription();
return value.toSimpleString(_allowDecimalRepresentationOfRationals) +
" dots per " +
(unit==null ? "unit" : unit.toLowerCase());
}
@Nullable
public String getXResolutionDescription()
{
Rational value = _directory.getRational(ExifThumbnailDirectory.TAG_X_RESOLUTION);
if (value==null)
return null;
final String unit = getResolutionDescription();
return value.toSimpleString(_allowDecimalRepresentationOfRationals) +
" dots per " +
(unit==null ? "unit" : unit.toLowerCase());
}
@Nullable
public String getYCbCrPositioningDescription()
{
Integer value = _directory.getInteger(ExifThumbnailDirectory.TAG_YCBCR_POSITIONING);
if (value==null)
return null;
switch (value) {
case 1: return "Center of pixel array";
case 2: return "Datum point";
default:
return String.valueOf(value);
}
}
@Nullable
public String getOrientationDescription()
{
Integer value = _directory.getInteger(ExifThumbnailDirectory.TAG_ORIENTATION);
if (value==null)
return null;
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 String.valueOf(value);
}
}
@Nullable
public String getResolutionDescription()
{
// '1' means no-unit, '2' means inch, '3' means centimeter. Default value is '2'(inch)
Integer value = _directory.getInteger(ExifThumbnailDirectory.TAG_RESOLUTION_UNIT);
if (value==null)
return null;
switch (value) {
case 1: return "(No unit)";
case 2: return "Inch";
case 3: return "cm";
default:
return "";
}
}
}