mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-07-18 20:04:16 -04:00
Move kimageformats code to the root directory.
This commit is contained in:
237
src/imageformats/hdr.cpp
Normal file
237
src/imageformats/hdr.cpp
Normal file
@ -0,0 +1,237 @@
|
||||
/* This file is part of the KDE project
|
||||
Copyright (C) 2005 Christoph Hormann <chris_hormann@gmx.de>
|
||||
Copyright (C) 2005 Ignacio Castaño <castanyo@yahoo.es>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the Lesser GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "hdr.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QtCore/QDataStream>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
typedef Q_UINT8 uchar;
|
||||
|
||||
namespace // Private.
|
||||
{
|
||||
|
||||
#define MAXLINE 1024
|
||||
#define MINELEN 8 // minimum scanline length for encoding
|
||||
#define MAXELEN 0x7fff // maximum scanline length for encoding
|
||||
|
||||
static inline uchar ClipToByte(float value)
|
||||
{
|
||||
if (value > 255.0f) return 255;
|
||||
//else if (value < 0.0f) return 0; // we know value is positive.
|
||||
return uchar(value);
|
||||
}
|
||||
|
||||
// read an old style line from the hdr image file
|
||||
// if 'first' is true the first byte is already read
|
||||
static bool Read_Old_Line(uchar * image, int width, QDataStream & s)
|
||||
{
|
||||
int rshift = 0;
|
||||
int i;
|
||||
|
||||
while (width > 0) {
|
||||
s >> image[0];
|
||||
s >> image[1];
|
||||
s >> image[2];
|
||||
s >> image[3];
|
||||
|
||||
if (s.atEnd()) return false;
|
||||
|
||||
if ((image[0] == 1) && (image[1] == 1) && (image[2] == 1)) {
|
||||
for (i = image[3] << rshift; i > 0; i--) {
|
||||
//memcpy(image, image-4, 4);
|
||||
(uint &)image[0] = (uint &)image[0 - 4];
|
||||
image += 4;
|
||||
width--;
|
||||
}
|
||||
rshift += 8;
|
||||
} else {
|
||||
image += 4;
|
||||
width--;
|
||||
rshift = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void RGBE_To_QRgbLine(uchar * image, QRgb * scanline, int width)
|
||||
{
|
||||
for (int j = 0; j < width; j++) {
|
||||
// v = ldexp(1.0, int(image[3]) - 128);
|
||||
float v;
|
||||
int e = int(image[3]) - 128;
|
||||
if (e > 0) {
|
||||
v = float(1 << e);
|
||||
} else {
|
||||
v = 1.0f / float(1 << -e);
|
||||
}
|
||||
|
||||
scanline[j] = qRgb(ClipToByte(float(image[0]) * v),
|
||||
ClipToByte(float(image[1]) * v),
|
||||
ClipToByte(float(image[2]) * v));
|
||||
|
||||
image += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Load the HDR image.
|
||||
static bool LoadHDR(QDataStream & s, const int width, const int height, QImage & img)
|
||||
{
|
||||
uchar val, code;
|
||||
|
||||
// Create dst image.
|
||||
if (!img.create(width, height, 32)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QMemArray<uchar> image(width * 4);
|
||||
|
||||
for (int cline = 0; cline < height; cline++) {
|
||||
QRgb * scanline = (QRgb *) img.scanLine(cline);
|
||||
|
||||
// determine scanline type
|
||||
if ((width < MINELEN) || (MAXELEN < width)) {
|
||||
Read_Old_Line(image.data(), width, s);
|
||||
RGBE_To_QRgbLine(image.data(), scanline, width);
|
||||
continue;
|
||||
}
|
||||
|
||||
s >> val;
|
||||
|
||||
if (s.atEnd()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (val != 2) {
|
||||
s.device()->at(s.device()->at() - 1);
|
||||
Read_Old_Line(image.data(), width, s);
|
||||
RGBE_To_QRgbLine(image.data(), scanline, width);
|
||||
continue;
|
||||
}
|
||||
|
||||
s >> image[1];
|
||||
s >> image[2];
|
||||
s >> image[3];
|
||||
|
||||
if (s.atEnd()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((image[1] != 2) || (image[2] & 128)) {
|
||||
image[0] = 2;
|
||||
Read_Old_Line(image.data() + 4, width - 1, s);
|
||||
RGBE_To_QRgbLine(image.data(), scanline, width);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((image[2] << 8 | image[3]) != width) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// read each component
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < width;) {
|
||||
s >> code;
|
||||
if (s.atEnd()) {
|
||||
return false;
|
||||
}
|
||||
if (code > 128) {
|
||||
// run
|
||||
code &= 127;
|
||||
s >> val;
|
||||
while (code != 0) {
|
||||
image[i + j * 4] = val;
|
||||
j++;
|
||||
code--;
|
||||
}
|
||||
} else {
|
||||
// non-run
|
||||
while (code != 0) {
|
||||
s >> image[i + j * 4];
|
||||
j++;
|
||||
code--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RGBE_To_QRgbLine(image.data(), scanline, width);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Q_DECL_EXPORT void kimgio_hdr_read(QImageIO * io)
|
||||
{
|
||||
int len;
|
||||
char line[MAXLINE];
|
||||
//bool validHeader = false;
|
||||
bool validFormat = false;
|
||||
|
||||
// Parse header
|
||||
do {
|
||||
len = io->ioDevice()->readLine(line, MAXLINE);
|
||||
|
||||
/*if (strcmp(line, "#?RADIANCE\n") == 0 || strcmp(line, "#?RGBE\n") == 0)
|
||||
{
|
||||
validHeader = true;
|
||||
}*/
|
||||
if (strcmp(line, "FORMAT=32-bit_rle_rgbe\n") == 0) {
|
||||
validFormat = true;
|
||||
}
|
||||
|
||||
} while ((len > 0) && (line[0] != '\n'));
|
||||
|
||||
if (/*!validHeader ||*/ !validFormat) {
|
||||
// qDebug() << "Unknown HDR format.";
|
||||
io->setImage(0);
|
||||
io->setStatus(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
io->ioDevice()->readLine(line, MAXLINE);
|
||||
|
||||
char s1[3], s2[3];
|
||||
int width, height;
|
||||
if (sscanf(line, "%2[+-XY] %d %2[+-XY] %d\n", s1, &height, s2, &width) != 4)
|
||||
//if( sscanf(line, "-Y %d +X %d", &height, &width) < 2 )
|
||||
{
|
||||
// qDebug() << "Invalid HDR file.";
|
||||
io->setImage(0);
|
||||
io->setStatus(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
QDataStream s(io->ioDevice());
|
||||
|
||||
QImage img;
|
||||
if (!LoadHDR(s, width, height, img)) {
|
||||
// qDebug() << "Error loading HDR file.";
|
||||
io->setImage(0);
|
||||
io->setStatus(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
io->setImage(img);
|
||||
io->setStatus(0);
|
||||
}
|
||||
|
||||
|
||||
Q_DECL_EXPORT void kimgio_hdr_write(QImageIO *)
|
||||
{
|
||||
// intentionally not implemented (since writing low dynamic range data to a HDR file is nonsense.)
|
||||
}
|
||||
|
Reference in New Issue
Block a user