The file src\osgPlugins\hdr\hdrloader.cpp is faulty and not working in the new 
release 2.8.0 of OSG.
This results in .HDR images not working in OSG2.8.0.

There has been some fault checks introducted such as "if (numRead<10) return 
false;" in for example isHDRFile(). The problem is that the fread() function 
call has always had its size and count arguments switched so that it in the 
above case has size=10 and count=1. This will result in a numRead=1 and not 10 
as the check wants it to be.

The bug is solved by simply switching the size and count arguments of the 
fread() calls in the hdrloader.cpp file. A corrected file is attached.

Regards
Ragnar Hammarqvist
/*
*
* Copyright (C) 2004 Mekensleep
*
*    Mekensleep
*    24 rue vieille du temple
*    75004 Paris
*       [email protected]
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*
* Author:
*  Igor Kravtchenko <[email protected]>
*
*/

#include "hdrloader.h"

#include <math.h>
#include <memory.h>
#include <stdio.h>

#include <osgDB/FileUtils>

typedef unsigned char RGBE[4];
#define R            0
#define G            1
#define B            2
#define E            3

#define  MINELEN    8                // minimum scanline length for encoding
#define  MAXELEN    0x7fff            // maximum scanline length for encoding

static void rawRGBEData(RGBE *scan, int len, float *cols);
static void workOnRGBE(RGBE *scan, int len, float *cols);
static bool decrunch(RGBE *scanline, int len, FILE *file);
static bool oldDecrunch(RGBE *scanline, int len, FILE *file);

bool HDRLoader::isHDRFile(const char *_fileName)
{
    FILE *file;
    file = osgDB::fopen(_fileName, "rb");
    if (!file)
        return false;

    char str[10];
    size_t numRead = fread(str, 1, 10, file);
    
    fclose(file);

    if (numRead<10) return false;
    
    if (memcmp(str, "#?RADIANCE", 10) && memcmp(str, "#?RGBE", 6))
        return false;

    return true;
}

bool HDRLoader::load(const char *_fileName, const bool _rawRGBE, 
HDRLoaderResult &_res)
{
    int i;
    char str[200];
    FILE *file;

    file = osgDB::fopen(_fileName, "rb");
    if (!file)
        return false;

    size_t numRead = fread(str, 1, 10, file);

    if (numRead<10) 
    {
        fclose(file);
        return false;
    }
    
    if (memcmp(str, "#?RADIANCE", 10))
    {
        fseek(file, 0, SEEK_SET);
        numRead = fread(str, 1, 6, file);
        if (numRead<6 || memcmp(str, "#?RGBE", 6))
        {
            fclose(file);
            return false;
        }
    }
    fseek(file, 1, SEEK_CUR);

    char cmd[2000];
    i = 0;
    char c = 0, oldc;
    while(true) {
        oldc = c;
        c = fgetc(file);
        if (c == 0xa && oldc == 0xa)
            break;
        cmd[i++] = c;
    }

    char reso[2000];
    i = 0;
    while(true) {
        c = fgetc(file);
        reso[i++] = c;
        if (c == 0xa)
            break;
    }

    int w, h;
    if (!sscanf(reso, "-Y %d +X %d", &h, &w)) {
        fclose(file);
        return false;
    }

    _res.width = w;
    _res.height = h;

    int components = _rawRGBE ? 4 : 3;
    float *cols = new float[w * h * components];
    _res.cols = cols;

    RGBE *scanline = new RGBE[w];
    if (!scanline) {
        fclose(file);
        return false;
    }

    // convert image
    cols += (h-1) * w * components;
    for (int y = h - 1; y >= 0; y--) {
        if (decrunch(scanline, w, file) == false)
            break;
        if (_rawRGBE)
            rawRGBEData(scanline, w, cols);
        else
            workOnRGBE(scanline, w, cols);
        cols -= w * components;
    }

    delete [] scanline;
    fclose(file);

    return true;
}

void rawRGBEData(RGBE *_scan, int _len, float *_cols)
{
    int ii = 0;
    while (_len-- > 0) {
        _cols[0] = _scan[0][R] / 255.0f;
        _cols[1] = _scan[0][G] / 255.0f;
        _cols[2] = _scan[0][B] / 255.0f;
        _cols[3] = _scan[0][E] / 255.0f;
        _cols += 4;
        _scan++;
        ii++;
    }
}

inline float convertComponent(int _expo, int _val)
{
    return static_cast<float>(ldexp( static_cast<float>(_val), _expo-8));
}

void workOnRGBE(RGBE *_scan, int _len, float *_cols)
{
    int ii = 0;
    while (_len-- > 0) {
        int expo = _scan[0][E] - 128;
        _cols[0] = convertComponent(expo, _scan[0][R]);
        _cols[1] = convertComponent(expo, _scan[0][G]);
        _cols[2] = convertComponent(expo, _scan[0][B]);
        _cols += 3;
        _scan++;
        ii++;
    }
}

bool decrunch(RGBE *_scanline, int _len, FILE *_file)
{
    int  i, j;

    if (_len < MINELEN || _len > MAXELEN)
        return oldDecrunch(_scanline, _len, _file);

    i = fgetc(_file);
    if (i != 2) {
        fseek(_file, -1, SEEK_CUR);
        return oldDecrunch(_scanline, _len, _file);
    }

    _scanline[0][G] = fgetc(_file);
    _scanline[0][B] = fgetc(_file);
    i = fgetc(_file);

    if (_scanline[0][G] != 2 || _scanline[0][B] & 128) {
        _scanline[0][R] = 2;
        _scanline[0][E] = i;
        return oldDecrunch(_scanline + 1, _len - 1, _file);
    }

    // read each component
    for (i = 0; i < 4; i++) {
        for (j = 0; j < _len; ) {
            unsigned char code = fgetc(_file);
            if (code > 128) { // run
                code &= 127;
                unsigned char val = fgetc(_file);
                while (code--)
                    _scanline[j++][i] = val;
            }
            else  {    // non-run
                while(code--)
                    _scanline[j++][i] = fgetc(_file);
            }
        }
    }

    return feof(_file) ? false : true;
}

bool oldDecrunch(RGBE *_scanline, int _len, FILE *_file)
{
    int i;
    int rshift = 0;

    while (_len > 0) {
        _scanline[0][R] = fgetc(_file);
        _scanline[0][G] = fgetc(_file);
        _scanline[0][B] = fgetc(_file);
        _scanline[0][E] = fgetc(_file);
        if (feof(_file))
            return false;

        if (_scanline[0][R] == 1 &&
            _scanline[0][G] == 1 &&
            _scanline[0][B] == 1) {
                for (i = _scanline[0][E] << rshift; i > 0; i--) {
                    memcpy(&_scanline[0][0], &_scanline[-1][0], 4);
                    _scanline++;
                    _len--;
                }
                rshift += 8;
            }
        else {
            _scanline++;
            _len--;
            rshift = 0;
        }
    }
    return true;
}
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to