📄 exifdirectory.java
字号:
tagNameMap.put(new Integer(TAG_WHITE_BALANCE), "Light Source");
tagNameMap.put(new Integer(TAG_FLASH), "Flash");
tagNameMap.put(new Integer(TAG_FOCAL_LENGTH), "Focal Length");
tagNameMap.put(new Integer(TAG_FLASH_ENERGY), "Flash Energy");
tagNameMap.put(new Integer(TAG_SPATIAL_FREQ_RESPONSE), "Spatial Frequency Response");
tagNameMap.put(new Integer(TAG_NOISE), "Noise");
tagNameMap.put(new Integer(TAG_IMAGE_NUMBER), "Image Number");
tagNameMap.put(new Integer(TAG_SECURITY_CLASSIFICATION), "Security Classification");
tagNameMap.put(new Integer(TAG_IMAGE_HISTORY), "Image History");
tagNameMap.put(new Integer(TAG_SUBJECT_LOCATION), "Subject Location");
tagNameMap.put(new Integer(TAG_EXPOSURE_INDEX), "Exposure Index");
tagNameMap.put(new Integer(TAG_TIFF_EP_STANDARD_ID), "TIFF/EP Standard ID");
tagNameMap.put(new Integer(TAG_USER_COMMENT), "User Comment");
tagNameMap.put(new Integer(TAG_SUBSECOND_TIME), "Sub-Sec Time");
tagNameMap.put(new Integer(TAG_SUBSECOND_TIME_ORIGINAL), "Sub-Sec Time Original");
tagNameMap.put(new Integer(TAG_SUBSECOND_TIME_DIGITIZED), "Sub-Sec Time Digitized");
tagNameMap.put(new Integer(TAG_FLASHPIX_VERSION), "FlashPix Version");
tagNameMap.put(new Integer(TAG_COLOR_SPACE), "Color Space");
tagNameMap.put(new Integer(TAG_EXIF_IMAGE_WIDTH), "Exif Image Width");
tagNameMap.put(new Integer(TAG_EXIF_IMAGE_HEIGHT), "Exif Image Height");
tagNameMap.put(new Integer(TAG_RELATED_SOUND_FILE), "Related Sound File");
// 0x920B in TIFF/EP
tagNameMap.put(new Integer(TAG_FLASH_ENERGY_2), "Flash Energy");
// 0x920C in TIFF/EP
tagNameMap.put(new Integer(TAG_SPATIAL_FREQ_RESPONSE_2), "Spatial Frequency Response");
// 0x920E in TIFF/EP
tagNameMap.put(new Integer(TAG_FOCAL_PLANE_X_RES), "Focal Plane X Resolution");
// 0x920F in TIFF/EP
tagNameMap.put(new Integer(TAG_FOCAL_PLANE_Y_RES), "Focal Plane Y Resolution");
// 0x9210 in TIFF/EP
tagNameMap.put(new Integer(TAG_FOCAL_PLANE_UNIT), "Focal Plane Resolution Unit");
// 0x9214 in TIFF/EP
tagNameMap.put(new Integer(TAG_SUBJECT_LOCATION_2), "Subject Location");
// 0x9215 in TIFF/EP
tagNameMap.put(new Integer(TAG_EXPOSURE_INDEX_2), "Exposure Index");
// 0x9217 in TIFF/EP
tagNameMap.put(new Integer(TAG_SENSING_METHOD), "Sensing Method");
tagNameMap.put(new Integer(TAG_FILE_SOURCE), "File Source");
tagNameMap.put(new Integer(TAG_SCENE_TYPE), "Scene Type");
tagNameMap.put(new Integer(TAG_CFA_PATTERN), "CFA Pattern");
tagNameMap.put(new Integer(TAG_CUSTOM_RENDERED), "Custom Rendered");
tagNameMap.put(new Integer(TAG_EXPOSURE_MODE), "Exposure Mode");
tagNameMap.put(new Integer(TAG_WHITE_BALANCE_MODE), "White Balance");
tagNameMap.put(new Integer(TAG_DIGITAL_ZOOM_RATIO), "Digital Zoom Ratio");
tagNameMap.put(new Integer(TAG_35MM_FILM_EQUIV_FOCAL_LENGTH), "Focal Length 35");
tagNameMap.put(new Integer(TAG_SCENE_CAPTURE_TYPE), "Scene Capture Type");
tagNameMap.put(new Integer(TAG_GAIN_CONTROL), "Gain Control");
tagNameMap.put(new Integer(TAG_CONTRAST), "Contrast");
tagNameMap.put(new Integer(TAG_SATURATION), "Saturation");
tagNameMap.put(new Integer(TAG_SHARPNESS), "Sharpness");
tagNameMap.put(new Integer(TAG_DEVICE_SETTING_DESCRIPTION), "Device Setting Description");
tagNameMap.put(new Integer(TAG_SUBJECT_DISTANCE_RANGE), "Subject Distance Range");
tagNameMap.put(new Integer(TAG_WIN_AUTHOR), "Windows XP Author");
tagNameMap.put(new Integer(TAG_WIN_COMMENT), "Windows XP Comment");
tagNameMap.put(new Integer(TAG_WIN_KEYWORDS), "Windows XP Keywords");
tagNameMap.put(new Integer(TAG_WIN_SUBJECT), "Windows XP Subject");
tagNameMap.put(new Integer(TAG_WIN_TITLE), "Windows XP Title");
tagNameMap.put(new Integer(TAG_MIN_SAMPLE_VALUE), "Minimum sample value");
tagNameMap.put(new Integer(TAG_MAX_SAMPLE_VALUE), "Maximum sample value");
}
public ExifDirectory()
{
this.setDescriptor(new ExifDescriptor(this));
}
public String getName()
{
return "Exif";
}
protected HashMap getTagNameMap()
{
return tagNameMap;
}
public byte[] getThumbnailData() throws MetadataException
{
if (!containsThumbnail())
return null;
return this.getByteArray(ExifDirectory.TAG_THUMBNAIL_DATA);
}
public void writeThumbnail(String filename) throws MetadataException, IOException
{
byte[] data = getThumbnailData();
if (data==null)
throw new MetadataException("No thumbnail data exists.");
FileOutputStream stream = null;
try {
stream = new FileOutputStream(filename);
stream.write(data);
} finally {
if (stream!=null)
stream.close();
}
}
/*
// This thumbnail extraction code is not complete, and is included to assist anyone who feels like looking into
// it. Please share any progress with the original author, and hence the community. Thanks.
/**
*
* @return
* @throws MetadataException
* /
public Image getThumbnailImage() throws MetadataException
{
if (!containsThumbnail())
return null;
int compression = 0;
try {
compression = this.getInt(ExifDirectory.TAG_COMPRESSION);
} catch (Throwable e) {
this.addError("Unable to determine thumbnail type " + e.getMessage());
}
final byte[] thumbnailBytes = getThumbnailData();
if (compression == ExifDirectory.COMPRESSION_JPEG)
{
// JPEG Thumbnail
// operate directly on thumbnailBytes
// try {
// int offset = this.getInt(ExifDirectory.TAG_THUMBNAIL_OFFSET);
// int length = this.getInt(ExifDirectory.TAG_THUMBNAIL_LENGTH);
// byte[] result = new byte[length];
// for (int i = 0; i<result.length; i++) {
// result[i] = _data[tiffHeaderOffset + offset + i];
// }
// this.setByteArray(ExifDirectory.TAG_THUMBNAIL_DATA, result);
// } catch (Throwable e) {
// this.addError("Unable to extract thumbnail: " + e.getMessage());
// }
// TODO decode the JPEG bytes as an image
return null; //new Image();
}
else if (compression == ExifDirectory.COMPRESSION_NONE)
{
// uncompressed thumbnail (raw RGB data)
if (!this.containsTag(ExifDirectory.TAG_PHOTOMETRIC_INTERPRETATION))
return null;
try
{
// If the image is RGB format, then convert it to a bitmap
final int photometricInterpretation = this.getInt(ExifDirectory.TAG_PHOTOMETRIC_INTERPRETATION);
if (photometricInterpretation == ExifDirectory.PHOTOMETRIC_INTERPRETATION_RGB)
{
// RGB
Image image = createImageFromRawRgb(thumbnailBytes);
return image;
}
else if (photometricInterpretation == ExifDirectory.PHOTOMETRIC_INTERPRETATION_YCBCR)
{
// YCbCr
Image image = createImageFromRawYCbCr(thumbnailBytes);
return image;
}
else if (photometricInterpretation == ExifDirectory.PHOTOMETRIC_INTERPRETATION_MONOCHROME)
{
// Monochrome
// TODO
return null;
}
} catch (Throwable e) {
this.addError("Unable to extract thumbnail: " + e.getMessage());
}
}
return null;
}
/**
* Handle the YCbCr thumbnail encoding used by Ricoh RDC4200/4300, Fuji DS-7/300 and DX-5/7/9 cameras.
*
* At DX-5/7/9, YCbCrSubsampling(0x0212) has values of '2,1', PlanarConfiguration(0x011c) has a value '1'. So the
* data align of this image is below.
*
* Y(0,0),Y(1,0),Cb(0,0),Cr(0,0), Y(2,0),Y(3,0),Cb(2,0),Cr(3.0), Y(4,0),Y(5,0),Cb(4,0),Cr(4,0). . . .
*
* The numerics in parenthesis are pixel coordinates. DX series' YCbCrCoefficients(0x0211) has values '0.299/0.587/0.114',
* ReferenceBlackWhite(0x0214) has values '0,255,128,255,128,255'. Therefore to convert from Y/Cb/Cr to RGB is;
*
* B(0,0)=(Cb-128)*(2-0.114*2)+Y(0,0)
* R(0,0)=(Cr-128)*(2-0.299*2)+Y(0,0)
* G(0,0)=(Y(0,0)-0.114*B(0,0)-0.299*R(0,0))/0.587
*
* Horizontal subsampling is a value '2', so you can calculate B(1,0)/R(1,0)/G(1,0) by using the Y(1,0) and Cr(0,0)/Cb(0,0).
* Repeat this conversion by value of ImageWidth(0x0100) and ImageLength(0x0101).
*
* @param thumbnailBytes
* @return
* @throws com.drew.metadata.MetadataException
* /
private Image createImageFromRawYCbCr(byte[] thumbnailBytes) throws MetadataException
{
/*
Y = 0.257R + 0.504G + 0.098B + 16
Cb = -0.148R - 0.291G + 0.439B + 128
Cr = 0.439R - 0.368G - 0.071B + 128
G = 1.164(Y-16) - 0.391(Cb-128) - 0.813(Cr-128)
R = 1.164(Y-16) + 1.596(Cr-128)
B = 1.164(Y-16) + 2.018(Cb-128)
R, G and B range from 0 to 255.
Y ranges from 16 to 235.
Cb and Cr range from 16 to 240.
http://www.faqs.org/faqs/graphics/colorspace-faq/
* /
int length = thumbnailBytes.length; // this.getInt(ExifDirectory.TAG_STRIP_BYTE_COUNTS);
final int imageWidth = this.getInt(ExifDirectory.TAG_THUMBNAIL_IMAGE_WIDTH);
final int imageHeight = this.getInt(ExifDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT);
// final int headerLength = 54;
// byte[] result = new byte[length + headerLength];
// // Add a windows BMP header described:
// // http://www.onicos.com/staff/iz/formats/bmp.html
// result[0] = 'B';
// result[1] = 'M'; // File Type identifier
// result[3] = (byte)(result.length / 256);
// result[2] = (byte)result.length;
// result[10] = (byte)headerLength;
// result[14] = 40; // MS Windows BMP header
// result[18] = (byte)imageWidth;
// result[22] = (byte)imageHeight;
// result[26] = 1; // 1 Plane
// result[28] = 24; // Colour depth
// result[34] = (byte)length;
// result[35] = (byte)(length / 256);
final BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
// order is YCbCr and image is upside down, bitmaps are BGR
//// for (int i = headerLength, dataOffset = length; i<result.length; i += 3, dataOffset -= 3)
// {
// final int y = thumbnailBytes[dataOffset - 2] & 0xFF;
// final int cb = thumbnailBytes[dataOffset - 1] & 0xFF;
// final int cr = thumbnailBytes[dataOffset] & 0xFF;
// if (y<16 || y>235 || cb<16 || cb>240 || cr<16 || cr>240)
// "".toString();
//
// int g = (int)(1.164*(y-16) - 0.391*(cb-128) - 0.813*(cr-128));
// int r = (int)(1.164*(y-16) + 1.596*(cr-128));
// int b = (int)(1.164*(y-16) + 2.018*(cb-128));
//
//// result[i] = (byte)b;
//// result[i + 1] = (byte)g;
//// result[i + 2] = (byte)r;
//
// // TODO compose the image here
// image.setRGB(1, 2, 3);
// }
return image;
}
/**
* Creates a thumbnail image in (Windows) BMP format from raw RGB data.
* @param thumbnailBytes
* @return
* @throws com.drew.metadata.MetadataException
* /
private Image createImageFromRawRgb(byte[] thumbnailBytes) throws MetadataException
{
final int length = thumbnailBytes.length; // this.getInt(ExifDirectory.TAG_STRIP_BYTE_COUNTS);
final int imageWidth = this.getInt(ExifDirectory.TAG_THUMBNAIL_IMAGE_WIDTH);
final int imageHeight = this.getInt(ExifDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT);
// final int headerlength = 54;
// final byte[] result = new byte[length + headerlength];
// // Add a windows BMP header described:
// // http://www.onicos.com/staff/iz/formats/bmp.html
// result[0] = 'B';
// result[1] = 'M'; // File Type identifier
// result[3] = (byte)(result.length / 256);
// result[2] = (byte)result.length;
// result[10] = (byte)headerlength;
// result[14] = 40; // MS Windows BMP header
// result[18] = (byte)imageWidth;
// result[22] = (byte)imageHeight;
// result[26] = 1; // 1 Plane
// result[28] = 24; // Colour depth
// result[34] = (byte)length;
// result[35] = (byte)(length / 256);
final BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
// order is RGB and image is upside down, bitmaps are BGR
// for (int i = headerlength, dataOffset = length; i<result.length; i += 3, dataOffset -= 3)
// {
// byte b = thumbnailBytes[dataOffset - 2];
// byte g = thumbnailBytes[dataOffset - 1];
// byte r = thumbnailBytes[dataOffset];
//
// // TODO compose the image here
// image.setRGB(1, 2, 3);
// }
return image;
}
*/
public boolean containsThumbnail()
{
return containsTag(ExifDirectory.TAG_THUMBNAIL_DATA);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -