areaDetector / ADCore

The home of the core components of the EPICS areaDetector software. It includes base classes for drivers and code for all of the standard plugins.
https://areadetector.github.io/areaDetector
Other
20 stars 69 forks source link

random data in areaDetector TIFF header #519

Open mp49 opened 1 week ago

mp49 commented 1 week ago

I came across an issue with the TIFF file writing plugin in ADCore. I am adding parameters from my areaDetector driver to the NDAttributeList, using an XML file like:

<?xml version="1.0" standalone="no" ?>
<Attributes>
  <Attribute name="SizeX" type="PARAM"  source="SIZE_X" datatype="INT"     description=""/>
  <Attribute name="SizeY" type="PARAM"  source="SIZE_Y" datatype="INT"     description=""/>
</Attributes>

And this should produce a TIFF header that includes:

 Tag 65012: SizeX:1024
 Tag 65013: SizeY:1024

However, I mostly see the integer data are corrupted, like:

 Tag 65012: SizeX:4742400410323518464
 Tag 65013: SizeY:4742400410323518464

I think I’ve tracked it down to the TIFF file writing plugin. When 64-bit integer support was added, the existing 32-bit support was removed, and we treat all integers the same:

In NDFileTIFF.cpp:

switch (attrDataType) {
            case NDAttrInt8:
            case NDAttrUInt8:
            case NDAttrInt16:
            case NDAttrUInt16:
            case NDAttrInt32:
            case NDAttrUInt32:
            case NDAttrInt64:
            case NDAttrUInt64: {
                pAttribute->getValue(attrDataType, &value.i64);
                epicsSnprintf(tagString, sizeof(tagString)-1, "%s:%lld", attributeName, value.i64);
                break;
            }
              ……

However, the attribute data is read via ‘getValue’ using a void pointer and I think that’s causing an issue – converting data types without a proper type cast. I was able to solve it by restoring the 32-bit support:

switch (attrDataType) {
            case NDAttrInt8:
            case NDAttrUInt8:
            case NDAttrInt16:
            case NDAttrUInt16:
            case NDAttrInt32:
            case NDAttrUInt32: {
                pAttribute->getValue(attrDataType, &value.i32);
                epicsSnprintf(tagString, sizeof(tagString)-1, "%s:%d", attributeName, value.i32);
                break;
            }
            case NDAttrInt64:
            case NDAttrUInt64: {
                pAttribute->getValue(attrDataType, &value.i64);
                epicsSnprintf(tagString, sizeof(tagString)-1, "%s:%lld", attributeName, value.i64);
                break;
            }
              …..
MarkRivers commented 1 week ago

I have created an alternative pull request for this: #520