blob: 3598658cb349976e4732f759f742c1624d56e70f [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.drill.exec.store.image;
import java.util.Date;
import java.util.TimeZone;
import org.apache.hadoop.fs.FileStatus;
import com.drew.imaging.FileType;
import com.drew.imaging.png.PngChunkType;
import com.drew.imaging.png.PngColorType;
import com.drew.lang.annotations.NotNull;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.MetadataException;
import com.drew.metadata.avi.AviDirectory;
import com.drew.metadata.bmp.BmpHeaderDirectory;
import com.drew.metadata.eps.EpsDirectory;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.drew.metadata.exif.ExifSubIFDDirectory;
import com.drew.metadata.gif.GifControlDirectory;
import com.drew.metadata.gif.GifHeaderDirectory;
import com.drew.metadata.ico.IcoDirectory;
import com.drew.metadata.jfif.JfifDirectory;
import com.drew.metadata.jpeg.JpegDirectory;
import com.drew.metadata.mov.QuickTimeDirectory;
import com.drew.metadata.mov.media.QuickTimeSoundDirectory;
import com.drew.metadata.mov.media.QuickTimeVideoDirectory;
import com.drew.metadata.mp4.Mp4Directory;
import com.drew.metadata.mp4.media.Mp4SoundDirectory;
import com.drew.metadata.mp4.media.Mp4VideoDirectory;
import com.drew.metadata.pcx.PcxDirectory;
import com.drew.metadata.photoshop.PsdHeaderDirectory;
import com.drew.metadata.png.PngDirectory;
import com.drew.metadata.wav.WavDirectory;
import com.drew.metadata.webp.WebpDirectory;
public class GenericMetadataReader
{
public void read(@NotNull FileType fileType, @NotNull FileStatus fileStatus, @NotNull Metadata metadata)
{
GenericMetadataDirectory directory = new GenericMetadataDirectory();
boolean skipEPSPreview = false;
directory.setLong(GenericMetadataDirectory.TAG_FILE_SIZE, fileStatus.getLen());
// Add local time zone offset to store the last modified time as local time
// just like TO_TIMESTAMP(UNIX_TIMESTAMP()) returns local time
directory.setDate(GenericMetadataDirectory.TAG_FILE_DATE_TIME,
new Date(fileStatus.getModificationTime() + TimeZone.getDefault().getRawOffset()));
directory.setString(GenericMetadataDirectory.TAG_FORMAT, fileType.name().toUpperCase());
for (Directory dir : metadata.getDirectories()) {
if (dir instanceof JpegDirectory) {
final JpegDirectory jpegDir = (JpegDirectory)dir;
directory.setPixelWidth(jpegDir, JpegDirectory.TAG_IMAGE_WIDTH);
directory.setPixelHeight(jpegDir, JpegDirectory.TAG_IMAGE_HEIGHT);
directory.setBitPerPixel(jpegDir, JpegDirectory.TAG_DATA_PRECISION, JpegDirectory.TAG_NUMBER_OF_COMPONENTS);
continue;
}
if (dir instanceof JfifDirectory) {
final JfifDirectory jfifDir = (JfifDirectory)dir;
try {
final int unit = jfifDir.getResUnits();
if (unit == 1 || unit == 2) {
directory.setDPIWidth(jfifDir, JfifDirectory.TAG_RESX, unit == 1 ? 1.0 : 2.54);
directory.setDPIHeight(jfifDir, JfifDirectory.TAG_RESY, unit == 1 ? 1.0 : 2.54);
}
} catch (MetadataException e) {
// Nothing needs to be done
}
continue;
}
if (dir instanceof ExifIFD0Directory) {
if (skipEPSPreview) {
skipEPSPreview = false;
continue;
}
final ExifIFD0Directory ifd0Dir = (ExifIFD0Directory)dir;
directory.setPixelWidth(ifd0Dir, ExifIFD0Directory.TAG_IMAGE_WIDTH);
directory.setPixelHeight(ifd0Dir, ExifIFD0Directory.TAG_IMAGE_HEIGHT);
directory.setOrientation(ifd0Dir, ExifIFD0Directory.TAG_ORIENTATION);
try {
final int unit = ifd0Dir.getInt(ExifIFD0Directory.TAG_RESOLUTION_UNIT);
if (unit == 2 || unit == 3) {
directory.setDPIWidth(ifd0Dir, ExifIFD0Directory.TAG_X_RESOLUTION, unit == 2 ? 1.0 : 2.54);
directory.setDPIHeight(ifd0Dir, ExifIFD0Directory.TAG_Y_RESOLUTION, unit == 2 ? 1.0 : 2.54);
}
} catch (MetadataException e) {
// Nothing needs to be done
}
int[] bitPerSample = ifd0Dir.getIntArray(ExifIFD0Directory.TAG_BITS_PER_SAMPLE);
if (bitPerSample != null) {
int bitsPerPixel = 0;
for (int n : bitPerSample) {
bitsPerPixel += n;
}
directory.setBitPerPixel(bitsPerPixel);
}
continue;
}
if (dir instanceof ExifSubIFDDirectory) {
final ExifSubIFDDirectory subIFDDir = (ExifSubIFDDirectory)dir;
directory.setPixelWidth(subIFDDir, ExifSubIFDDirectory.TAG_EXIF_IMAGE_WIDTH);
directory.setPixelHeight(subIFDDir, ExifSubIFDDirectory.TAG_EXIF_IMAGE_HEIGHT);
continue;
}
if (dir instanceof PsdHeaderDirectory) {
final PsdHeaderDirectory psdDir = (PsdHeaderDirectory)dir;
directory.setPixelWidth(psdDir, PsdHeaderDirectory.TAG_IMAGE_WIDTH);
directory.setPixelHeight(psdDir, PsdHeaderDirectory.TAG_IMAGE_HEIGHT);
directory.setBitPerPixel(
psdDir, PsdHeaderDirectory.TAG_BITS_PER_CHANNEL, PsdHeaderDirectory.TAG_CHANNEL_COUNT);
directory.setColorMode(psdDir, PsdHeaderDirectory.TAG_COLOR_MODE);
continue;
}
if (dir instanceof PngDirectory) {
final PngDirectory pngDir = (PngDirectory)dir;
if (pngDir.getPngChunkType() == PngChunkType.IHDR) {
directory.setPixelWidth(pngDir, PngDirectory.TAG_IMAGE_WIDTH);
directory.setPixelHeight(pngDir, PngDirectory.TAG_IMAGE_HEIGHT);
try {
int numOfComponent = 1;
int colorType = pngDir.getInt(PngDirectory.TAG_COLOR_TYPE);
if (colorType == PngColorType.INDEXED_COLOR.getNumericValue()) {
directory.setColorMode("Indexed");
} else if (colorType == PngColorType.GREYSCALE.getNumericValue()) {
directory.setColorMode("Grayscale");
} else if (colorType == PngColorType.GREYSCALE_WITH_ALPHA.getNumericValue()) {
numOfComponent = 2;
directory.setColorMode("Grayscale");
directory.setAlpha(true);
} else if (colorType == PngColorType.TRUE_COLOR.getNumericValue()) {
numOfComponent = 3;
} else if (colorType == PngColorType.TRUE_COLOR_WITH_ALPHA.getNumericValue()) {
numOfComponent = 4;
directory.setAlpha(true);
}
directory.setBitPerPixel(pngDir.getInt(PngDirectory.TAG_BITS_PER_SAMPLE) * numOfComponent);
} catch (MetadataException e) {
// Nothing needs to be done
}
continue;
}
if (pngDir.getPngChunkType() == PngChunkType.pHYs) {
try {
final int unit = pngDir.getInt(PngDirectory.TAG_UNIT_SPECIFIER);
if (unit == 1) {
directory.setDPIWidth(pngDir, PngDirectory.TAG_PIXELS_PER_UNIT_X, 0.0254);
directory.setDPIHeight(pngDir, PngDirectory.TAG_PIXELS_PER_UNIT_Y, 0.0254);
}
} catch (MetadataException e) {
// Nothing needs to be done
}
continue;
}
if (pngDir.getPngChunkType() == PngChunkType.tRNS) {
directory.setAlpha(true);
continue;
}
continue;
}
if (dir instanceof BmpHeaderDirectory) {
final BmpHeaderDirectory bmpDir = (BmpHeaderDirectory)dir;
directory.setPixelWidth(bmpDir, BmpHeaderDirectory.TAG_IMAGE_WIDTH);
directory.setPixelHeight(bmpDir, BmpHeaderDirectory.TAG_IMAGE_HEIGHT);
directory.setDPIWidth(bmpDir, BmpHeaderDirectory.TAG_X_PIXELS_PER_METER, 0.0254);
directory.setDPIHeight(bmpDir, BmpHeaderDirectory.TAG_Y_PIXELS_PER_METER, 0.0254);
try {
final int bitsPerPixel = bmpDir.getInt(BmpHeaderDirectory.TAG_BITS_PER_PIXEL);
if (bitsPerPixel <= 8) {
directory.setColorMode("Indexed");
}
directory.setBitPerPixel(bitsPerPixel);
} catch (MetadataException e) {
// Nothing needs to be done
}
continue;
}
if (dir instanceof GifHeaderDirectory) {
final GifHeaderDirectory gifDir = (GifHeaderDirectory)dir;
directory.setPixelWidth(gifDir, GifHeaderDirectory.TAG_IMAGE_WIDTH);
directory.setPixelHeight(gifDir, GifHeaderDirectory.TAG_IMAGE_HEIGHT);
directory.setColorMode("Indexed");
directory.setBitPerPixel(gifDir, GifHeaderDirectory.TAG_BITS_PER_PIXEL);
continue;
}
if (dir instanceof GifControlDirectory) {
final GifControlDirectory gifControlDir = (GifControlDirectory)dir;
directory.setAlpha(gifControlDir, GifControlDirectory.TAG_TRANSPARENT_COLOR_FLAG);
continue;
}
if (dir instanceof IcoDirectory) {
final IcoDirectory icoDir = (IcoDirectory)dir;
directory.setPixelWidth(icoDir, IcoDirectory.TAG_IMAGE_WIDTH);
directory.setPixelHeight(icoDir, IcoDirectory.TAG_IMAGE_HEIGHT);
try {
if (icoDir.getInt(IcoDirectory.TAG_COLOUR_PALETTE_SIZE) != 0) {
directory.setColorMode("Indexed");
}
} catch (MetadataException e) {
// Nothing needs to be done
}
directory.setBitPerPixel(icoDir, IcoDirectory.TAG_BITS_PER_PIXEL);
directory.setAlpha(true);
continue;
}
if (dir instanceof PcxDirectory) {
final PcxDirectory pcxDir = (PcxDirectory)dir;
try {
directory.setPixelWidth(pcxDir.getInt(PcxDirectory.TAG_XMAX) - pcxDir.getInt(PcxDirectory.TAG_XMIN) + 1);
} catch (MetadataException e) {
// Nothing needs to be done
}
try {
directory.setPixelHeight(pcxDir.getInt(PcxDirectory.TAG_YMAX) - pcxDir.getInt(PcxDirectory.TAG_YMIN) + 1);
} catch (MetadataException e) {
// Nothing needs to be done
}
directory.setDPIWidth(pcxDir, PcxDirectory.TAG_HORIZONTAL_DPI);
directory.setDPIHeight(pcxDir, PcxDirectory.TAG_VERTICAL_DPI);
directory.setBitPerPixel(pcxDir, PcxDirectory.TAG_BITS_PER_PIXEL, PcxDirectory.TAG_COLOR_PLANES);
try {
int colorPlanes = pcxDir.getInt(PcxDirectory.TAG_COLOR_PLANES);
if (colorPlanes == 1) {
if (pcxDir.getInt(PcxDirectory.TAG_PALETTE_TYPE) == 2) {
directory.setColorMode("Grayscale");
} else {
directory.setColorMode("Indexed");
}
}
directory.setAlpha(colorPlanes == 4);
} catch (MetadataException e) {
// Nothing needs to be done
}
continue;
}
if (dir instanceof WavDirectory) {
final WavDirectory wavDir = (WavDirectory)dir;
directory.setColorMode("N/A");
directory.setDuration(wavDir, WavDirectory.TAG_DURATION);
directory.setAudioCodec(wavDir, WavDirectory.TAG_FORMAT);
directory.setAudioSampleSize(wavDir, WavDirectory.TAG_BITS_PER_SAMPLE);
directory.setAudioSampleRate(wavDir, WavDirectory.TAG_SAMPLES_PER_SEC);
}
if (dir instanceof AviDirectory) {
final AviDirectory aviDir = (AviDirectory)dir;
directory.setPixelWidth(aviDir, AviDirectory.TAG_WIDTH);
directory.setPixelHeight(aviDir, AviDirectory.TAG_HEIGHT);
directory.setDuration(aviDir, AviDirectory.TAG_DURATION);
directory.setVideoCodec(aviDir, AviDirectory.TAG_VIDEO_CODEC);
directory.setFrameRate(aviDir, AviDirectory.TAG_FRAMES_PER_SECOND);
directory.setAudioCodec(aviDir, AviDirectory.TAG_AUDIO_CODEC);
directory.setAudioSampleRate(aviDir, AviDirectory.TAG_SAMPLES_PER_SECOND);
continue;
}
if (dir instanceof WebpDirectory) {
final WebpDirectory webpDir = (WebpDirectory)dir;
directory.setPixelWidth(webpDir, WebpDirectory.TAG_IMAGE_WIDTH);
directory.setPixelHeight(webpDir, WebpDirectory.TAG_IMAGE_HEIGHT);
directory.setAlpha(webpDir, WebpDirectory.TAG_HAS_ALPHA);
continue;
}
if (dir instanceof QuickTimeVideoDirectory) {
final QuickTimeVideoDirectory qtVideoDir = (QuickTimeVideoDirectory)dir;
directory.setPixelWidth(qtVideoDir, QuickTimeVideoDirectory.TAG_WIDTH);
directory.setPixelHeight(qtVideoDir, QuickTimeVideoDirectory.TAG_HEIGHT);
directory.setDPIWidth(qtVideoDir, QuickTimeVideoDirectory.TAG_HORIZONTAL_RESOLUTION);
directory.setDPIHeight(qtVideoDir, QuickTimeVideoDirectory.TAG_VERTICAL_RESOLUTION);
try {
int bitsPerPixel = qtVideoDir.getInt(QuickTimeVideoDirectory.TAG_DEPTH) % 32;
directory.setBitPerPixel(bitsPerPixel);
} catch (MetadataException e) {
// Nothing needs to be done
}
directory.setDuration(qtVideoDir, QuickTimeVideoDirectory.TAG_DURATION);
directory.setVideoCodec(qtVideoDir, QuickTimeVideoDirectory.TAG_COMPRESSION_TYPE);
directory.setFrameRate(qtVideoDir, QuickTimeVideoDirectory.TAG_FRAME_RATE);
continue;
}
if (dir instanceof QuickTimeSoundDirectory) {
final QuickTimeSoundDirectory qtSoundDir = (QuickTimeSoundDirectory)dir;
directory.setAudioCodec(qtSoundDir, QuickTimeSoundDirectory.TAG_AUDIO_FORMAT);
directory.setAudioSampleSize(qtSoundDir, QuickTimeSoundDirectory.TAG_AUDIO_SAMPLE_SIZE);
directory.setAudioSampleRate(qtSoundDir, QuickTimeSoundDirectory.TAG_AUDIO_SAMPLE_RATE);
continue;
}
if (dir instanceof QuickTimeDirectory) {
final QuickTimeDirectory qtDir = (QuickTimeDirectory)dir;
directory.setDuration(qtDir, QuickTimeDirectory.TAG_DURATION);
continue;
}
if (dir instanceof Mp4VideoDirectory) {
final Mp4VideoDirectory mp4VideoDir = (Mp4VideoDirectory)dir;
directory.setPixelWidth(mp4VideoDir, Mp4VideoDirectory.TAG_WIDTH);
directory.setPixelHeight(mp4VideoDir, Mp4VideoDirectory.TAG_HEIGHT);
directory.setDPIWidth(mp4VideoDir, Mp4VideoDirectory.TAG_HORIZONTAL_RESOLUTION);
directory.setDPIHeight(mp4VideoDir, Mp4VideoDirectory.TAG_VERTICAL_RESOLUTION);
try {
int bitsPerPixel = mp4VideoDir.getInt(Mp4VideoDirectory.TAG_DEPTH) % 32;
directory.setBitPerPixel(bitsPerPixel);
} catch (MetadataException e) {
// Nothing needs to be done
}
directory.setDuration(mp4VideoDir, Mp4VideoDirectory.TAG_DURATION);
directory.setVideoCodec(mp4VideoDir, Mp4VideoDirectory.TAG_COMPRESSION_TYPE);
directory.setFrameRate(mp4VideoDir, Mp4VideoDirectory.TAG_FRAME_RATE);
continue;
}
if (dir instanceof Mp4SoundDirectory) {
final Mp4SoundDirectory mp4SoundDir = (Mp4SoundDirectory)dir;
directory.setAudioCodec(mp4SoundDir, Mp4SoundDirectory.TAG_AUDIO_FORMAT);
directory.setAudioSampleSize(mp4SoundDir, Mp4SoundDirectory.TAG_AUDIO_SAMPLE_SIZE);
directory.setAudioSampleRate(mp4SoundDir, Mp4SoundDirectory.TAG_AUDIO_SAMPLE_RATE);
continue;
}
if (dir instanceof Mp4Directory) {
final Mp4Directory mp4Dir = (Mp4Directory)dir;
directory.setDuration(mp4Dir, Mp4Directory.TAG_DURATION);
continue;
}
if (dir instanceof EpsDirectory) {
final EpsDirectory epsDir = (EpsDirectory)dir;
directory.setPixelWidth(epsDir, EpsDirectory.TAG_IMAGE_WIDTH);
directory.setPixelHeight(epsDir, EpsDirectory.TAG_IMAGE_HEIGHT);
try {
int bitsPerPixel = 24;
int colorType = epsDir.getInt(EpsDirectory.TAG_COLOR_TYPE);
if (colorType == 1) {
String imageData = epsDir.getString(EpsDirectory.TAG_IMAGE_DATA);
if (imageData != null && imageData.split(" ")[2].equals("1")) {
bitsPerPixel = 1;
directory.setColorMode("Bitmap");
} else {
bitsPerPixel = 8;
directory.setColorMode("Grayscale");
}
} else if (colorType == 2) {
directory.setColorMode("Lab");
} else if (colorType == 4) {
bitsPerPixel = 32;
directory.setColorMode("CMYK");
}
directory.setBitPerPixel(bitsPerPixel);
skipEPSPreview = epsDir.containsTag(EpsDirectory.TAG_TIFF_PREVIEW_SIZE);
} catch (MetadataException e) {
// Nothing needs to be done
}
continue;
}
}
// Set default value if empty
directory.setPixelWidth(0);
directory.setPixelHeight(0);
directory.setOrientation(0);
directory.setDPIWidth(0.0);
directory.setDPIHeight(0.0);
directory.setColorMode("RGB");
directory.setBitPerPixel(0);
directory.setAlpha(false);
directory.setDuration(0);
directory.setVideoCodec("Unknown");
directory.setFrameRate(0.0);
directory.setAudioCodec("Unknown");
directory.setAudioSampleSize(0);
directory.setAudioSampleRate(0.0);
metadata.addDirectory(directory);
}
}