Skip to content

Problem when saving RATIONAL values ​​in tags with FieldBit.Custom #110

Open
@ThereWereProblems

Description

@ThereWereProblems

Hi,

I need to write code that will convert a jpeg photo to tiff so that I can open it in another program.

I have a problem with saving tags that take the value RATIONAL.

So I'll start from the beginning:

I use TagExtender and I create tags so that I can save the GPS location of the photo and XMP data.

public void TagExtender(Tiff tiff)
{
    TiffFieldInfo[] tiffFieldInfo =
    {
        new TiffFieldInfo((TiffTag)GPSLatitudeRef, 1, 1, TiffType.ASCII, FieldBit.Custom, true, false, "GPSLatitudeRef"),
        new TiffFieldInfo((TiffTag)GPSLongitudeRef, 1, 1, TiffType.ASCII, FieldBit.Custom, true, false, "GPSLongitudeRef"),
        new TiffFieldInfo((TiffTag)GPSAltitudeRef, 1, 1, TiffType.BYTE, FieldBit.Custom, true, false, "GPSAltitudeRef"),
        new TiffFieldInfo((TiffTag)GPSLatitude, 3, 3, TiffType.RATIONAL, FieldBit.Custom, false, true, "GPSLatitude"),
        new TiffFieldInfo((TiffTag)GPSLongitude, 3, 3, TiffType.RATIONAL, FieldBit.Custom, false, true, "GPSLongitude"),
        new TiffFieldInfo((TiffTag)GPSAltitude, 1, 1, TiffType.RATIONAL, FieldBit.Custom, false, true, "GPSAltitude"),
        new TiffFieldInfo((TiffTag)XMP, -1, -1, TiffType.BYTE,  FieldBit.Custom, true, false, "XMP")
    };

    tiff.MergeFieldInfo(tiffFieldInfo, tiffFieldInfo.Length);

    if (m_parentExtender != null)
        m_parentExtender(tiff);
}

I set TagExtender and create a new photo and save the data one by one

 m_parentExtender = Tiff.SetTagExtender(TagExtender);

 using (Tiff output = Tiff.Open(outputPath, "w"))
 {
     output.SetDirectory(0);

     bool res;

     #region required tags for FLIR
     res = output.SetField(TiffTag.IMAGEWIDTH, width);
     res = output.SetField(TiffTag.IMAGELENGTH, height);
     // flir cameras record on 14 bits
     res = output.SetField(TiffTag.BITSPERSAMPLE, 14);
     res = output.SetField(TiffTag.COMPRESSION, Compression.NONE);
     res = output.SetField(TiffTag.PHOTOMETRIC, Photometric.MINISBLACK);
     res = output.SetField(TiffTag.ROWSPERSTRIP, height);

     // there is no problem with saving RATIONAL data
     res = output.SetField(TiffTag.XRESOLUTION, width);
     res = output.SetField(TiffTag.YRESOLUTION, height);

     res = output.SetField(TiffTag.RESOLUTIONUNIT, ResUnit.CENTIMETER);
     #endregion

     #region optional tags for FLIR
     var cameraInfo = image.CameraInformation;
     res = output.SetField(TiffTag.MODEL, cameraInfo.Model);
     res = output.SetField(TiffTag.SAMPLESPERPIXEL, 1);
     res = output.SetField(TiffTag.SOFTWARE, cameraInfo.Firmware);
     res = output.SetField(TiffTag.CAMERASERIALNUMBER, cameraInfo.SerialNumber);
     #endregion

     // this is where the problems begin
     #region GPS data
     var gps = image.GpsData;
     res = output.SetField((TiffTag)GPSLatitudeRef, gps.Latitude >= 0 ? "N" : "S");
     res = output.SetField((TiffTag)GPSLatitude, 3, ConvertToDMS(gps.Latitude));

     res = output.SetField((TiffTag)GPSLongitudeRef, gps.Longitude >= 0 ? "E" : "W");
     res = output.SetField((TiffTag)GPSLongitude, 3, ConvertToDMS(gps.Longitude));

     res = output.SetField((TiffTag)GPSAltitudeRef, gps.Altitude >= 0 ? 0 : 1); // 0 = above sea level, 1 = below sea level
     res = output.SetField((TiffTag)GPSAltitude, Math.Abs(gps.Altitude));

     byte[] xmpBytes = Encoding.UTF8.GetBytes(gps.Xmp);
     res = output.SetField((TiffTag)XMP, xmpBytes.Length, xmpBytes);
     #endregion

     #region other tags set on save
     res = output.SetField(TiffTag.ORIENTATION, Orientation.TOPLEFT);
     res = output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
     res = output.SetField(TiffTag.FILLORDER, FillOrder.MSB2LSB);

     // problem
     // gain mode, LowGainUp = 1, HighGainUp = 2, 
     res = output.SetField(TiffTag.EXIF_GAINCONTROL, maxTemp > 135 ? 1.0 : 2.0);
     #endregion

     output.CheckpointDirectory();

     var buffer = new byte[width * height * sizeof(short)];
     Buffer.BlockCopy(imageData, 0, buffer, 0, buffer.Length);
     output.WriteEncodedStrip(0, buffer, width * height * sizeof(short));
 }

 Tiff.SetTagExtender(m_parentExtender);

when I save photos exactly with the code as above I get an error when saving the GPSAltitude:

System.IndexOutOfRangeException: „Index was outside the bounds of the array.”

I solved this problem by passing an array instead of a single value

res = output.SetField((TiffTag)GPSAltitude, 1, new float[] { (float)Math.Abs(gps.Altitude) });

then the SetField method returns true.

However, in the case of the TiffTag.EXIF_GAINCONTROL tag, changing to the code below did not help. The method returns false

res = output.SetField(TiffTag.EXIF_GAINCONTROL, 1, new float[] { maxTemp > 135 ? 1.0f : 2.0f });

Additionally if we open the photo in the tag editor for example using this page. GPS altitude is outside the location nesting and is as a list and not a single field. Additionally, there is no reference N/S and W/E which are displayed for jpeg photos even though the SetField function returned true and I can read it in the code using this library.

image

I've noticed that the problem concerns tags that have FieldBit.Custom. Does anyone know how to deal with this problem. Maybe I'm doing something wrong?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions