You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libksquirrel/kernel/kls_openexr/fmt_codec_openexr.cpp

304 lines
7.2 KiB

/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net)
Copyright (c) 2005 Dmitry Baryshev <ksquirrel@tut.by>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation;
either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <iostream>
#include <exception>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "ksquirrel-libs/fmt_types.h"
#include "ksquirrel-libs/fileio.h"
#include "ksquirrel-libs/fmt_utils.h"
#include <ImfStandardAttributes.h>
#include <ImathBox.h>
#include <ImfInputFile.h>
#include <ImfBoxAttribute.h>
#include <ImfChannelListAttribute.h>
#include <ImfCompressionAttribute.h>
#include <ImfFloatAttribute.h>
#include <ImfIntAttribute.h>
#include <ImfLineOrderAttribute.h>
#include <ImfStringAttribute.h>
#include <ImfVecAttribute.h>
#include <ImfConvert.h>
#include "fmt_codec_openexr_defs.h"
#include "fmt_codec_openexr.h"
#include "ksquirrel-libs/error.h"
#include "../xpm/codec_openexr.xpm"
RGBA RgbaToRGBA(struct Rgba);
/*
*
* A high-dynamic-range image format from Industrial Light & Magic
* for use in digital visual effects production.
*
*/
fmt_codec::fmt_codec() : fmt_codec_base()
{}
fmt_codec::~fmt_codec()
{}
void fmt_codec::options(codec_options *o)
{
o->version = "0.2.1";
o->name = "OpenEXR";
o->filter = "*.exr ";
o->config = "";
o->mime = "";
o->mimetype = "image/x-exr";
o->pixmap = codec_openexr;
o->readable = true;
o->canbemultiple = false;
o->writestatic = false;
o->writeanimated = false;
o->needtempfile = false;
}
s32 fmt_codec::read_init(const std::string &fl)
{
frs.open(fl.c_str(), ios::binary | ios::in);
if(!frs.good())
return SQE_R_NOFILE;
frs.close();
currentImage = -1;
read_error = false;
pixels = 0;
file = fl;
finfo.animated = false;
return SQE_OK;
}
s32 fmt_codec::read_next()
{
currentImage++;
if(currentImage)
return SQE_NOTOK;
fmt_image image;
s32 width, height;
RgbaInputFile *in = NULL;
pixels = new Array2D<Rgba>;
try
{
in = new RgbaInputFile(file.c_str());
Imath::Box2i dw = in->dataWindow();
width = dw.max.x - dw.min.x + 1;
height = dw.max.y - dw.min.y + 1;
pixels->resizeErase(height, width);
in->setFrameBuffer(&(*pixels)[0][0] - dw.min.x - dw.min.y * width, 1, width);
in->readPixels(dw.min.y, dw.max.y);
}
catch(const exception &e)
{
cerr << e.what() << endl;
delete in;
return SQE_R_BADFILE;
}
switch(in->compression())
{
case Imf::NO_COMPRESSION:
image.compression = "-";
break;
case Imf::RLE_COMPRESSION:
image.compression = "RLE";
break;
case Imf::ZIPS_COMPRESSION:
image.compression = "ZIPS";
break;
case Imf::ZIP_COMPRESSION:
image.compression = "ZIP";
break;
case Imf::PIZ_COMPRESSION:
image.compression = "PIZ";
break;
case Imf::PXR24_COMPRESSION:
image.compression = "PXR24";
break;
case Imf::NUM_COMPRESSION_METHODS:
image.compression = "Different methods";
break;
default:
image.compression = "Unknown";
}
image.colorspace = "RGBA";
image.bpp = 32;
image.w = width;
image.h = height;
finfo.image.push_back(image);
line = -1;
delete in;
return SQE_OK;
}
s32 fmt_codec::read_next_pass()
{
return SQE_OK;
}
s32 fmt_codec::read_scanline(RGBA *scan)
{
RGBA rgba;
fmt_image *im = image(currentImage);
fmt_utils::fillAlpha(scan, im->w);
line++;
for(s32 x = 0; x < im->w; x++)
{
rgba = RgbaToRGBA((*pixels)[line][x]);
memcpy(scan+x, &rgba, sizeof(RGBA));
}
return SQE_OK;
}
void fmt_codec::read_close()
{
finfo.meta.clear();
finfo.image.clear();
delete pixels;
pixels = 0;
}
/*
* This function is taken from exr plugin for KImageIO, kdelibs-3.4.0:
*
* KImageIO Routines to read (and perhaps in the future, write) images
* in the high dynamic range EXR format.
* Copyright (c) 2003, Brad Hards <bradh@frogmouth.net>
*
* This library is distributed under the conditions of the GNU LGPL.
*
* $Id: exr.cpp,v 1.4 2004/11/22 03:48:27 mueller Exp $
*/
/*
* utility function
*
* this does a conversion from the ILM Half (equal to Nvidia Half)
* format into the normal 32 bit pixel format. Process is from the
* ILM code.
*
*/
RGBA RgbaToRGBA(struct Rgba imagePixel)
{
float r,g,b,a;
// 1) Compensate for fogging by subtracting defog
// from the raw pixel values.
// Response: We work with defog of 0.0, so this is a no-op
// 2) Multiply the defogged pixel values by
// 2^(exposure + 2.47393).
// Response: We work with exposure of 0.0.
// (2^2.47393) is 5.55555
r = imagePixel.r * 5.55555;
g = imagePixel.g * 5.55555;
b = imagePixel.b * 5.55555;
a = imagePixel.a * 5.55555;
// 3) Values, which are now 1.0, are called "middle gray".
// If defog and exposure are both set to 0.0, then
// middle gray corresponds to a raw pixel value of 0.18.
// In step 6, middle gray values will be mapped to an
// intensity 3.5 f-stops below the display's maximum
// intensity.
// Response: no apparent content.
// 4) Apply a knee function. The knee function has two
// parameters, kneeLow and kneeHigh. Pixel values
// below 2^kneeLow are not changed by the knee
// function. Pixel values above kneeLow are lowered
// according to a logarithmic curve, such that the
// value 2^kneeHigh is mapped to 2^3.5 (in step 6,
// this value will be mapped to the the display's
// maximum intensity).
// Response: kneeLow = 0.0 (2^0.0 => 1); kneeHigh = 5.0 (2^5 =>32)
if (r > 1.0)
r = 1.0 + Imath::Math<float>::log ((r-1.0) * 0.184874 + 1) / 0.184874;
if (g > 1.0)
g = 1.0 + Imath::Math<float>::log ((g-1.0) * 0.184874 + 1) / 0.184874;
if (b > 1.0)
b = 1.0 + Imath::Math<float>::log ((b-1.0) * 0.184874 + 1) / 0.184874;
if (a > 1.0)
a = 1.0 + Imath::Math<float>::log ((a-1.0) * 0.184874 + 1) / 0.184874;
//
// 5) Gamma-correct the pixel values, assuming that the
// screen's gamma is 0.4545 (or 1/2.2).
r = Imath::Math<float>::pow (r, 0.4545);
g = Imath::Math<float>::pow (g, 0.4545);
b = Imath::Math<float>::pow (b, 0.4545);
a = Imath::Math<float>::pow (a, 0.4545);
// 6) Scale the values such that pixels middle gray
// pixels are mapped to 84.66 (or 3.5 f-stops below
// the display's maximum intensity).
//
// 7) Clamp the values to [0, 255].
return RGBA( s8 (Imath::clamp ( r * 84.66f, 0.f, 255.f ) ),
s8 (Imath::clamp ( g * 84.66f, 0.f, 255.f ) ),
s8 (Imath::clamp ( b * 84.66f, 0.f, 255.f ) ),
s8 (Imath::clamp ( a * 84.66f, 0.f, 255.f ) ) );
}
#include "fmt_codec_cd_func.h"