The Windows is Russian environment, use putAndInsertOFStringArray() wirte 1.2/1.3 in tag DCM_PixelSpacing lost number

All other questions regarding DCMTK

Moderator: Moderator Team

Post Reply
Message
Author
Emma_cao
Posts: 13
Joined: Mon, 2016-12-05, 10:51

The Windows is Russian environment, use putAndInsertOFStringArray() wirte 1.2/1.3 in tag DCM_PixelSpacing lost number

#1 Post by Emma_cao »

Dear all,
I use putAndInsertOFStringArray() to write 1.2/1.3 to tag DCM_PixelSpacing of a image.
but the result is 1.0/1.0;
I find the lost is created by the function OFStandard::atof();
the version my complied, DISABLE_OFSTD_ATOF is not defined. so the function OFStandard::atof() is coded as following

Code: Select all

double OFStandard::atof(const char *s, OFBool *success)
{
    if (success) *success = OFFalse;
    const char *p = s;
    char c;
    int sign = 0;
    int expSign = 0;
    double fraction;
    int exponent = 0; // Exponent read from "EX" field.
    const char *pExp; // Temporarily holds location of exponent in string.

    /* Exponent that derives from the fractional part.  Under normal
     * circumstances, it is the negative of the number of digits in F.
     * However, if I is very long, the last digits of I get dropped
     * (otherwise a long I with a large negative exponent could cause an
     * unnecessary overflow on I alone).  In this case, fracExp is
     * incremented one for each dropped digit.
     */
    int fracExp = 0;

    // Strip off leading blanks and check for a sign.
    while (isspace(OFstatic_cast(unsigned char, *p))) ++p;

    if (*p == '-')
    {
        sign = 1;
        ++p;
    }
    else
    {
        if (*p == '+') ++p;
    }

    //Check for special cases like NaN
    if ((p[0] == 'n' || p[0] == 'N') && (p[1] == 'a' || p[1] == 'A') && (p[2] == 'n' || p[2] == 'N')) {
        if (success) *success = OFTrue;
        return OFnumeric_limits<double>::quiet_NaN();
    }

    if ((p[0] == 'i' || p[0] == 'I') && (p[1] == 'n' || p[1] == 'N') && (p[2] == 'f' || p[2] == 'F')) {
        if (success) *success = OFTrue;
        return sign ? -OFnumeric_limits<double>::infinity() : OFnumeric_limits<double>::infinity();
    }
    // Count the number of digits in the mantissa (including the decimal
    // point), and also locate the decimal point.

    int decPt = -1; // Number of mantissa digits BEFORE decimal point.
    int mantSize;     // Number of digits in mantissa.
    for (mantSize = 0; ; ++mantSize)
    {
        c = *p;
        if (!isdigit(OFstatic_cast(unsigned char, c)))
        {
            if ((c != '.') || (decPt >= 0)) break;
            decPt = mantSize;
        }
        ++p;
    }

    /*
     * Now suck up the digits in the mantissa.  Use two integers to
     * collect 9 digits each (this is faster than using floating-point).
     * If the mantissa has more than 18 digits, ignore the extras, since
     * they can't affect the value anyway.
     */

    pExp = p;
    p -= mantSize;
    if (decPt < 0)
      decPt = mantSize;
      else mantSize -= 1; // One of the digits was the point

    if (mantSize > 18)
    {
        fracExp = decPt - 18;
        mantSize = 18;
    }
    else
    {
        fracExp = decPt - mantSize;
    }

    if (mantSize == 0)
    {
      // subject sequence does not have expected form.
      // return 0 and leave success flag set to false
      return 0.0;
    }
    else
    {
        int frac1 = 0;
        for ( ; mantSize > 9; mantSize -= 1)
        {
            c = *p;
            ++p;
            if (c == '.')
            {
                c = *p;
                ++p;
            }
            frac1 = 10*frac1 + (c - '0');
        }
        int frac2 = 0;
        for (; mantSize > 0; mantSize -= 1)
        {
            c = *p;
            ++p;
            if (c == '.')
            {
                c = *p;
                ++p;
            }
            frac2 = 10*frac2 + (c - '0');
        }
        fraction = (1.0e9 * frac1) + frac2;
    }

    // Skim off the exponent.
    p = pExp;
    if ((*p == 'E') || (*p == 'e'))
    {
        ++p;
        if (*p == '-')
        {
            expSign = 1;
            ++p;
        }
        else
        {
            if (*p == '+') ++p;
            expSign = 0;
        }
        while (isdigit(OFstatic_cast(unsigned char, *p)))
        {
            exponent = exponent * 10 + (*p - '0');
            ++p;
        }
    }

    if (expSign)
       exponent = fracExp - exponent;
       else exponent = fracExp + exponent;

    /*
     * Generate a floating-point number that represents the exponent.
     * Do this by processing the exponent one bit at a time to combine
     * many powers of 2 of 10. Then combine the exponent with the
     * fraction.
     */

    if (exponent < 0)
    {
        expSign = 1;
        exponent = -exponent;
    }
    else expSign = 0;

    if (exponent > ATOF_MAXEXPONENT) exponent = ATOF_MAXEXPONENT;
    double dblExp = 1.0;
    for (const double *d = atof_powersOf10; exponent != 0; exponent >>= 1, ++d)
    {
        if (exponent & 01) dblExp *= *d;
    }

    if (expSign)
      fraction /= dblExp;
      else fraction *= dblExp;

    if (success) *success = OFTrue;
    if (sign) return -fraction;
    return fraction;
}
How to solve this problem?
Best Wishes!

