Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nikon PictureControl directory extraction #635

Merged
merged 3 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Source/com/drew/metadata/exif/ExifTiffHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,26 @@ public boolean customProcessTag(final int tagOffset,
}
}

if (_currentDirectory instanceof NikonType2MakernoteDirectory) {
if (tagId == NikonType2MakernoteDirectory.TAG_PICTURE_CONTROL || tagId == NikonType2MakernoteDirectory.TAG_PICTURE_CONTROL_2) {
if (byteCount == 58) {
byte[] bytes = reader.getBytes(tagOffset, byteCount);
NikonPictureControl1Directory directory = NikonPictureControl1Directory.read(bytes);
directory.setParent(_currentDirectory);
_metadata.addDirectory(directory);
return true;
} else if (byteCount == 68) {
byte[] bytes = reader.getBytes(tagOffset, byteCount);
NikonPictureControl2Directory directory = NikonPictureControl2Directory.read(bytes);
directory.setParent(_currentDirectory);
_metadata.addDirectory(directory);
return true;
} else if (byteCount == 74) {
//TODO NikonPictureControl3Directory
}
}
}

return false;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.drew.metadata.exif.makernotes;

import com.drew.metadata.TagDescriptor;

import static com.drew.metadata.exif.makernotes.NikonPictureControl1Directory.TAG_FILTER_EFFECT;
import static com.drew.metadata.exif.makernotes.NikonPictureControl1Directory.TAG_PICTURE_CONTROL_ADJUST;
import static com.drew.metadata.exif.makernotes.NikonPictureControl1Directory.TAG_TONING_EFFECT;

