Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2005-11-20 17:32:07 +0300
committerTon Roosendaal <ton@blender.org>2005-11-20 17:32:07 +0300
commitc52170b4ed83a279af5d1a065d173969fe3d24cd (patch)
treec7bde0a344cfc7734e4214147bb925c216370ddc /source/blender/imbuf
parent36a9ae941510a12d092e76ac1d2cf1d731d793d3 (diff)
Patch provided by Alfredo de Greef
This adds Radiance HDR image file support. So now at least we can save the 'fbuf' (4x32 bits float colors) in Blender. It doesn't change anything for internal support in imbuf for floa colors, so when reading .hdr files it still converts it to 32 bits RGBA. As an extra I've added that saving images with F3 now also adds the optional extension, when the F10 "Extensions" option is set. One important note; I don't know the proper license for the code, it was provided without... will await feedback from Alfredo about it. For now I've added the standard Blender GPL header.
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r--source/blender/imbuf/IMB_imbuf.h5
-rw-r--r--source/blender/imbuf/IMB_imbuf_types.h2
-rw-r--r--source/blender/imbuf/SConscript1
-rw-r--r--source/blender/imbuf/intern/IMB_radiance_hdr.h42
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c392
-rw-r--r--source/blender/imbuf/intern/readimage.c4
-rw-r--r--source/blender/imbuf/intern/util.c7
-rw-r--r--source/blender/imbuf/intern/writeimage.c4
8 files changed, 457 insertions, 0 deletions
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 80eec374627..c16f25a4492 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -513,4 +513,9 @@ void quicktime_exit(void);
#endif //WITH_QUICKTIME
+/* radhdr: Temporary routine to save directly from render floatbuffer.
+ Defined in radiance_hdr.c
+ Called by schrijfplaatje() in toets.c */
+short imb_savehdr_fromfloat(float *fbuf, char *name, int width, int height);
+
#endif
diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h
index 8e0fedbe15e..413047bcae6 100644
--- a/source/blender/imbuf/IMB_imbuf_types.h
+++ b/source/blender/imbuf/IMB_imbuf_types.h
@@ -150,6 +150,7 @@ typedef enum {
#ifdef WITH_QUICKTIME
#define QUICKTIME (1 << 25)
#endif
+#define RADHDR (1<<24)
#define RAWTGA (TGA | 1)
@@ -187,6 +188,7 @@ typedef enum {
#define IS_tga(x) (x->ftype & TGA)
#define IS_png(x) (x->ftype & PNG)
#define IS_bmp(x) (x->ftype & BMP)
+#define IS_radhdr(x) (x->ftype & RADHDR)
#define IMAGIC 0732
#define IS_iris(x) (x->ftype == IMAGIC)
diff --git a/source/blender/imbuf/SConscript b/source/blender/imbuf/SConscript
index 94b8846c769..55bf18e404b 100644
--- a/source/blender/imbuf/SConscript
+++ b/source/blender/imbuf/SConscript
@@ -25,6 +25,7 @@ source_files = ['intern/allocimbuf.c',
'intern/iris.c',
'intern/jpeg.c',
'intern/png.c',
+ 'intern/radiance_hdr.c',
'intern/readimage.c',
'intern/rectop.c',
'intern/rotate.c',
diff --git a/source/blender/imbuf/intern/IMB_radiance_hdr.h b/source/blender/imbuf/intern/IMB_radiance_hdr.h
new file mode 100644
index 00000000000..91a8f380557
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_radiance_hdr.h
@@ -0,0 +1,42 @@
+/*
+ * IMB_radiance_hdr.h
+ *
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef IMB_RADIANCE_HDR_H
+#define IMB_RADIANCE_HDR_H
+
+struct ImBuf;
+
+int imb_is_a_hdr(void *buf);
+
+struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags);
+short imb_savehdr(struct ImBuf * ibuf, char *name, int flags);
+
+#endif
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
new file mode 100644
index 00000000000..fe18d4e3574
--- /dev/null
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -0,0 +1,392 @@
+/*
+ * radiance_hdr.c
+ *
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+*/
+
+
+/*
+ -------------------------------------------------------------------------------------------------
+ Radiance High Dynamic Range image file IO
+ For description and code for reading/writing of radiance hdr files by Greg Ward, refer to:
+ http://radsite.lbl.gov/radiance/refer/Notes/picture_format.html
+ -------------------------------------------------------------------------------------------------
+*/
+
+#ifdef WIN32
+#include <io.h>
+#endif
+#include "BLI_blenlib.h"
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_allocimbuf.h"
+#include "IMB_cmap.h"
+#include "IMB_radiance_hdr.h"
+
+/* needed constants */
+#define MINELEN 8
+#define MAXELEN 0x7fff
+#define MINRUN 4 /* minimum run length */
+#define RED 0
+#define GRN 1
+#define BLU 2
+#define EXP 3
+#define COLXS 128
+typedef unsigned char RGBE[4];
+typedef float fCOLOR[3];
+/* copy source -> dest */
+#define copy_rgbe(c1, c2) (c2[RED]=c1[RED], c2[GRN]=c1[GRN], c2[BLU]=c1[BLU], c2[EXP]=c1[EXP])
+#define copy_fcol(f1, f2) (f2[RED]=f1[RED], f2[GRN]=f1[GRN], f2[BLU]=f1[BLU])
+
+/*-------------------------------------------------------------------------------------------------*/
+/* read routines */
+
+static unsigned char* oldreadcolrs(RGBE *scan, unsigned char *mem, int xmax)
+{
+ int i, rshift = 0, len = xmax;
+ while (len > 0) {
+ scan[0][RED] = *mem++;
+ scan[0][GRN] = *mem++;
+ scan[0][BLU] = *mem++;
+ scan[0][EXP] = *mem++;
+ if (scan[0][RED] == 1 && scan[0][GRN] == 1 && scan[0][BLU] == 1) {
+ for (i=scan[0][EXP]<<rshift;i>0;i--) {
+ copy_rgbe(scan[-1], scan[0]);
+ scan++;
+ len--;
+ }
+ rshift += 8;
+ }
+ else {
+ scan++;
+ len--;
+ rshift = 0;
+ }
+ }
+ return mem;
+}
+
+static unsigned char* freadcolrs(RGBE *scan, unsigned char* mem, int xmax)
+{
+ int i, j, code, val;
+
+ if ((xmax < MINELEN) | (xmax > MAXELEN)) return oldreadcolrs(scan, mem, xmax);
+
+ i = *mem++;
+ if (i != 2) return oldreadcolrs(scan, mem-1, xmax);
+
+ scan[0][GRN] = *mem++;
+ scan[0][BLU] = *mem++;
+
+ i = *mem++;
+ if (((scan[0][BLU] << 8) | i) != xmax) return NULL;
+
+ for (i=0;i<4;i++)
+ for (j=0;j<xmax;) {
+ code = *mem++;
+ if (code > 128) {
+ code &= 127;
+ val = *mem++;
+ while (code--)
+ scan[j++][i] = (unsigned char)val;
+ }
+ else
+ while (code--)
+ scan[j++][i] = *mem++;
+ }
+ return mem;
+}
+
+/*-------------------------------------------------------------------------------------------------*/
+/* helper functions */
+
+/* rgbe -> float color */
+static void RGBE2FLOAT(RGBE rgbe, fCOLOR fcol)
+{
+ if (rgbe[EXP]==0) {
+ fcol[RED] = fcol[GRN] = fcol[BLU] = 0;
+ }
+ else {
+ float f = ldexp(1.0, rgbe[EXP]-(COLXS+8));
+ fcol[RED] = f*(rgbe[RED] + 0.5f);
+ fcol[GRN] = f*(rgbe[GRN] + 0.5f);
+ fcol[BLU] = f*(rgbe[BLU] + 0.5f);
+ }
+}
+
+/* float color -> rgbe */
+static void FLOAT2RGBE(fCOLOR fcol, RGBE rgbe)
+{
+ int e;
+ float d = (fcol[RED]>fcol[GRN]) ? fcol[RED] : fcol[GRN];
+ if (fcol[BLU]>d) d = fcol[BLU];
+ if (d <= 1e-32f)
+ rgbe[RED] = rgbe[GRN] = rgbe[BLU] = rgbe[EXP] = 0;
+ else {
+ d = frexp(d, &e) * 256.f / d;
+ rgbe[RED] = (unsigned char)(fcol[RED] * d);
+ rgbe[GRN] = (unsigned char)(fcol[GRN] * d);
+ rgbe[BLU] = (unsigned char)(fcol[BLU] * d);
+ rgbe[EXP] = (unsigned char)(e + COLXS);
+ }
+}
+
+/*-------------------------------------------------------------------------------------------------*/
+/* ImBuf read */
+
+int imb_is_a_hdr(void *buf)
+{
+ /* For recognition, Blender only loades first 32 bytes, so use #?RADIANCE id instead */
+ if (strstr((char*)buf, "#?RADIANCE")) return 1;
+ // if (strstr((char*)buf, "32-bit_rle_rgbe")) return 1;
+ return 0;
+}
+
+struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags)
+{
+ int found=0;
+ char oriY[80], oriX[80];
+ int width=0, height=0;
+ RGBE* sline;
+ int x, y;
+ char* ptr;
+ fCOLOR fcol;
+ int ir, ig, ib;
+ unsigned char* rect;
+ struct ImBuf* ibuf;
+
+ if (imb_is_a_hdr((void*)mem))
+ {
+ /* find empty line, next line is resolution info */
+ for (x=1;x<size;x++) {
+ if ((mem[x-1]=='\n') && (mem[x]=='\n')) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ sscanf((char*)&mem[x+1], "%s %d %s %d", (char*)&oriY, &height, (char*)&oriX, &width);
+
+ /* find end of this line, data right behind it */
+ ptr = strchr((char*)&mem[x+1], '\n');
+ ptr++;
+
+ if (flags & IB_test) ibuf = IMB_allocImBuf(width, height, 24, 0, 0);
+ else ibuf = IMB_allocImBuf(width, height, 24, 1, 0);
+
+ if (ibuf==NULL) return NULL;
+ ibuf->ftype = RADHDR;
+ ibuf->xorig = ibuf->yorig = 0;
+
+ if (flags & IB_test) return ibuf;
+
+ /* read in and decode the actual data */
+ sline = (RGBE*)MEM_mallocN(sizeof(RGBE)*width, "radhdr_read_tmpscan");
+ rect = (unsigned char*)ibuf->rect;
+ for (y=0;y<height;y++) {
+ ptr = freadcolrs(sline, ptr, width);
+ if (ptr==NULL) {
+ printf("HDR decode error\n");
+ MEM_freeN(sline);
+ return ibuf;
+ }
+ for (x=0;x<width;x++) {
+ /* convert to ldr */
+ RGBE2FLOAT(sline[x], fcol);
+ /*--------------------------------------------------------------------------------------*/
+ /* THIS PART NEEDS TO BE ADAPTED TO WRITE TO IMBUF FLOATBUFFER ONCE THAT IS IMPLEMENTED
+ * temporarily now loads as regular image using simple tone mapping
+ * (of course this should NOT be done when loading to floatbuffer!) */
+ fcol[RED] = 1.f-exp(fcol[RED]*-1.414213562f);
+ fcol[GRN] = 1.f-exp(fcol[GRN]*-1.414213562f);
+ fcol[BLU] = 1.f-exp(fcol[BLU]*-1.414213562f);
+ ir = (int)(255.f*pow(fcol[RED], 0.45454545f));
+ ig = (int)(255.f*pow(fcol[GRN], 0.45454545f));
+ ib = (int)(255.f*pow(fcol[BLU], 0.45454545f));
+ *rect++ = (unsigned char)((ir<0) ? 0 : ((ir>255) ? 255 : ir));
+ *rect++ = (unsigned char)((ig<0) ? 0 : ((ig>255) ? 255 : ig));
+ *rect++ = (unsigned char)((ib<0) ? 0 : ((ib>255) ? 255 : ib));
+ *rect++ = 255;
+ /*--------------------------------------------------------------------------------------*/
+ }
+ }
+ MEM_freeN(sline);
+ if (oriY[0]=='-') IMB_flipy(ibuf);
+ return ibuf;
+ }
+ //else printf("Data not found!\n");
+ }
+ //else printf("Not a valid radiance HDR file!\n");
+
+ return NULL;
+}
+
+/*-------------------------------------------------------------------------------------------------*/
+/* ImBuf write */
+
+
+static int fwritecolrs(FILE* file, int width, RGBE* rgbe_scan, unsigned char* ibufscan, float* fpscan)
+{
+ int i, j, beg, c2, cnt=0;
+ fCOLOR fcol;
+ RGBE rgbe;
+
+ if ((ibufscan==NULL) && (fpscan==NULL)) return 0;
+
+ /* convert scanline */
+ for (i=0, j=0;i<width;i++, j+=4) {
+ if (ibufscan) {
+ fcol[RED] = (float)ibufscan[j] / 255.f;
+ fcol[GRN] = (float)ibufscan[j+1] / 255.f;
+ fcol[BLU] = (float)ibufscan[j+2] /255.f;
+ }
+ else {
+ fcol[RED] = fpscan[j];
+ fcol[GRN] = fpscan[j+1];
+ fcol[BLU] = fpscan[j+2];
+ }
+ FLOAT2RGBE(fcol, rgbe);
+ copy_rgbe(rgbe, rgbe_scan[i]);
+ }
+
+ if ((width < MINELEN) | (width > MAXELEN)) /* OOBs, write out flat */
+ return (fwrite((char *)rgbe_scan, sizeof(RGBE), width, file) - width);
+ /* put magic header */
+ putc(2, file);
+ putc(2, file);
+ putc((unsigned char)(width >> 8), file);
+ putc((unsigned char)(width & 255), file);
+ /* put components seperately */
+ for (i=0;i<4;i++) {
+ for (j=0;j<width;j+=cnt) { /* find next run */
+ for (beg=j;beg<width;beg+=cnt) {
+ for (cnt=1;(cnt<127) && ((beg+cnt)<width) && (rgbe_scan[beg+cnt][i] == rgbe_scan[beg][i]); cnt++);
+ if (cnt>=MINRUN) break; /* long enough */
+ }
+ if (((beg-j)>1) && ((beg-j) < MINRUN)) {
+ c2 = j+1;
+ while (rgbe_scan[c2++][i] == rgbe_scan[j][i])
+ if (c2 == beg) { /* short run */
+ putc((unsigned char)(128+beg-j), file);
+ putc((unsigned char)(rgbe_scan[j][i]), file);
+ j = beg;
+ break;
+ }
+ }
+ while (j < beg) { /* write out non-run */
+ if ((c2 = beg-j) > 128) c2 = 128;
+ putc((unsigned char)(c2), file);
+ while (c2--) putc(rgbe_scan[j++][i], file);
+ }
+ if (cnt >= MINRUN) { /* write out run */
+ putc((unsigned char)(128+cnt), file);
+ putc(rgbe_scan[beg][i], file);
+ }
+ else cnt = 0;
+ }
+ }
+ return(ferror(file) ? -1 : 0);
+}
+
+static void writeHeader(FILE *file, int width, int height)
+{
+ fprintf(file, "#?RADIANCE");
+ fputc(10, file);
+ fprintf(file, "# %s", "Created with Blender");
+ fputc(10, file);
+ fprintf(file, "FORMAT=32-bit_rle_rgbe");
+ fputc(10, file);
+ fprintf(file, "EXPOSURE=%25.13f", 1.0);
+ fputc(10, file);
+ fputc(10, file);
+ fprintf(file, "-Y %d +X %d", height, width);
+ fputc(10, file);
+}
+
+short imb_savehdr(struct ImBuf *ibuf, char *name, int flags)
+{
+ int y, width=ibuf->x, height=ibuf->y;
+ RGBE* sline;
+
+ FILE* file = fopen(name, "wb");
+ if (file==NULL) return 0;
+
+ writeHeader(file, width, height);
+
+ sline = (RGBE*)MEM_mallocN(sizeof(RGBE)*width, "radhdr_write_tmpscan");
+
+ for (y=height-1;y>=0;y--) {
+ if (fwritecolrs(file, width, sline, (unsigned char*)&ibuf->rect[y*width], NULL) < 0)
+ { // error
+ fclose(file);
+ MEM_freeN(sline);
+ printf("HDR write error\n");
+ return 0;
+ }
+ }
+
+ fclose(file);
+ MEM_freeN(sline);
+ return 1;
+}
+
+/* Temporary routine to save directly from render floatbuffer.
+ Called by schrijfplaatje() in toets.c */
+short imb_savehdr_fromfloat(float *fbuf, char *name, int width, int height)
+{
+ int y;
+ RGBE* sline;
+
+ FILE* file = fopen(name, "wb");
+ if (file==NULL) return 0;
+
+ writeHeader(file, width, height);
+
+ sline = (RGBE*)MEM_mallocN(sizeof(RGBE)*width, "radhdr_write_tmpscan");
+
+ for (y=height-1;y>=0;y--) {
+ if (fwritecolrs(file, width, sline, NULL, &fbuf[y*width*4]) < 0)
+ { // error
+ fclose(file);
+ MEM_freeN(sline);
+ printf("HDR write error\n");
+ return 0;
+ }
+ }
+
+ fclose(file);
+ MEM_freeN(sline);
+ return 1;
+}
+
+/*-------------------------------------------------------------------------------------------------*/
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index 4cae5cace16..166b1d6af81 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -50,6 +50,7 @@
#include "IMB_hamx.h"
#include "IMB_jpeg.h"
#include "IMB_bmp.h"
+#include "IMB_radiance_hdr.h"
#include "BKE_global.h"
#ifdef WITH_QUICKTIME
@@ -128,6 +129,9 @@ ImBuf *IMB_ibImageFromMemory(int *mem, int size, int flags) {
ibuf = imb_loadtarga((uchar *)mem, flags);
if (ibuf) return(ibuf);
+ ibuf = imb_loadhdr((uchar*)mem, size, flags);
+ if (ibuf) return (ibuf);
+
#ifdef WITH_QUICKTIME
#if defined(_WIN32) || defined (__APPLE__)
if(G.have_quicktime) {
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 8863097a8ba..bbfa41e9dcc 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -45,6 +45,7 @@
#include "IMB_targa.h"
#include "IMB_png.h"
#include "IMB_bmp.h"
+#include "IMB_radiance_hdr.h"
#include "IMB_anim.h"
@@ -95,6 +96,10 @@ static int IMB_ispic_name(char *name)
}
if (imb_is_a_png(buf)) return(PNG);
if (imb_is_a_targa(buf)) return(TGA);
+
+ /* radhdr: check if hdr format */
+ if (imb_is_a_hdr(buf)) return(RADHDR);
+
/*
if (imb_is_a_bmp(buf)) return(BMP);
*/
@@ -123,6 +128,7 @@ int IMB_ispic(char *filename)
if (G.have_quicktime){
if( BLI_testextensie(filename, ".jpg")
|| BLI_testextensie(filename, ".jpeg")
+ || BLI_testextensie(filename, ".hdr")
|| BLI_testextensie(filename, ".tga")
|| BLI_testextensie(filename, ".rgb")
|| BLI_testextensie(filename, ".bmp")
@@ -145,6 +151,7 @@ int IMB_ispic(char *filename)
} else { // no quicktime
if( BLI_testextensie(filename, ".jpg")
|| BLI_testextensie(filename, ".jpeg")
+ || BLI_testextensie(filename, ".hdr")
|| BLI_testextensie(filename, ".tga")
|| BLI_testextensie(filename, ".rgb")
|| BLI_testextensie(filename, ".bmp")
diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c
index 04e83c6814b..148597dda35 100644
--- a/source/blender/imbuf/intern/writeimage.c
+++ b/source/blender/imbuf/intern/writeimage.c
@@ -54,6 +54,7 @@
#include "IMB_amiga.h"
#include "IMB_png.h"
#include "IMB_bmp.h"
+#include "IMB_radiance_hdr.h"
#include "IMB_iff.h"
#include "IMB_bitplanes.h"
@@ -71,6 +72,9 @@ short IMB_saveiff(struct ImBuf *ibuf,char *naam,int flags)
if (IS_jpg(ibuf)) {
return imb_savejpeg(ibuf, naam, flags);
}
+ if (IS_radhdr(ibuf)) {
+ return imb_savehdr(ibuf, naam, flags);
+ }
if (IS_png(ibuf)) {
return imb_savepng(ibuf,naam,flags);
}