J. Riesmeier
DCMTK Developer
Posts: 2501
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: The Windows is Russian environment, use putAndInsertOFStringArray() wirte 1.2/1.3 in tag DCM_PixelSpacing lost numbe

#2 Post by J. Riesmeier »

Could you please post how you call the method putAndInsertOFStringArray(), i.e. including the parameters.

Emma_cao
Posts: 13
Joined: Mon, 2016-12-05, 10:51

Re: The Windows is Russian environment, use putAndInsertOFStringArray() wirte 1.2/1.3 in tag DCM_PixelSpacing lost numbe

#3 Post by Emma_cao »

sorry, I express this uncorrectly.

This is the question.

Code: Select all

case EVR_DS:
	case EVR_FD:
		{
			for (unsigned long i = 0; i < vm; i++)
			{						
				Float64 val;
				OFCondition con = delem->getFloat64(val, i);
				OFString strVal;
				std::string tag;
				con = delem->getOFString(strVal, i);
				if (con == EC_Normal)
				{
					//char strOut[1024];
					//sprintf_s(strOut, 1024, "%.2f", val);
					//tagValue += strOut;
					string_v str;
					str = DoubleToDecimalString(val);
					tagValue += str.c_cstr();
					if (i != vm-1)
						tagValue += "|";

					tag += strVal.c_str();
					if (i != vm - 1)
						tag += "|";
				}
			}
		}
		break;
I read the tagvalue using the upside code. DCM_PixelSpacing value is 1.2/1.3, but the result is 1.0/1.0;
the error is happend in the following code.

Code: Select all

OFCondition DcmDecimalString::getFloat64(Float64 &doubleVal,
                                         const unsigned long pos)
{
    /* get decimal string value */
    OFString str;
    OFCondition l_error = getOFString(str, pos, OFTrue /*normalize*/);
    if (l_error.good())
    {
        OFBool success = OFFalse;
        /* convert string to float value */
        doubleVal = OFStandard::atof(str.c_str(), &success);
        if (!success)
            l_error = EC_CorruptedData;
    }
    return l_error;
}
str = 1,2. but doubleVal = 1.0

J. Riesmeier
DCMTK Developer
Posts: 2501
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

Re: The Windows is Russian environment, use putAndInsertOFStringArray() wirte 1.2/1.3 in tag DCM_PixelSpacing lost numbe

#4 Post by J. Riesmeier »

Short answer: according to the DICOM standard, the delimiter for DS (Decimal String) values is the backslash ("\") and not the pipe symbol ("|").

Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 1 guest