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

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

Open
ThereWereProblems opened this issue Sep 9, 2024 · 0 comments

Comments

@ThereWereProblems
Copy link

ThereWereProblems commented Sep 9, 2024

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants