【问题标题】:How can I write a rational tag like 200/1 using the LibTiff.Net 2.3 Library如何使用 LibTiff.Net 2.3 库编写像 200/1 这样的有理标签
【发布时间】:2012-06-26 23:34:25
【问题描述】:

我不知道为什么这很难做到,但我无法让 LibTiff.Net 2.3 正确设置合理值......多年来,我一直在 tiff 标签号中使用像“200/1”这样的值282(X 分辨率)和 283(Y 分辨率)。但是当使用 LibTiff.Net 库时,似乎不可能得到这样的结果。我总是得到诸如“419430400/2097152”之类的东西。有谁知道我该如何解决这个问题?

关于我的问题的注释:

这是 libtiff 库(.Net 之前),它看起来像第一个 else if 确实考虑了 200/1 之类的东西。

TIFFWriteDirectoryTagCheckedRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, float* value)
{
    static const char module[] = "TIFFWriteDirectoryTagCheckedRationalArray";
    uint32* m;
    float* na;
    uint32* nb;
    uint32 nc;
    int o;
    assert(sizeof(uint32)==4);
    m=_TIFFmalloc(count*2*sizeof(uint32));
    if (m==NULL)
    {
        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
        return(0);
    }
    for (na=value, nb=m, nc=0; nc<count; na++, nb+=2, nc++)
    {
        if (*na<=0.0)
        {
            nb[0]=0;
            nb[1]=1;
        }
        else if (*na==(float)(uint32)(*na))
        {
            nb[0]=(uint32)(*na);
            nb[1]=1;
        }
        else if (*na<1.0)
        {
            nb[0]=(uint32)((*na)*0xFFFFFFFF);
            nb[1]=0xFFFFFFFF;
        }
        else
        {
            nb[0]=0xFFFFFFFF;
            nb[1]=(uint32)(0xFFFFFFFF/(*na));
        }
    }
    if (tif->tif_flags&TIFF_SWAB)
        TIFFSwabArrayOfLong(m,count*2);
    o=TIFFWriteDirectoryTagData(tif,ndir,dir,tag,TIFF_RATIONAL,count,count*8,&m[0]);
    _TIFFfree(m);
    return(o);
}

这是新的 .Net 版本...

private bool writeRationalArray(ref TiffDirEntry dir, float[] v)
{
    int[] t = new int [2 * dir.tdir_count];
    for (int i = 0; i < dir.tdir_count; i++)
    {
        int sign = 1;
        float fv = v[i];
        if (fv < 0)
        {
            if (dir.tdir_type == TiffType.RATIONAL)
            {
                WarningExt(this, m_clientdata, m_name,
                "\"{0}\": Information lost writing value ({1:G}) as (unsigned) RATIONAL",
                FieldWithTag(dir.tdir_tag).Name, fv);
                fv = 0;
            }
            else
            {
                fv = -fv;
                sign = -1;
            }
        }

        int den = 1;
        if (fv > 0)
        {
            while (fv < (1L << (31 - 3)) && den < (1L << (31 - 3)))
            {
                fv *= 1 << 3;
                den *= 1 << 3;
            }
        }

        t[2 * i + 0] = (int)(sign * (fv + 0.5));
        t[2 * i + 1] = den;
    }

    return writeData(ref dir, t, 2 * dir.tdir_count);
}