public final class NikonPictureControl1Descriptor extends TagDescriptor<NikonPictureControl1Directory>
{
public NikonPictureControl1Descriptor(NikonPictureControl1Directory directory)
{
super(directory);
}

@Override
public String getDescription(int tagType)
{
switch (tagType) {
case TAG_PICTURE_CONTROL_ADJUST:
return getPictureControlAdjustDescription();
case TAG_FILTER_EFFECT:
return getFilterEffectDescription();
case TAG_TONING_EFFECT:
return getToningEffectDescription();
default:
return super.getDescription(tagType);
}
}

public String getPictureControlAdjustDescription()
{
return getIndexedDescription(
TAG_PICTURE_CONTROL_ADJUST,
"Default Settings",
"Quick Adjust",
"Full Control"
);
}

public String getFilterEffectDescription()
{
Integer value = _directory.getInteger(TAG_FILTER_EFFECT);
if (value == null) {
return null;
}

switch (value) {
case 0x80:
return "Off";
case 0x81:
return "Yellow";
case 0x82:
return "Orange";
case 0x83:
return "Red";
case 0x84:
return "Green";
case 0xFF:
return "N/A";
default:
return super.getDescription(TAG_FILTER_EFFECT);
}
}

public String getToningEffectDescription()
{
Integer value = _directory.getInteger(TAG_TONING_EFFECT);
if (value == null) {
return null;
}

switch (value) {
case 0x80:
return "B&W";
case 0x81:
return "Sepia";
case 0x82:
return "Cyanotype";
case 0x83:
return "Red";
case 0x84:
return "Yellow";
case 0x85:
return "Green";
case 0x86:
return "Blue-green";
case 0x87:
return "Blue";
case 0x88:
return "Purple-blue";
case 0x89:
return "Red-purple";
case 0xFF:
return "N/A";
default:
return super.getDescription(TAG_TONING_EFFECT);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.drew.metadata.exif.makernotes;

import com.drew.lang.Charsets;
import com.drew.lang.SequentialByteArrayReader;
import com.drew.lang.annotations.NotNull;
import com.drew.metadata.Directory;

import java.io.IOException;
import java.util.HashMap;

public final class NikonPictureControl1Directory extends Directory
{
// Tag values are offsets into the underlying data.
// Data from https://exiftool.org/TagNames/Nikon.html#PictureControl

public static final int TAG_PICTURE_CONTROL_VERSION = 0;
public static final int TAG_PICTURE_CONTROL_NAME = 4;
public static final int TAG_PICTURE_CONTROL_BASE = 24;
// skip 4
public static final int TAG_PICTURE_CONTROL_ADJUST = 48;
public static final int TAG_PICTURE_CONTROL_QUICK_ADJUST = 49;
public static final int TAG_SHARPNESS = 50;
public static final int TAG_CONTRAST = 51;
public static final int TAG_BRIGHTNESS = 52;
public static final int TAG_SATURATION = 53;
public static final int TAG_HUE_ADJUSTMENT = 54;
public static final int TAG_FILTER_EFFECT = 55;
public static final int TAG_TONING_EFFECT = 56;
public static final int TAG_TONING_SATURATION = 57;

private static final HashMap<Integer, String> TAG_NAME_MAP = new HashMap<>();

static
{
TAG_NAME_MAP.put(TAG_PICTURE_CONTROL_VERSION, "Picture Control Version");
TAG_NAME_MAP.put(TAG_PICTURE_CONTROL_NAME, "Picture Control Name");
TAG_NAME_MAP.put(TAG_PICTURE_CONTROL_BASE, "Picture Control Base");
TAG_NAME_MAP.put(TAG_PICTURE_CONTROL_ADJUST, "Picture Control Adjust");
TAG_NAME_MAP.put(TAG_PICTURE_CONTROL_QUICK_ADJUST, "Picture Control Quick Adjust");
TAG_NAME_MAP.put(TAG_SHARPNESS, "Sharpness");
TAG_NAME_MAP.put(TAG_CONTRAST, "Contrast");
TAG_NAME_MAP.put(TAG_BRIGHTNESS, "Brightness");
TAG_NAME_MAP.put(TAG_SATURATION, "Saturation");
TAG_NAME_MAP.put(TAG_HUE_ADJUSTMENT, "Hue Adjustment");
TAG_NAME_MAP.put(TAG_FILTER_EFFECT, "Filter Effect");
TAG_NAME_MAP.put(TAG_TONING_EFFECT, "Toning Effect");
TAG_NAME_MAP.put(TAG_TONING_SATURATION, "Toning Saturation");
}

public NikonPictureControl1Directory()
{
setDescriptor(new NikonPictureControl1Descriptor(this));
}

@NotNull
@Override
public String getName()
{
return "Nikon PictureControl 1";
}

@NotNull
@Override
protected HashMap<Integer, String> getTagNameMap()
{
return TAG_NAME_MAP;
}

public static NikonPictureControl1Directory read(byte[] bytes) throws IOException
{
final int EXPECTED_LENGTH = 58;

if (bytes.length != EXPECTED_LENGTH) {
throw new IllegalArgumentException("Must have " + EXPECTED_LENGTH + " bytes.");
}

SequentialByteArrayReader reader = new SequentialByteArrayReader(bytes);

NikonPictureControl1Directory directory = new NikonPictureControl1Directory();

directory.setObject(TAG_PICTURE_CONTROL_VERSION, reader.getStringValue(4, Charsets.UTF_8));
directory.setObject(TAG_PICTURE_CONTROL_NAME, reader.getStringValue(20, Charsets.UTF_8));
directory.setObject(TAG_PICTURE_CONTROL_BASE, reader.getStringValue(20, Charsets.UTF_8));
reader.skip(4);
directory.setObject(TAG_PICTURE_CONTROL_ADJUST, reader.getUInt8());
directory.setObject(TAG_PICTURE_CONTROL_QUICK_ADJUST, reader.getUInt8());
directory.setObject(TAG_SHARPNESS, reader.getUInt8());
directory.setObject(TAG_CONTRAST, reader.getUInt8());
directory.setObject(TAG_BRIGHTNESS, reader.getUInt8());
directory.setObject(TAG_SATURATION, reader.getUInt8());
directory.setObject(TAG_HUE_ADJUSTMENT, reader.getUInt8());
directory.setObject(TAG_FILTER_EFFECT, reader.getUInt8());
directory.setObject(TAG_TONING_EFFECT, reader.getUInt8());
directory.setObject(TAG_TONING_SATURATION, reader.getUInt8());

assert (reader.getPosition() == EXPECTED_LENGTH);

return directory;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.drew.metadata.exif.makernotes;

import com.drew.metadata.TagDescriptor;

import static com.drew.metadata.exif.makernotes.NikonPictureControl2Directory.TAG_FILTER_EFFECT;
import static com.drew.metadata.exif.makernotes.NikonPictureControl2Directory.TAG_PICTURE_CONTROL_ADJUST;
import static com.drew.metadata.exif.makernotes.NikonPictureControl2Directory.TAG_TONING_EFFECT;

public final class NikonPictureControl2Descriptor extends TagDescriptor<NikonPictureControl2Directory>
{
public NikonPictureControl2Descriptor(NikonPictureControl2Directory directory)
{
super(directory);
}

@Override
public String getDescription(int tagType)
{
switch (tagType) {
case TAG_PICTURE_CONTROL_ADJUST:
return getPictureControlAdjustDescription();
case TAG_FILTER_EFFECT:
return getFilterEffectDescription();
case TAG_TONING_EFFECT:
return getToningEffectDescription();
default:
return super.getDescription(tagType);
}
}

public String getPictureControlAdjustDescription()
{
return getIndexedDescription(
TAG_PICTURE_CONTROL_ADJUST,
"Default Settings",
"Quick Adjust",
"Full Control"
);
}

public String getFilterEffectDescription()
{
byte[] value = _directory.getByteArray(TAG_FILTER_EFFECT);
if (value == null) {
return null;
}

switch (value[0]) {
case (byte) 0x80:
return "Off";
case (byte) 0x81:
return "Yellow";
case (byte) 0x82:
return "Orange";
case (byte) 0x83:
return "Red";
case (byte) 0x84:
return "Green";
case (byte) 0xFF:
return "N/A";
default:
return super.getDescription(TAG_FILTER_EFFECT);
}
}

public String getToningEffectDescription()
{
byte[] value = _directory.getByteArray(TAG_TONING_EFFECT);
if (value == null) {
return null;
}

switch (value[0]) {
case (byte) 0x80:
return "B&W";
case (byte) 0x81:
return "Sepia";
case (byte) 0x82:
return "Cyanotype";
case (byte) 0x83:
return "Red";
case (byte) 0x84:
return "Yellow";
case (byte) 0x85:
return "Green";
case (byte) 0x86:
return "Blue-green";
case (byte) 0x87:
return "Blue";
case (byte) 0x88:
return "Purple-blue";
case (byte) 0x89:
return "Red-purple";
case (byte) 0xFF:
return "N/A";
default:
return super.getDescription(TAG_TONING_EFFECT);
}
}
}
Loading
Loading