0

如果它在 mac32 上运行,它运行良好;如果我在 win32 上运行它,我会在 139 像素处得到一个意外的文件结尾,如果我注释掉 fseek (在我的测试 .tga 图像中它只会寻找 0 字节,所以不应该有区别)我得到在像素 35 处文件意外结束。但标题读取完全正常;这只是数据。

对于不同的编译器/架构,这 2 个函数是否以不同的方式实现?

struct TGAHeader
{   
    char    idlength;
    char    colourmaptype;
    char    datatypecode;
    short   colourmaporigin;
    short   colourmaplength;
    char    colourmapdepth;
    short   x_origin;
    short   y_origin;
    short   width;
    short   height;
    char    bitsperpixel;
    char    imagedescriptor;
};    

bool read()
{
    printf("Reading TGA file...\n");

    header.idlength = fgetc(TGAFile);
    header.colourmaptype = fgetc(TGAFile);
    header.datatypecode = fgetc(TGAFile);
    fread(&header.colourmaporigin,2,1,TGAFile);
    fread(&header.colourmaplength,2,1,TGAFile);
    header.colourmapdepth = fgetc(TGAFile);
    fread(&header.x_origin,2,1,TGAFile);
    fread(&header.y_origin,2,1,TGAFile);
    fread(&header.width,2,1,TGAFile);
    fread(&header.height,2,1,TGAFile);
    header.bitsperpixel = fgetc(TGAFile);
    header.imagedescriptor = fgetc(TGAFile);

    printf("...TGA file has been read\n\n");
    printf("ID length:         %d\n",header.idlength);
    printf("Colourmap type:    %d\n",header.colourmaptype);
    printf("Image type:        %d\n",header.datatypecode);
    printf("Colour map offset: %d\n",header.colourmaporigin);
    printf("Colour map length: %d\n",header.colourmaplength);
    printf("Colour map depth:  %d\n",header.colourmapdepth);
    printf("X origin:          %d\n",header.x_origin);
    printf("Y origin:          %d\n",header.y_origin);
    printf("Width:             %d\n",header.width);
    printf("Height:            %d\n",header.height);
    printf("Bits per pixel:    %d\n",header.bitsperpixel);
    printf("Descriptor:        %d\n",header.imagedescriptor);

    bytesToRead = header.bitsperpixel / 8;

    if(!errCheck())
    {
        m_bLoaded = false;
        return false;
    }
    //set stream position indicator to the start of the data
    fseek(TGAFile,(header.idlength+(header.colourmaptype * header.colourmaplength)),SEEK_CUR);

    //allocate space to store data
    releaseTGAData();
    pixelData = new unsigned char*[header.width*header.height];
    for(int i=0;i<header.width*header.height;i++)
        pixelData[i] = new unsigned char[bytesToRead];

    for(int i=0;i<header.width * header.height;i++)
    {
        if (fread(pixelData[i],1,bytesToRead,TGAFile) != bytesToRead)
        {
            printf("Unexpected end of file at pixel %d\n",i);
            m_bLoaded = false;
            releaseTGAData();
            return false;
        }
    }
    fclose(TGAFile);

    return true;
}

编辑:这是加载功能

bool load(const char* inFilename = NULL)
{
    m_bLoaded = false;
    if(NULL!=filename)
        delete [] filename;
    filename = new char[128];

    //if the filename has not been selected by the programmer
    if(NULL==inFilename)
    {
        //ask the user for it
        printf("please enter the filename of an uncompressed TGA file:\n");
        scanf("%s", filename);
    }
    else sprintf(filename, inFilename);

    if ((TGAFile = fopen(filename,"r")) == NULL)
    {
        printf("File open failed, please try again\n");
        return false;
    }
    if(!read())
        return false;

    m_bLoaded=true;
    return true;
}
4

3 回答 3

2

问题是您以文本模式打开文件。在 Windows 上,输入函数会将字节序列0x0d 0x0a(即 Windows 换行序列"\r\n")转换为单个字符。

Windows 很可能还会检查字节0x19(我认为),它是CTRL-Z并且是 Windows 中的文件结尾字符。

于 2013-01-27T19:41:04.033 回答
1

您的问题很可能是由于处理非二进制文件时 Windows 处理从文件读取的方式不同引起的,但更有效的解决方案是使用 #pragma pack 或属性(alaligned(1)) 作为标头结构并读取一个 fread 调用中的整个标题

于 2013-01-27T19:42:06.577 回答
1

由于该文件包含二进制数据,因此您必须在 Windows 上"rb"的调用中使用作为打开模式。fopen()在 Unix 上,这b是可选的(但无害),因此如果您的代码是可移植的,请在两个系统上使用相同的模式。

如果您在 Windows 上打开文件而不指定b,您将获得 'CRLF' 映射(因此回车换行序列"\r\n"映射到换行符"\n"- 其中换行符只是换行符的另一个名称)。第一个 control-Z 字节标记文件的结尾。

于 2013-01-27T19:44:40.570 回答