【问题讨论】:

    标签: c# tags tiff libtiff.net


    【解决方案1】:

    如果这对您有帮助,请务必给我一个 1UP。谢谢!

    好的,所以我决定着手编辑库以考虑减少的分数。下面是我在 .Net 库中更改以使其工作的代码。它确实有效!

    我希望 Bobrovsky 在他的下一个版本中包含这一点。我相信除了我之外,还有其他人会感激不尽! ;)

    如果您对如何编辑库有点不确定,这里是我使用的尽可能详细的步骤...

    1) 下载位于here的库源。

    2) 打开项目文件。我使用 LibTiff.NET_NoSilverlight.sln 解决方案文件打开了项目。

    3) 展开 LibTiff 项目节点。

    4) 展开 Internals 节点。

    5) 找到Tiff_DirWrite.cs类文件并打开。

    6) 在该类文件中,我找到了名为 writeRationalArray 的函数,它看起来是这样的......

    /// <summary>
    /// Setup a directory entry of an array of RATIONAL or SRATIONAL and
    /// write the associated indirect values.
    /// </summary>
    private bool writeRationalArray(ref TiffDirEntry dir, float[] v)
    {
        int[] t = new int [2 * dir.tdir_count];
        for (int i = 0; i < dir.tdir_count; i++)
        {
            int sign = 1;
            float fv = v[i];
            if (fv < 0)
            {
                if (dir.tdir_type == TiffType.RATIONAL)
                {
                    WarningExt(this, m_clientdata, m_name,
                        "\"{0}\": Information lost writing value ({1:G}) as (unsigned) RATIONAL",
                        FieldWithTag(dir.tdir_tag).Name, fv);
                    fv = 0;
                }
                else
                {
                    fv = -fv;
                    sign = -1;
                }
            }
    
            int den = 1;
            if (fv > 0)
            {
                while (fv < (1L << (31 - 3)) && den < (1L << (31 - 3)))
                {
                    fv *= 1 << 3;
                    den *= 1 << 3;
                }
            }
    
            t[2 * i + 0] = (int)(sign * (fv + 0.5));
            t[2 * i + 1] = den;
        }
    
        return writeData(ref dir, t, 2 * dir.tdir_count);
    }
    

    7) 编辑 writeRationalArray 函数,使其如下所示...

    /// <summary>
    /// Setup a directory entry of an array of RATIONAL or SRATIONAL and
    /// write the associated indirect values.
    /// </summary>
    private bool writeRationalArray(ref TiffDirEntry dir, float[] v)
    {
        int[] t = new int [2 * dir.tdir_count];
        for (int i = 0; i < dir.tdir_count; i++)
        {
            int sign = 1;
            float fv = v[i];
            if (fv < 0)
            {
                if (dir.tdir_type == TiffType.RATIONAL)
                {
                    WarningExt(this, m_clientdata, m_name,
                        "\"{0}\": Information lost writing value ({1:G}) as (unsigned) RATIONAL",
                        FieldWithTag(dir.tdir_tag).Name, fv);
                    fv = 0;
                }
                else
                {
                    fv = -fv;
                    sign = -1;
                }
            }
    
            int den = 1;
            if (fv > 0)
            {
                while (fv < (1L << (31 - 3)) && den < (1L << (31 - 3)))
                {
                    fv *= 1 << 3;
                    den *= 1 << 3;
                }
            }
    
            t[2 * i + 0] = (int)(sign * (fv + 0.5));
            t[2 * i + 1] = den;
    
            //Reduce the fraction
            int a = t[2 * i + 0];
            int b = t[2 * i + 1];
            while (b > 0) { int rem = a % b; a = b; b = rem; }
            for (int ind = 0; ind < 2; ind++) { t[2 * i + ind] /= a; }
        }
    
        return writeData(ref dir, t, 2 * dir.tdir_count);
    }
    

    我所做的只是添加三行代码来减少最后的分数。

    【讨论】:

      【解决方案2】:

      在使用 LibTiff.Net 时,您应该像这样设置有理值:

      image.SetField(TiffTag.XRESOLUTION, 150.0);
      image.SetField(TiffTag.YRESOLUTION, 150.0);
      

      库将在 TIFF 中写入一个有理值作为整数值对(除数和除数)。你不需要帮助它。

      【讨论】:

      • 是的,我愿意。 ;) 但它并没有改变它在 tiff 上显示为“419430400/2097152”而不是“200/1”的事实。出于某种原因,LibTiff 没有将分数减少到最低公分母。为什么会发生这种情况?
      • 我不知道为什么 libtiff 的作者决定不减少分数(可能是性能)。如果您绝对需要减少分数,那么我建议您使用修改后的源代码。 Tiff_DirWrite.cs 中的writeRationalArray 是您可能要修改的方法。
      • 谢谢博布罗夫斯基!你知道以前有人做过吗?我以前从未更改过 LibTiff.Net 的源代码,在我开始破解之前我应该​​知道什么?
      • 我个人将 libtiff 移植到 LibTiff.Net,所以我对源代码进行了很多修改 :-) LibTiff.Net 的源代码包包含一些单元测试,因此您将获得某种保护当你开始黑客攻击时。除此之外,我猜这是反复试验。移植的目的是提供完全相同的功能,所以如果 libtiff 写入分数而不减少(值得检查,顺便说一句),那么 LibTiff.Net 也会这样做。如果这些库之间存在差异,那么差异被认为是一个错误,我会尝试修复它。
      • 如果您在 .Net 版本中添加一小段代码,至少会有一个人非常高兴。 ;) 或者至少告诉我应该添加什么并让我自己构建。只是看着 sn-ps,我似乎无法理解我将 if () {} 放在哪里......或者我将使用什么来使“if”指令工作......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多