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:
Diffstat (limited to 'source/blender/imbuf/intern')
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h4
-rw-r--r--source/blender/imbuf/intern/IMB_imginfo.h85
-rw-r--r--source/blender/imbuf/intern/IMB_jpeg.h2
-rw-r--r--source/blender/imbuf/intern/Makefile7
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c8
-rw-r--r--source/blender/imbuf/intern/anim.c148
-rw-r--r--source/blender/imbuf/intern/cineon/Makefile4
-rw-r--r--source/blender/imbuf/intern/cineon/cineon_dpx.c24
-rw-r--r--source/blender/imbuf/intern/cineon/cineonlib.c12
-rw-r--r--source/blender/imbuf/intern/cineon/dpxlib.c14
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.c29
-rw-r--r--source/blender/imbuf/intern/cineon/logImageCore.h4
-rw-r--r--source/blender/imbuf/intern/cineon/logImageLib.c5
-rw-r--r--source/blender/imbuf/intern/cineon/logImageLib.h1
-rw-r--r--source/blender/imbuf/intern/dds/BlockDXT.cpp591
-rw-r--r--source/blender/imbuf/intern/dds/BlockDXT.h248
-rw-r--r--source/blender/imbuf/intern/dds/Color.h99
-rw-r--r--source/blender/imbuf/intern/dds/ColorBlock.cpp317
-rw-r--r--source/blender/imbuf/intern/dds/ColorBlock.h116
-rw-r--r--source/blender/imbuf/intern/dds/Common.h56
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.cpp1023
-rw-r--r--source/blender/imbuf/intern/dds/DirectDrawSurface.h181
-rw-r--r--source/blender/imbuf/intern/dds/Image.cpp132
-rw-r--r--source/blender/imbuf/intern/dds/Image.h104
-rw-r--r--source/blender/imbuf/intern/dds/Makefile63
-rw-r--r--source/blender/imbuf/intern/dds/PixelFormat.h110
-rw-r--r--source/blender/imbuf/intern/dds/SConscript19
-rw-r--r--source/blender/imbuf/intern/dds/Stream.cpp99
-rw-r--r--source/blender/imbuf/intern/dds/Stream.h49
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.cpp132
-rw-r--r--source/blender/imbuf/intern/dds/dds_api.h43
-rw-r--r--source/blender/imbuf/intern/divers.c2
-rw-r--r--source/blender/imbuf/intern/dynlibtiff.c8
-rw-r--r--source/blender/imbuf/intern/filter.c73
-rwxr-xr-xsource/blender/imbuf/intern/gen_dynlibtiff.py8
-rw-r--r--source/blender/imbuf/intern/imageprocess.c260
-rw-r--r--source/blender/imbuf/intern/imginfo.c158
-rw-r--r--source/blender/imbuf/intern/jpeg.c94
-rw-r--r--source/blender/imbuf/intern/md5.c361
-rw-r--r--source/blender/imbuf/intern/md5.h116
-rw-r--r--source/blender/imbuf/intern/openexr/Makefile4
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp51
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_multi.h8
-rw-r--r--source/blender/imbuf/intern/png.c39
-rw-r--r--source/blender/imbuf/intern/radiance_hdr.c29
-rw-r--r--source/blender/imbuf/intern/readimage.c11
-rw-r--r--source/blender/imbuf/intern/rectop.c84
-rw-r--r--source/blender/imbuf/intern/rotate.c91
-rw-r--r--source/blender/imbuf/intern/scaling.c473
-rw-r--r--source/blender/imbuf/intern/thumbs.c459
-rw-r--r--source/blender/imbuf/intern/tiff.c192
-rw-r--r--source/blender/imbuf/intern/util.c20
-rw-r--r--source/blender/imbuf/intern/writeimage.c10
53 files changed, 6038 insertions, 242 deletions
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index 602b13df4ca..f3514a92ae4 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -81,6 +81,7 @@
#ifdef WITH_FFMPEG
#include <ffmpeg/avformat.h>
#include <ffmpeg/avcodec.h>
+#include <ffmpeg/swscale.h>
#endif
#include "IMB_imbuf_types.h"
@@ -181,7 +182,8 @@ struct anim {
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrameRGB;
- AVFrame *pFrame;
+ AVFrame *pFrame;
+ struct SwsContext *img_convert_ctx;
int videoStream;
#endif
diff --git a/source/blender/imbuf/intern/IMB_imginfo.h b/source/blender/imbuf/intern/IMB_imginfo.h
new file mode 100644
index 00000000000..e82cc5f32af
--- /dev/null
+++ b/source/blender/imbuf/intern/IMB_imginfo.h
@@ -0,0 +1,85 @@
+/**
+ * $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 (C) 2005 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Austin Benesh. Ton Roosendaal.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef _IMB_IMGINFO_H
+#define _IMB_IMGINFO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ImBuf;
+
+typedef struct ImgInfo {
+ struct ImgInfo *next, *prev;
+ char* key;
+ char* value;
+ int len;
+} ImgInfo;
+
+/** The imginfo is a list of key/value pairs (both char*) that can me
+ saved in the header of several image formats.
+ Apart from some common keys like
+ 'Software' and 'Description' (png standard) we'll use keys within the
+ Blender namespace, so should be called 'Blender::StampInfo' or 'Blender::FrameNum'
+ etc...
+*/
+
+
+/* free blender ImgInfo struct */
+void IMB_imginfo_free(struct ImBuf* img);
+
+/** read the field from the image info into the field
+ * @param img - the ImBuf that contains the image data
+ * @param key - the key of the field
+ * @param value - the data in the field, first one found with key is returned,
+ memory has to be allocated by user.
+ * @param len - length of value buffer allocated by user.
+ * @return - 1 (true) if ImageInfo present and value for the key found, 0 (false) otherwise
+ */
+int IMB_imginfo_get_field(struct ImBuf* img, const char* key, char* value, int len);
+
+/** set user data in the ImgInfo struct, which has to be allocated with IMB_imginfo_create
+ * before calling this function.
+ * @param img - the ImBuf that contains the image data
+ * @param key - the key of the field
+ * @param value - the data to be written to the field. zero terminated string
+ * @return - 1 (true) if ImageInfo present, 0 (false) otherwise
+ */
+int IMB_imginfo_add_field(struct ImBuf* img, const char* key, const char* field);
+
+/** delete the key/field par in the ImgInfo struct.
+ * @param img - the ImBuf that contains the image data
+ * @param key - the key of the field
+ * @return - 1 (true) if delete the key/field, 0 (false) otherwise
+ */
+int IMB_imginfo_del_field(struct ImBuf *img, const char *key);
+
+#endif /* _IMB_IMGINFO_H */
+
diff --git a/source/blender/imbuf/intern/IMB_jpeg.h b/source/blender/imbuf/intern/IMB_jpeg.h
index 4a86a72ca77..f78810d27ee 100644
--- a/source/blender/imbuf/intern/IMB_jpeg.h
+++ b/source/blender/imbuf/intern/IMB_jpeg.h
@@ -45,7 +45,7 @@ struct jpeg_compress_struct;
int imb_is_a_jpeg(unsigned char *mem);
int imb_savejpeg(struct ImBuf * ibuf, char * name, int flags);
-struct ImBuf * imb_ibJpegImageFromFilename (char * filename, int flags);
+struct ImBuf * imb_ibJpegImageFromFilename (const char * filename, int flags);
struct ImBuf * imb_ibJpegImageFromMemory (unsigned char * buffer, int size, int flags);
#endif
diff --git a/source/blender/imbuf/intern/Makefile b/source/blender/imbuf/intern/Makefile
index f51844aad96..09eb487b3a6 100644
--- a/source/blender/imbuf/intern/Makefile
+++ b/source/blender/imbuf/intern/Makefile
@@ -46,9 +46,9 @@ ifeq ($(WITH_OPENEXR), true)
CFLAGS += -DWITH_OPENEXR
endif
-
-ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
- CFLAGS += -funsigned-char
+ifeq ($(WITH_DDS), true)
+ DIRS += dds
+ CPPFLAGS += -DWITH_DDS
endif
CFLAGS += $(LEVEL_1_C_WARNINGS)
@@ -80,4 +80,3 @@ ifeq ($(WITH_FFMPEG), true)
CPPFLAGS += -DWITH_FFMPEG
CPPFLAGS += $(NAN_FFMPEGCFLAGS)
endif
-
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 003d377389b..bc750e455a6 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -43,6 +43,7 @@
#include "IMB_divers.h"
#include "IMB_allocimbuf.h"
+#include "IMB_imginfo.h"
#include "MEM_CacheLimiterC-Api.h"
static unsigned int dfltcmap[16] = {
@@ -163,6 +164,7 @@ void IMB_freeImBuf(struct ImBuf * ibuf)
IMB_freecmapImBuf(ibuf);
freeencodedbufferImBuf(ibuf);
IMB_cache_limiter_unmanage(ibuf);
+ IMB_imginfo_free(ibuf);
MEM_freeN(ibuf);
}
}
@@ -278,6 +280,7 @@ short imb_addrectfloatImBuf(struct ImBuf * ibuf)
size = ibuf->x * ibuf->y;
size = size * 4 * sizeof(float);
+ ibuf->channels= 4;
if ( (ibuf->rect_float = MEM_mapallocN(size, "imb_addrectfloatImBuf")) ){
ibuf->mall |= IB_rectfloat;
@@ -443,7 +446,7 @@ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1)
memcpy(ibuf2->rect, ibuf1->rect, x * y * sizeof(int));
if (flags & IB_rectfloat)
- memcpy(ibuf2->rect_float, ibuf1->rect_float, 4 * x * y * sizeof(float));
+ memcpy(ibuf2->rect_float, ibuf1->rect_float, ibuf1->channels * x * y * sizeof(float));
if (flags & IB_planes)
memcpy(*(ibuf2->planes),*(ibuf1->planes),ibuf1->depth * ibuf1->skipx * y * sizeof(int));
@@ -476,6 +479,9 @@ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1)
tbuf.mall = ibuf2->mall;
tbuf.c_handle = 0;
+ // for now don't duplicate image info
+ tbuf.img_info = 0;
+
*ibuf2 = tbuf;
if (ibuf1->cmap){
diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c
index a1ef735ffdb..1700790c4fa 100644
--- a/source/blender/imbuf/intern/anim.c
+++ b/source/blender/imbuf/intern/anim.c
@@ -89,6 +89,7 @@
#include <ffmpeg/avformat.h>
#include <ffmpeg/avcodec.h>
#include <ffmpeg/rational.h>
+#include <ffmpeg/swscale.h>
#if LIBAVFORMAT_VERSION_INT < (49 << 16)
#define FFMPEG_OLD_FRAME_RATE 1
@@ -338,12 +339,12 @@ void IMB_close_anim(struct anim * anim) {
}
-struct anim * IMB_open_anim(char * name, int ib_flags) {
+struct anim * IMB_open_anim( const char * name, int ib_flags) {
struct anim * anim;
anim = (struct anim*)MEM_callocN(sizeof(struct anim), "anim struct");
if (anim != NULL) {
- strcpy(anim->name, name);
+ strcpy(anim->name, name); /* fixme: possible buffer overflow here? */
anim->ib_flags = ib_flags;
}
return(anim);
@@ -593,7 +594,7 @@ static int startffmpeg(struct anim * anim) {
anim->pFrame = avcodec_alloc_frame();
anim->pFrameRGB = avcodec_alloc_frame();
- if (avpicture_get_size(PIX_FMT_RGBA32, anim->x, anim->y)
+ if (avpicture_get_size(PIX_FMT_BGR32, anim->x, anim->y)
!= anim->x * anim->y * 4) {
fprintf (stderr,
"ffmpeg has changed alloc scheme ... ARGHHH!\n");
@@ -609,7 +610,17 @@ static int startffmpeg(struct anim * anim) {
} else {
anim->preseek = 0;
}
-
+
+ anim->img_convert_ctx = sws_getContext(
+ anim->pCodecCtx->width,
+ anim->pCodecCtx->height,
+ anim->pCodecCtx->pix_fmt,
+ anim->pCodecCtx->width,
+ anim->pCodecCtx->height,
+ PIX_FMT_BGR32,
+ SWS_FAST_BILINEAR | SWS_PRINT_INFO,
+ NULL, NULL, NULL);
+
return (0);
}
@@ -626,7 +637,7 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
avpicture_fill((AVPicture *)anim->pFrameRGB,
(unsigned char*) ibuf->rect,
- PIX_FMT_RGBA32, anim->x, anim->y);
+ PIX_FMT_BGR32, anim->x, anim->y);
if (position != anim->curposition + 1) {
if (position > anim->curposition + 1
@@ -703,36 +714,98 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
}
if(frameFinished && pos_found == 1) {
- unsigned char * p =(unsigned char*) ibuf->rect;
- unsigned char * e = p + anim->x * anim->y * 4;
-
- img_convert((AVPicture *)anim->pFrameRGB,
- PIX_FMT_RGBA32,
- (AVPicture*)anim->pFrame,
- anim->pCodecCtx->pix_fmt,
- anim->pCodecCtx->width,
- anim->pCodecCtx->height);
- IMB_flipy(ibuf);
- if (G.order == L_ENDIAN) {
- /* BGRA -> RGBA */
- while (p != e) {
- unsigned char a = p[0];
- p[0] = p[2];
- p[2] = a;
- p += 4;
+ if (G.order == B_ENDIAN) {
+ int * dstStride
+ = anim->pFrameRGB->linesize;
+ uint8_t** dst = anim->pFrameRGB->data;
+ int dstStride2[4]
+ = { dstStride[0], 0, 0, 0 };
+ uint8_t* dst2[4]= {
+ dst[0], 0, 0, 0 };
+ int x,y,h,w;
+ unsigned char* bottom;
+ unsigned char* top;
+
+ sws_scale(anim->img_convert_ctx,
+ anim->pFrame->data,
+ anim->pFrame->linesize,
+ 0,
+ anim->pCodecCtx->height,
+ dst2,
+ dstStride2);
+
+ /* workaround: sws_scale
+ sets alpha = 0 and compensate
+ for altivec-bugs and flipy... */
+
+ bottom = (unsigned char*) ibuf->rect;
+ top = bottom
+ + ibuf->x * (ibuf->y-1) * 4;
+
+ h = (ibuf->y + 1) / 2;
+ w = ibuf->x;
+
+ for (y = 0; y < h; y++) {
+ unsigned char tmp[4];
+ unsigned long * tmp_l =
+ (unsigned long*) tmp;
+ tmp[3] = 0xff;
+
+ for (x = 0; x < w; x++) {
+ tmp[0] = bottom[3];
+ tmp[1] = bottom[2];
+ tmp[2] = bottom[1];
+
+ bottom[0] = top[3];
+ bottom[1] = top[2];
+ bottom[2] = top[1];
+ bottom[3] = 0xff;
+
+ *(unsigned long*) top
+ = *tmp_l;
+
+ bottom +=4;
+ top += 4;
+ }
+ top -= 8 * w;
}
+
+ av_free_packet(&packet);
+ break;
} else {
- /* ARGB -> RGBA */
- while (p != e) {
- unsigned long a =
- *(unsigned long*) p;
- a = (a << 8) | p[0];
- *(unsigned long*) p = a;
- p += 4;
+ int * dstStride
+ = anim->pFrameRGB->linesize;
+ uint8_t** dst = anim->pFrameRGB->data;
+ int dstStride2[4]
+ = { -dstStride[0], 0, 0, 0 };
+ uint8_t* dst2[4]= {
+ dst[0]
+ + (anim->y - 1)*dstStride[0],
+ 0, 0, 0 };
+ int i;
+ unsigned char* r;
+
+ sws_scale(anim->img_convert_ctx,
+ anim->pFrame->data,
+ anim->pFrame->linesize,
+ 0,
+ anim->pCodecCtx->height,
+ dst2,
+ dstStride2);
+
+ /* workaround: sws_scale
+ sets alpha = 0... */
+
+ r = (unsigned char*) ibuf->rect;
+
+ for (i = 0; i < ibuf->x * ibuf->y;i++){
+ r[3] = 0xff;
+ r+=4;
}
+
+ av_free_packet(&packet);
+ break;
}
- av_free_packet(&packet);
- break;
}
}
@@ -750,6 +823,7 @@ static void free_anim_ffmpeg(struct anim * anim) {
av_close_input_file(anim->pFormatCtx);
av_free(anim->pFrameRGB);
av_free(anim->pFrame);
+ sws_freeContext(anim->img_convert_ctx);
}
anim->duration = 0;
}
@@ -819,6 +893,18 @@ static struct ImBuf * anim_getnew(struct anim * anim) {
return(ibuf);
}
+struct ImBuf * IMB_anim_previewframe(struct anim * anim) {
+ struct ImBuf * ibuf = 0;
+ int position = 0;
+
+ ibuf = IMB_anim_absolute(anim, 0);
+ if (ibuf) {
+ IMB_freeImBuf(ibuf);
+ position = anim->duration / 2;
+ ibuf = IMB_anim_absolute(anim, position);
+ }
+ return ibuf;
+}
struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) {
struct ImBuf * ibuf = 0;
diff --git a/source/blender/imbuf/intern/cineon/Makefile b/source/blender/imbuf/intern/cineon/Makefile
index 596a6647093..e61c8dd59ed 100644
--- a/source/blender/imbuf/intern/cineon/Makefile
+++ b/source/blender/imbuf/intern/cineon/Makefile
@@ -38,10 +38,6 @@ SOURCEDIR = source/blender/imbuf/intern/cineon
include nan_compile.mk
include nan_definitions.mk
-ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
- CFLAGS += -funsigned-char
-endif
-
CFLAGS += $(LEVEL_1_C_WARNINGS)
CPPFLAGS += -I$(NAN_JPEG)/include
diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c
index 691b81745e0..f00f6bc38c5 100644
--- a/source/blender/imbuf/intern/cineon/cineon_dpx.c
+++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c
@@ -42,14 +42,29 @@
#include "MEM_guardedalloc.h"
+/* ugly bad level, should be fixed */
+#include "DNA_scene_types.h"
+#include "BKE_global.h"
+
+static void cineon_conversion_parameters(LogImageByteConversionParameters *params)
+{
+ params->blackPoint = G.scene->r.cineonblack;
+ params->whitePoint = G.scene->r.cineonwhite;
+ params->gamma = G.scene->r.cineongamma;
+ params->doLogarithm = G.scene->r.subimtype & R_CINEON_LOG;
+}
+
static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int size, int flags)
{
+ LogImageByteConversionParameters conversion;
ImBuf *ibuf;
LogImageFile *image;
int x, y;
unsigned short *row, *upix;
int width, height, depth;
float *frow;
+
+ cineon_conversion_parameters(&conversion);
image = logImageOpenFromMem(mem, size, use_cineon);
@@ -70,6 +85,8 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, int use_cineon, int
return NULL;
}
+ logImageSetByteConversion(image, &conversion);
+
ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags, 0);
row = MEM_mallocN(sizeof(unsigned short)*width*depth, "row in cineon_dpx.c");
@@ -107,10 +124,9 @@ static int imb_save_dpx_cineon(ImBuf *buf, char *filename, int use_cineon, int f
int i, j;
int index;
float *fline;
-
- conversion.blackPoint = 95;
- conversion.whitePoint = 685;
- conversion.gamma = 1;
+
+ cineon_conversion_parameters(&conversion);
+
/*
* Get the drawable for the current image...
*/
diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c
index 20f4e0d4de4..3b45a9de822 100644
--- a/source/blender/imbuf/intern/cineon/cineonlib.c
+++ b/source/blender/imbuf/intern/cineon/cineonlib.c
@@ -350,8 +350,10 @@ cineonGetRowBytes(CineonFile* cineon, unsigned short* row, int y) {
/* extract required pixels */
for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- /* row[pixelIndex] = cineon->lut10[cineon->pixelBuffer[pixelIndex]]; */
- row[pixelIndex] = cineon->pixelBuffer[pixelIndex] << 6;
+ if(cineon->params.doLogarithm)
+ row[pixelIndex] = cineon->lut10_16[cineon->pixelBuffer[pixelIndex]];
+ else
+ row[pixelIndex] = cineon->pixelBuffer[pixelIndex] << 6;
}
return 0;
@@ -367,8 +369,10 @@ cineonSetRowBytes(CineonFile* cineon, const unsigned short* row, int y) {
/* put new pixels into pixelBuffer */
for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- /* cineon->pixelBuffer[pixelIndex] = cineon->lut8[row[pixelIndex]]; */
- cineon->pixelBuffer[pixelIndex] = row[pixelIndex] >> 6;
+ if(cineon->params.doLogarithm)
+ cineon->pixelBuffer[pixelIndex] = cineon->lut16_16[row[pixelIndex]];
+ else
+ cineon->pixelBuffer[pixelIndex] = row[pixelIndex] >> 6;
}
/* pack into longwords */
diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c
index b769d1e6132..a81e632a797 100644
--- a/source/blender/imbuf/intern/cineon/dpxlib.c
+++ b/source/blender/imbuf/intern/cineon/dpxlib.c
@@ -199,7 +199,7 @@ dumpDpxMainHeader(DpxMainHeader* header) {
#endif
}
-static int verbose = 0;
+static int verbose = 1;
void
dpxSetVerbose(int verbosity) {
verbose = verbosity;
@@ -275,8 +275,10 @@ dpxGetRowBytes(DpxFile* dpx, unsigned short* row, int y) {
/* extract required pixels */
for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- /* row[pixelIndex] = dpx->lut10[dpx->pixelBuffer[pixelIndex]]; */
- row[pixelIndex] = dpx->pixelBuffer[pixelIndex] << 6;
+ if(dpx->params.doLogarithm)
+ row[pixelIndex] = dpx->lut10_16[dpx->pixelBuffer[pixelIndex]];
+ else
+ row[pixelIndex] = dpx->pixelBuffer[pixelIndex] << 6;
}
/* save remaining pixels */
@@ -316,8 +318,10 @@ dpxSetRowBytes(DpxFile* dpx, const unsigned short* row, int y) {
/* put new pixels into pixelBuffer */
for (pixelIndex = 0; pixelIndex < numPixels; ++pixelIndex) {
- /* dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = dpx->lut8[row[pixelIndex]]; */
- dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = row[pixelIndex] >> 6;
+ if(dpx->params.doLogarithm)
+ dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = dpx->lut16_16[row[pixelIndex]];
+ else
+ dpx->pixelBuffer[dpx->pixelBufferUsed + pixelIndex] = row[pixelIndex] >> 6;
}
dpx->pixelBufferUsed += numPixels;
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c
index e88e9241443..6032f342ed8 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.c
+++ b/source/blender/imbuf/intern/cineon/logImageCore.c
@@ -93,6 +93,35 @@ setupLut(LogImageFile *logImage) {
}
}
+/* set up the 10 bit to 16 bit and 16 bit to 10 bit tables */
+void
+setupLut16(LogImageFile *logImage) {
+
+ int i;
+ double f_black;
+ double scale;
+
+ f_black = convertTo(logImage->params.blackPoint, logImage->params.whitePoint, logImage->params.gamma);
+ scale = 65535.0 / (1.0 - f_black);
+
+ for (i = 0; i <= logImage->params.blackPoint; ++i) {
+ logImage->lut10_16[i] = 0;
+ }
+ for (; i < logImage->params.whitePoint; ++i) {
+ double f_i;
+ f_i = convertTo(i, logImage->params.whitePoint, logImage->params.gamma);
+ logImage->lut10_16[i] = (int)rint(scale * (f_i - f_black));
+ }
+ for (; i < 1024; ++i) {
+ logImage->lut10_16[i] = 65535;
+ }
+
+ for (i = 0; i < 65536; ++i) {
+ double f_i = f_black + (i / 65535.0) * (1.0 - f_black);
+ logImage->lut16_16[i] = convertFrom(f_i, logImage->params.whitePoint, logImage->params.gamma);
+ }
+}
+
/* how many longwords to hold this many pixels? */
int
pixelsToLongs(int numPixels) {
diff --git a/source/blender/imbuf/intern/cineon/logImageCore.h b/source/blender/imbuf/intern/cineon/logImageCore.h
index 1af18d5e3b8..01eff8d570d 100644
--- a/source/blender/imbuf/intern/cineon/logImageCore.h
+++ b/source/blender/imbuf/intern/cineon/logImageCore.h
@@ -71,6 +71,9 @@ struct _Log_Image_File_t_
unsigned char lut10[1024];
unsigned short lut8[256];
+ unsigned short lut10_16[1024];
+ unsigned short lut16_16[65536];
+
/* pixel access functions */
GetRowFn* getRow;
SetRowFn* setRow;
@@ -82,6 +85,7 @@ struct _Log_Image_File_t_
};
void setupLut(LogImageFile*);
+void setupLut16(LogImageFile*);
int pixelsToLongs(int numPixels);
diff --git a/source/blender/imbuf/intern/cineon/logImageLib.c b/source/blender/imbuf/intern/cineon/logImageLib.c
index ff209d5ebd0..2fc52959ff6 100644
--- a/source/blender/imbuf/intern/cineon/logImageLib.c
+++ b/source/blender/imbuf/intern/cineon/logImageLib.c
@@ -89,6 +89,7 @@ logImageGetByteConversionDefaults(LogImageByteConversionParameters* params) {
params->gamma = DEFAULT_GAMMA;
params->blackPoint = DEFAULT_BLACK_POINT;
params->whitePoint = DEFAULT_WHITE_POINT;
+ params->doLogarithm = 0;
return 0;
}
@@ -97,6 +98,7 @@ logImageGetByteConversion(const LogImageFile* logImage, LogImageByteConversionPa
params->gamma = logImage->params.gamma;
params->blackPoint = logImage->params.blackPoint;
params->whitePoint = logImage->params.whitePoint;
+ params->doLogarithm = 0;
return 0;
}
@@ -110,7 +112,8 @@ logImageSetByteConversion(LogImageFile* logImage, const LogImageByteConversionPa
logImage->params.gamma = params->gamma;
logImage->params.blackPoint = params->blackPoint;
logImage->params.whitePoint = params->whitePoint;
- setupLut(logImage);
+ logImage->params.doLogarithm = params->doLogarithm;
+ setupLut16(logImage);
return 0;
}
return 1;
diff --git a/source/blender/imbuf/intern/cineon/logImageLib.h b/source/blender/imbuf/intern/cineon/logImageLib.h
index ea45c675fe2..617da1d0d92 100644
--- a/source/blender/imbuf/intern/cineon/logImageLib.h
+++ b/source/blender/imbuf/intern/cineon/logImageLib.h
@@ -47,6 +47,7 @@ typedef struct {
float gamma;
int blackPoint;
int whitePoint;
+ int doLogarithm;
} LogImageByteConversionParameters;
/* int functions return 0 for OK */
diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp
new file mode 100644
index 00000000000..24a090d93f6
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp
@@ -0,0 +1,591 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#include <Common.h>
+#include <Stream.h>
+#include <ColorBlock.h>
+#include <BlockDXT.h>
+
+/*----------------------------------------------------------------------------
+ BlockDXT1
+----------------------------------------------------------------------------*/
+
+uint BlockDXT1::evaluatePalette(Color32 color_array[4]) const
+{
+ // Does bit expansion before interpolation.
+ color_array[0].b = (col0.b << 3) | (col0.b >> 2);
+ color_array[0].g = (col0.g << 2) | (col0.g >> 4);
+ color_array[0].r = (col0.r << 3) | (col0.r >> 2);
+ color_array[0].a = 0xFF;
+
+ // @@ Same as above, but faster?
+// Color32 c;
+// c.u = ((col0.u << 3) & 0xf8) | ((col0.u << 5) & 0xfc00) | ((col0.u << 8) & 0xf80000);
+// c.u |= (c.u >> 5) & 0x070007;
+// c.u |= (c.u >> 6) & 0x000300;
+// color_array[0].u = c.u;
+
+ color_array[1].r = (col1.r << 3) | (col1.r >> 2);
+ color_array[1].g = (col1.g << 2) | (col1.g >> 4);
+ color_array[1].b = (col1.b << 3) | (col1.b >> 2);
+ color_array[1].a = 0xFF;
+
+ // @@ Same as above, but faster?
+// c.u = ((col1.u << 3) & 0xf8) | ((col1.u << 5) & 0xfc00) | ((col1.u << 8) & 0xf80000);
+// c.u |= (c.u >> 5) & 0x070007;
+// c.u |= (c.u >> 6) & 0x000300;
+// color_array[1].u = c.u;
+
+ if( col0.u > col1.u ) {
+ // Four-color block: derive the other two colors.
+ color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3;
+ color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
+ color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
+ color_array[2].a = 0xFF;
+
+ color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3;
+ color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
+ color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
+ color_array[3].a = 0xFF;
+
+ return 4;
+ }
+ else {
+ // Three-color block: derive the other color.
+ color_array[2].r = (color_array[0].r + color_array[1].r) / 2;
+ color_array[2].g = (color_array[0].g + color_array[1].g) / 2;
+ color_array[2].b = (color_array[0].b + color_array[1].b) / 2;
+ color_array[2].a = 0xFF;
+
+ // Set all components to 0 to match DXT specs.
+ color_array[3].r = 0x00; // color_array[2].r;
+ color_array[3].g = 0x00; // color_array[2].g;
+ color_array[3].b = 0x00; // color_array[2].b;
+ color_array[3].a = 0x00;
+
+ return 3;
+ }
+}
+
+// Evaluate palette assuming 3 color block.
+void BlockDXT1::evaluatePalette3(Color32 color_array[4]) const
+{
+ color_array[0].b = (col0.b << 3) | (col0.b >> 2);
+ color_array[0].g = (col0.g << 2) | (col0.g >> 4);
+ color_array[0].r = (col0.r << 3) | (col0.r >> 2);
+ color_array[0].a = 0xFF;
+
+ color_array[1].r = (col1.r << 3) | (col1.r >> 2);
+ color_array[1].g = (col1.g << 2) | (col1.g >> 4);
+ color_array[1].b = (col1.b << 3) | (col1.b >> 2);
+ color_array[1].a = 0xFF;
+
+ // Three-color block: derive the other color.
+ color_array[2].r = (color_array[0].r + color_array[1].r) / 2;
+ color_array[2].g = (color_array[0].g + color_array[1].g) / 2;
+ color_array[2].b = (color_array[0].b + color_array[1].b) / 2;
+ color_array[2].a = 0xFF;
+
+ // Set all components to 0 to match DXT specs.
+ color_array[3].r = 0x00; // color_array[2].r;
+ color_array[3].g = 0x00; // color_array[2].g;
+ color_array[3].b = 0x00; // color_array[2].b;
+ color_array[3].a = 0x00;
+}
+
+// Evaluate palette assuming 4 color block.
+void BlockDXT1::evaluatePalette4(Color32 color_array[4]) const
+{
+ color_array[0].b = (col0.b << 3) | (col0.b >> 2);
+ color_array[0].g = (col0.g << 2) | (col0.g >> 4);
+ color_array[0].r = (col0.r << 3) | (col0.r >> 2);
+ color_array[0].a = 0xFF;
+
+ color_array[1].r = (col1.r << 3) | (col1.r >> 2);
+ color_array[1].g = (col1.g << 2) | (col1.g >> 4);
+ color_array[1].b = (col1.b << 3) | (col1.b >> 2);
+ color_array[1].a = 0xFF;
+
+ // Four-color block: derive the other two colors.
+ color_array[2].r = (2 * color_array[0].r + color_array[1].r) / 3;
+ color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
+ color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
+ color_array[2].a = 0xFF;
+
+ color_array[3].r = (2 * color_array[1].r + color_array[0].r) / 3;
+ color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
+ color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
+ color_array[3].a = 0xFF;
+}
+
+void BlockDXT1::decodeBlock(ColorBlock * block) const
+{
+ // Decode color block.
+ Color32 color_array[4];
+ evaluatePalette(color_array);
+
+ // Write color block.
+ for( uint j = 0; j < 4; j++ ) {
+ for( uint i = 0; i < 4; i++ ) {
+ uint idx = (row[j] >> (2 * i)) & 3;
+ block->color(i, j) = color_array[idx];
+ }
+ }
+}
+
+void BlockDXT1::setIndices(int * idx)
+{
+ indices = 0;
+ for(uint i = 0; i < 16; i++) {
+ indices |= (idx[i] & 3) << (2 * i);
+ }
+}
+
+
+/// Flip DXT1 block vertically.
+inline void BlockDXT1::flip4()
+{
+ swap(row[0], row[3]);
+ swap(row[1], row[2]);
+}
+
+/// Flip half DXT1 block vertically.
+inline void BlockDXT1::flip2()
+{
+ swap(row[0], row[1]);
+}
+
+
+/*----------------------------------------------------------------------------
+ BlockDXT3
+----------------------------------------------------------------------------*/
+
+void BlockDXT3::decodeBlock(ColorBlock * block) const
+{
+ // Decode color.
+ color.decodeBlock(block);
+
+ // Decode alpha.
+ alpha.decodeBlock(block);
+}
+
+void AlphaBlockDXT3::decodeBlock(ColorBlock * block) const
+{
+ block->color(0x0).a = (alpha0 << 4) | alpha0;
+ block->color(0x1).a = (alpha1 << 4) | alpha1;
+ block->color(0x2).a = (alpha2 << 4) | alpha2;
+ block->color(0x3).a = (alpha3 << 4) | alpha3;
+ block->color(0x4).a = (alpha4 << 4) | alpha4;
+ block->color(0x5).a = (alpha5 << 4) | alpha5;
+ block->color(0x6).a = (alpha6 << 4) | alpha6;
+ block->color(0x7).a = (alpha7 << 4) | alpha7;
+ block->color(0x8).a = (alpha8 << 4) | alpha8;
+ block->color(0x9).a = (alpha9 << 4) | alpha9;
+ block->color(0xA).a = (alphaA << 4) | alphaA;
+ block->color(0xB).a = (alphaB << 4) | alphaB;
+ block->color(0xC).a = (alphaC << 4) | alphaC;
+ block->color(0xD).a = (alphaD << 4) | alphaD;
+ block->color(0xE).a = (alphaE << 4) | alphaE;
+ block->color(0xF).a = (alphaF << 4) | alphaF;
+}
+
+/// Flip DXT3 alpha block vertically.
+void AlphaBlockDXT3::flip4()
+{
+ swap(row[0], row[3]);
+ swap(row[1], row[2]);
+}
+
+/// Flip half DXT3 alpha block vertically.
+void AlphaBlockDXT3::flip2()
+{
+ swap(row[0], row[1]);
+}
+
+/// Flip DXT3 block vertically.
+void BlockDXT3::flip4()
+{
+ alpha.flip4();
+ color.flip4();
+}
+
+/// Flip half DXT3 block vertically.
+void BlockDXT3::flip2()
+{
+ alpha.flip2();
+ color.flip2();
+}
+
+
+/*----------------------------------------------------------------------------
+ BlockDXT5
+----------------------------------------------------------------------------*/
+
+void AlphaBlockDXT5::evaluatePalette(uint8 alpha[8]) const
+{
+ if (alpha0 > alpha1) {
+ evaluatePalette8(alpha);
+ }
+ else {
+ evaluatePalette6(alpha);
+ }
+}
+
+void AlphaBlockDXT5::evaluatePalette8(uint8 alpha[8]) const
+{
+ // 8-alpha block: derive the other six alphas.
+ // Bit code 000 = alpha0, 001 = alpha1, others are interpolated.
+ alpha[0] = alpha0;
+ alpha[1] = alpha1;
+ alpha[2] = (6 * alpha[0] + 1 * alpha[1]) / 7; // bit code 010
+ alpha[3] = (5 * alpha[0] + 2 * alpha[1]) / 7; // bit code 011
+ alpha[4] = (4 * alpha[0] + 3 * alpha[1]) / 7; // bit code 100
+ alpha[5] = (3 * alpha[0] + 4 * alpha[1]) / 7; // bit code 101
+ alpha[6] = (2 * alpha[0] + 5 * alpha[1]) / 7; // bit code 110
+ alpha[7] = (1 * alpha[0] + 6 * alpha[1]) / 7; // bit code 111
+}
+
+void AlphaBlockDXT5::evaluatePalette6(uint8 alpha[8]) const
+{
+ // 6-alpha block.
+ // Bit code 000 = alpha0, 001 = alpha1, others are interpolated.
+ alpha[0] = alpha0;
+ alpha[1] = alpha1;
+ alpha[2] = (4 * alpha[0] + 1 * alpha[1]) / 5; // Bit code 010
+ alpha[3] = (3 * alpha[0] + 2 * alpha[1]) / 5; // Bit code 011
+ alpha[4] = (2 * alpha[0] + 3 * alpha[1]) / 5; // Bit code 100
+ alpha[5] = (1 * alpha[0] + 4 * alpha[1]) / 5; // Bit code 101
+ alpha[6] = 0x00; // Bit code 110
+ alpha[7] = 0xFF; // Bit code 111
+}
+
+void AlphaBlockDXT5::indices(uint8 index_array[16]) const
+{
+ index_array[0x0] = bits0;
+ index_array[0x1] = bits1;
+ index_array[0x2] = bits2;
+ index_array[0x3] = bits3;
+ index_array[0x4] = bits4;
+ index_array[0x5] = bits5;
+ index_array[0x6] = bits6;
+ index_array[0x7] = bits7;
+ index_array[0x8] = bits8;
+ index_array[0x9] = bits9;
+ index_array[0xA] = bitsA;
+ index_array[0xB] = bitsB;
+ index_array[0xC] = bitsC;
+ index_array[0xD] = bitsD;
+ index_array[0xE] = bitsE;
+ index_array[0xF] = bitsF;
+}
+
+uint AlphaBlockDXT5::index(uint index) const
+{
+ int offset = (3 * index + 16);
+ return uint((this->u >> offset) & 0x7);
+}
+
+void AlphaBlockDXT5::setIndex(uint index, uint value)
+{
+ int offset = (3 * index + 16);
+ uint64 mask = uint64(0x7) << offset;
+ this->u = (this->u & ~mask) | (uint64(value) << offset);
+}
+
+void AlphaBlockDXT5::decodeBlock(ColorBlock * block) const
+{
+ uint8 alpha_array[8];
+ evaluatePalette(alpha_array);
+
+ uint8 index_array[16];
+ indices(index_array);
+
+ for(uint i = 0; i < 16; i++) {
+ block->color(i).a = alpha_array[index_array[i]];
+ }
+}
+
+void AlphaBlockDXT5::flip4()
+{
+ uint64 * b = (uint64 *)this;
+
+ // @@ The masks might have to be byte swapped.
+ uint64 tmp = (*b & (uint64)(0x000000000000FFFFLL));
+ tmp |= (*b & (uint64)(0x000000000FFF0000LL)) << 36;
+ tmp |= (*b & (uint64)(0x000000FFF0000000LL)) << 12;
+ tmp |= (*b & (uint64)(0x000FFF0000000000LL)) >> 12;
+ tmp |= (*b & (uint64)(0xFFF0000000000000LL)) >> 36;
+
+ *b = tmp;
+}
+
+void AlphaBlockDXT5::flip2()
+{
+ uint * b = (uint *)this;
+
+ // @@ The masks might have to be byte swapped.
+ uint tmp = (*b & 0xFF000000);
+ tmp |= (*b & 0x00000FFF) << 12;
+ tmp |= (*b & 0x00FFF000) >> 12;
+
+ *b = tmp;
+}
+
+void BlockDXT5::decodeBlock(ColorBlock * block) const
+{
+ // Decode color.
+ color.decodeBlock(block);
+
+ // Decode alpha.
+ alpha.decodeBlock(block);
+
+}
+
+/// Flip DXT5 block vertically.
+void BlockDXT5::flip4()
+{
+ alpha.flip4();
+ color.flip4();
+}
+
+/// Flip half DXT5 block vertically.
+void BlockDXT5::flip2()
+{
+ alpha.flip2();
+ color.flip2();
+}
+
+
+/// Decode ATI1 block.
+void BlockATI1::decodeBlock(ColorBlock * block) const
+{
+ uint8 alpha_array[8];
+ alpha.evaluatePalette(alpha_array);
+
+ uint8 index_array[16];
+ alpha.indices(index_array);
+
+ for(uint i = 0; i < 16; i++) {
+ Color32 & c = block->color(i);
+ c.b = c.g = c.r = alpha_array[index_array[i]];
+ c.a = 255;
+ }
+}
+
+/// Flip ATI1 block vertically.
+void BlockATI1::flip4()
+{
+ alpha.flip4();
+}
+
+/// Flip half ATI1 block vertically.
+void BlockATI1::flip2()
+{
+ alpha.flip2();
+}
+
+
+/// Decode ATI2 block.
+void BlockATI2::decodeBlock(ColorBlock * block) const
+{
+ uint8 alpha_array[8];
+ uint8 index_array[16];
+
+ x.evaluatePalette(alpha_array);
+ x.indices(index_array);
+
+ for(uint i = 0; i < 16; i++) {
+ Color32 & c = block->color(i);
+ c.r = alpha_array[index_array[i]];
+ }
+
+ y.evaluatePalette(alpha_array);
+ y.indices(index_array);
+
+ for(uint i = 0; i < 16; i++) {
+ Color32 & c = block->color(i);
+ c.g = alpha_array[index_array[i]];
+ c.b = 0;
+ c.a = 255;
+ }
+}
+
+/// Flip ATI2 block vertically.
+void BlockATI2::flip4()
+{
+ x.flip4();
+ y.flip4();
+}
+
+/// Flip half ATI2 block vertically.
+void BlockATI2::flip2()
+{
+ x.flip2();
+ y.flip2();
+}
+
+
+void BlockCTX1::evaluatePalette(Color32 color_array[4]) const
+{
+ // Does bit expansion before interpolation.
+ color_array[0].b = 0x00;
+ color_array[0].g = col0[1];
+ color_array[0].r = col0[0];
+ color_array[0].a = 0xFF;
+
+ color_array[1].r = 0x00;
+ color_array[1].g = col0[1];
+ color_array[1].b = col1[0];
+ color_array[1].a = 0xFF;
+
+ color_array[2].r = 0x00;
+ color_array[2].g = (2 * color_array[0].g + color_array[1].g) / 3;
+ color_array[2].b = (2 * color_array[0].b + color_array[1].b) / 3;
+ color_array[2].a = 0xFF;
+
+ color_array[3].r = 0x00;
+ color_array[3].g = (2 * color_array[1].g + color_array[0].g) / 3;
+ color_array[3].b = (2 * color_array[1].b + color_array[0].b) / 3;
+ color_array[3].a = 0xFF;
+}
+
+void BlockCTX1::decodeBlock(ColorBlock * block) const
+{
+ // Decode color block.
+ Color32 color_array[4];
+ evaluatePalette(color_array);
+
+ // Write color block.
+ for( uint j = 0; j < 4; j++ ) {
+ for( uint i = 0; i < 4; i++ ) {
+ uint idx = (row[j] >> (2 * i)) & 3;
+ block->color(i, j) = color_array[idx];
+ }
+ }
+}
+
+void BlockCTX1::setIndices(int * idx)
+{
+ indices = 0;
+ for(uint i = 0; i < 16; i++) {
+ indices |= (idx[i] & 3) << (2 * i);
+ }
+}
+
+
+/// Flip CTX1 block vertically.
+inline void BlockCTX1::flip4()
+{
+ swap(row[0], row[3]);
+ swap(row[1], row[2]);
+}
+
+/// Flip half CTX1 block vertically.
+inline void BlockCTX1::flip2()
+{
+ swap(row[0], row[1]);
+}
+
+void mem_read(Stream & mem, BlockDXT1 & block)
+{
+ mem_read(mem, block.col0.u);
+ mem_read(mem, block.col1.u);
+ mem_read(mem, block.indices);
+}
+
+void mem_read(Stream & mem, AlphaBlockDXT3 & block)
+{
+ for (unsigned int i = 0; i < 4; i++) mem_read(mem, block.row[i]);
+}
+
+void mem_read(Stream & mem, BlockDXT3 & block)
+{
+ mem_read(mem, block.alpha);
+ mem_read(mem, block.color);
+}
+
+void mem_read(Stream & mem, AlphaBlockDXT5 & block)
+{
+ mem_read(mem, block.u);
+}
+
+void mem_read(Stream & mem, BlockDXT5 & block)
+{
+ mem_read(mem, block.alpha);
+ mem_read(mem, block.color);
+}
+
+void mem_read(Stream & mem, BlockATI1 & block)
+{
+ mem_read(mem, block.alpha);
+}
+
+void mem_read(Stream & mem, BlockATI2 & block)
+{
+ mem_read(mem, block.x);
+ mem_read(mem, block.y);
+}
+
+void mem_read(Stream & mem, BlockCTX1 & block)
+{
+ mem_read(mem, block.col0[0]);
+ mem_read(mem, block.col0[1]);
+ mem_read(mem, block.col1[0]);
+ mem_read(mem, block.col1[1]);
+ mem_read(mem, block.indices);
+}
+
diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h
new file mode 100644
index 00000000000..5c232201f0c
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/BlockDXT.h
@@ -0,0 +1,248 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef _DDS_BLOCKDXT_H
+#define _DDS_BLOCKDXT_H
+
+#include <Common.h>
+#include <Color.h>
+#include <ColorBlock.h>
+#include <Stream.h>
+
+/// DXT1 block.
+struct BlockDXT1
+{
+ Color16 col0;
+ Color16 col1;
+ union {
+ uint8 row[4];
+ uint indices;
+ };
+
+ bool isFourColorMode() const;
+
+ uint evaluatePalette(Color32 color_array[4]) const;
+ uint evaluatePaletteFast(Color32 color_array[4]) const;
+ void evaluatePalette3(Color32 color_array[4]) const;
+ void evaluatePalette4(Color32 color_array[4]) const;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void setIndices(int * idx);
+
+ void flip4();
+ void flip2();
+};
+
+/// Return true if the block uses four color mode, false otherwise.
+inline bool BlockDXT1::isFourColorMode() const
+{
+ return col0.u > col1.u;
+}
+
+
+/// DXT3 alpha block with explicit alpha.
+struct AlphaBlockDXT3
+{
+ union {
+ struct {
+ uint alpha0 : 4;
+ uint alpha1 : 4;
+ uint alpha2 : 4;
+ uint alpha3 : 4;
+ uint alpha4 : 4;
+ uint alpha5 : 4;
+ uint alpha6 : 4;
+ uint alpha7 : 4;
+ uint alpha8 : 4;
+ uint alpha9 : 4;
+ uint alphaA : 4;
+ uint alphaB : 4;
+ uint alphaC : 4;
+ uint alphaD : 4;
+ uint alphaE : 4;
+ uint alphaF : 4;
+ };
+ uint16 row[4];
+ };
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+
+/// DXT3 block.
+struct BlockDXT3
+{
+ AlphaBlockDXT3 alpha;
+ BlockDXT1 color;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+
+/// DXT5 alpha block.
+struct AlphaBlockDXT5
+{
+ union {
+ struct {
+ unsigned int alpha0 : 8; // 8
+ unsigned int alpha1 : 8; // 16
+ unsigned int bits0 : 3; // 3 - 19
+ unsigned int bits1 : 3; // 6 - 22
+ unsigned int bits2 : 3; // 9 - 25
+ unsigned int bits3 : 3; // 12 - 28
+ unsigned int bits4 : 3; // 15 - 31
+ unsigned int bits5 : 3; // 18 - 34
+ unsigned int bits6 : 3; // 21 - 37
+ unsigned int bits7 : 3; // 24 - 40
+ unsigned int bits8 : 3; // 27 - 43
+ unsigned int bits9 : 3; // 30 - 46
+ unsigned int bitsA : 3; // 33 - 49
+ unsigned int bitsB : 3; // 36 - 52
+ unsigned int bitsC : 3; // 39 - 55
+ unsigned int bitsD : 3; // 42 - 58
+ unsigned int bitsE : 3; // 45 - 61
+ unsigned int bitsF : 3; // 48 - 64
+ };
+ uint64 u;
+ };
+
+ void evaluatePalette(uint8 alpha[8]) const;
+ void evaluatePalette8(uint8 alpha[8]) const;
+ void evaluatePalette6(uint8 alpha[8]) const;
+ void indices(uint8 index_array[16]) const;
+
+ uint index(uint index) const;
+ void setIndex(uint index, uint value);
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+
+/// DXT5 block.
+struct BlockDXT5
+{
+ AlphaBlockDXT5 alpha;
+ BlockDXT1 color;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+/// ATI1 block.
+struct BlockATI1
+{
+ AlphaBlockDXT5 alpha;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+/// ATI2 block.
+struct BlockATI2
+{
+ AlphaBlockDXT5 x;
+ AlphaBlockDXT5 y;
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+/// CTX1 block.
+struct BlockCTX1
+{
+ uint8 col0[2];
+ uint8 col1[2];
+ union {
+ uint8 row[4];
+ uint indices;
+ };
+
+ void evaluatePalette(Color32 color_array[4]) const;
+ void setIndices(int * idx);
+
+ void decodeBlock(ColorBlock * block) const;
+
+ void flip4();
+ void flip2();
+};
+
+void mem_read(Stream & mem, BlockDXT1 & block);
+void mem_read(Stream & mem, AlphaBlockDXT3 & block);
+void mem_read(Stream & mem, BlockDXT3 & block);
+void mem_read(Stream & mem, AlphaBlockDXT5 & block);
+void mem_read(Stream & mem, BlockDXT5 & block);
+void mem_read(Stream & mem, BlockATI1 & block);
+void mem_read(Stream & mem, BlockATI2 & block);
+void mem_read(Stream & mem, BlockCTX1 & block);
+
+#endif // _DDS_BLOCKDXT_H
diff --git a/source/blender/imbuf/intern/dds/Color.h b/source/blender/imbuf/intern/dds/Color.h
new file mode 100644
index 00000000000..f8055afdfc9
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Color.h
@@ -0,0 +1,99 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#ifndef _DDS_COLOR_H
+#define _DDS_COLOR_H
+
+/// 32 bit color stored as BGRA.
+class Color32
+{
+public:
+ Color32() { }
+ Color32(const Color32 & c) : u(c.u) { }
+ Color32(unsigned char R, unsigned char G, unsigned char B) { setRGBA(R, G, B, 0xFF); }
+ Color32(unsigned char R, unsigned char G, unsigned char B, unsigned char A) { setRGBA( R, G, B, A); }
+ //Color32(unsigned char c[4]) { setRGBA(c[0], c[1], c[2], c[3]); }
+ //Color32(float R, float G, float B) { setRGBA(uint(R*255), uint(G*255), uint(B*255), 0xFF); }
+ //Color32(float R, float G, float B, float A) { setRGBA(uint(R*255), uint(G*255), uint(B*255), uint(A*255)); }
+ Color32(unsigned int U) : u(U) { }
+
+ void setRGBA(unsigned char R, unsigned char G, unsigned char B, unsigned char A)
+ {
+ r = R;
+ g = G;
+ b = B;
+ a = A;
+ }
+
+ void setBGRA(unsigned char B, unsigned char G, unsigned char R, unsigned char A = 0xFF)
+ {
+ r = R;
+ g = G;
+ b = B;
+ a = A;
+ }
+
+ operator unsigned int () const {
+ return u;
+ }
+
+ union {
+ struct {
+ unsigned char b, g, r, a;
+ };
+ unsigned int u;
+ };
+};
+
+/// 16 bit 565 BGR color.
+class Color16
+{
+public:
+ Color16() { }
+ Color16(const Color16 & c) : u(c.u) { }
+ explicit Color16(unsigned short U) : u(U) { }
+
+ union {
+ struct {
+ unsigned short b : 5;
+ unsigned short g : 6;
+ unsigned short r : 5;
+ };
+ unsigned short u;
+ };
+};
+
+#endif // _DDS_COLOR_H
diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp
new file mode 100644
index 00000000000..0199d15ada7
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp
@@ -0,0 +1,317 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#include <ColorBlock.h>
+#include <Image.h>
+#include <Common.h>
+
+ // Get approximate luminance.
+ inline static uint colorLuminance(Color32 c)
+ {
+ return c.r + c.g + c.b;
+ }
+
+ // Get the euclidean distance between the given colors.
+ inline static uint colorDistance(Color32 c0, Color32 c1)
+ {
+ return (c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) + (c0.b - c1.b) * (c0.b - c1.b);
+ }
+
+
+/// Default constructor.
+ColorBlock::ColorBlock()
+{
+}
+
+/// Init the color block with the contents of the given block.
+ColorBlock::ColorBlock(const ColorBlock & block)
+{
+ for(uint i = 0; i < 16; i++) {
+ color(i) = block.color(i);
+ }
+}
+
+
+/// Initialize this color block.
+ColorBlock::ColorBlock(const Image * img, uint x, uint y)
+{
+ init(img, x, y);
+}
+
+void ColorBlock::init(const Image * img, uint x, uint y)
+{
+ const uint bw = min(img->width() - x, 4U);
+ const uint bh = min(img->height() - y, 4U);
+
+ static int remainder[] = {
+ 0, 0, 0, 0,
+ 0, 1, 0, 1,
+ 0, 1, 2, 0,
+ 0, 1, 2, 3,
+ };
+
+ // Blocks that are smaller than 4x4 are handled by repeating the pixels.
+ // @@ Thats only correct when block size is 1, 2 or 4, but not with 3. :(
+
+ for(uint i = 0; i < 4; i++) {
+ //const int by = i % bh;
+ const int by = remainder[(bh - 1) * 4 + i];
+ for(uint e = 0; e < 4; e++) {
+ //const int bx = e % bw;
+ const int bx = remainder[(bw - 1) * 4 + e];
+ color(e, i) = img->pixel(x + bx, y + by);
+ }
+ }
+}
+
+
+void ColorBlock::swizzleDXT5n()
+{
+ for(int i = 0; i < 16; i++)
+ {
+ Color32 c = m_color[i];
+ m_color[i] = Color32(0, c.g, 0, c.r);
+ }
+}
+
+void ColorBlock::splatX()
+{
+ for(int i = 0; i < 16; i++)
+ {
+ uint8 x = m_color[i].r;
+ m_color[i] = Color32(x, x, x, x);
+ }
+}
+
+void ColorBlock::splatY()
+{
+ for(int i = 0; i < 16; i++)
+ {
+ uint8 y = m_color[i].g;
+ m_color[i] = Color32(y, y, y, y);
+ }
+}
+
+
+/// Count number of unique colors in this color block.
+uint ColorBlock::countUniqueColors() const
+{
+ uint count = 0;
+
+ // @@ This does not have to be o(n^2)
+ for(int i = 0; i < 16; i++)
+ {
+ bool unique = true;
+ for(int j = 0; j < i; j++) {
+ if( m_color[i] != m_color[j] ) {
+ unique = false;
+ }
+ }
+
+ if( unique ) {
+ count++;
+ }
+ }
+
+ return count;
+}
+
+/// Get average color of the block.
+Color32 ColorBlock::averageColor() const
+{
+ uint r, g, b, a;
+ r = g = b = a = 0;
+
+ for(uint i = 0; i < 16; i++) {
+ r += m_color[i].r;
+ g += m_color[i].g;
+ b += m_color[i].b;
+ a += m_color[i].a;
+ }
+
+ return Color32(uint8(r / 16), uint8(g / 16), uint8(b / 16), uint8(a / 16));
+}
+
+/// Return true if the block is not fully opaque.
+bool ColorBlock::hasAlpha() const
+{
+ for (uint i = 0; i < 16; i++)
+ {
+ if (m_color[i].a != 255) return true;
+ }
+ return false;
+}
+
+
+/// Get diameter color range.
+void ColorBlock::diameterRange(Color32 * start, Color32 * end) const
+{
+ Color32 c0, c1;
+ uint best_dist = 0;
+
+ for(int i = 0; i < 16; i++) {
+ for (int j = i+1; j < 16; j++) {
+ uint dist = colorDistance(m_color[i], m_color[j]);
+ if( dist > best_dist ) {
+ best_dist = dist;
+ c0 = m_color[i];
+ c1 = m_color[j];
+ }
+ }
+ }
+
+ *start = c0;
+ *end = c1;
+}
+
+/// Get luminance color range.
+void ColorBlock::luminanceRange(Color32 * start, Color32 * end) const
+{
+ Color32 minColor, maxColor;
+ uint minLuminance, maxLuminance;
+
+ maxLuminance = minLuminance = colorLuminance(m_color[0]);
+
+ for(uint i = 1; i < 16; i++)
+ {
+ uint luminance = colorLuminance(m_color[i]);
+
+ if (luminance > maxLuminance) {
+ maxLuminance = luminance;
+ maxColor = m_color[i];
+ }
+ else if (luminance < minLuminance) {
+ minLuminance = luminance;
+ minColor = m_color[i];
+ }
+ }
+
+ *start = minColor;
+ *end = maxColor;
+}
+
+/// Get color range based on the bounding box.
+void ColorBlock::boundsRange(Color32 * start, Color32 * end) const
+{
+ Color32 minColor(255, 255, 255);
+ Color32 maxColor(0, 0, 0);
+
+ for(uint i = 0; i < 16; i++)
+ {
+ if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; }
+ if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; }
+ if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; }
+ if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; }
+ if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; }
+ if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; }
+ }
+
+ // Offset range by 1/16 of the extents
+ Color32 inset;
+ inset.r = (maxColor.r - minColor.r) >> 4;
+ inset.g = (maxColor.g - minColor.g) >> 4;
+ inset.b = (maxColor.b - minColor.b) >> 4;
+
+ minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255;
+ minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255;
+ minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255;
+
+ maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0;
+ maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0;
+ maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0;
+
+ *start = minColor;
+ *end = maxColor;
+}
+
+/// Get color range based on the bounding box.
+void ColorBlock::boundsRangeAlpha(Color32 * start, Color32 * end) const
+{
+ Color32 minColor(255, 255, 255, 255);
+ Color32 maxColor(0, 0, 0, 0);
+
+ for(uint i = 0; i < 16; i++)
+ {
+ if (m_color[i].r < minColor.r) { minColor.r = m_color[i].r; }
+ if (m_color[i].g < minColor.g) { minColor.g = m_color[i].g; }
+ if (m_color[i].b < minColor.b) { minColor.b = m_color[i].b; }
+ if (m_color[i].a < minColor.a) { minColor.a = m_color[i].a; }
+ if (m_color[i].r > maxColor.r) { maxColor.r = m_color[i].r; }
+ if (m_color[i].g > maxColor.g) { maxColor.g = m_color[i].g; }
+ if (m_color[i].b > maxColor.b) { maxColor.b = m_color[i].b; }
+ if (m_color[i].a > maxColor.a) { maxColor.a = m_color[i].a; }
+ }
+
+ // Offset range by 1/16 of the extents
+ Color32 inset;
+ inset.r = (maxColor.r - minColor.r) >> 4;
+ inset.g = (maxColor.g - minColor.g) >> 4;
+ inset.b = (maxColor.b - minColor.b) >> 4;
+ inset.a = (maxColor.a - minColor.a) >> 4;
+
+ minColor.r = (minColor.r + inset.r <= 255) ? minColor.r + inset.r : 255;
+ minColor.g = (minColor.g + inset.g <= 255) ? minColor.g + inset.g : 255;
+ minColor.b = (minColor.b + inset.b <= 255) ? minColor.b + inset.b : 255;
+ minColor.a = (minColor.a + inset.a <= 255) ? minColor.a + inset.a : 255;
+
+ maxColor.r = (maxColor.r >= inset.r) ? maxColor.r - inset.r : 0;
+ maxColor.g = (maxColor.g >= inset.g) ? maxColor.g - inset.g : 0;
+ maxColor.b = (maxColor.b >= inset.b) ? maxColor.b - inset.b : 0;
+ maxColor.a = (maxColor.a >= inset.a) ? maxColor.a - inset.a : 0;
+
+ *start = minColor;
+ *end = maxColor;
+}
+
+/// Sort colors by abosolute value in their 16 bit representation.
+void ColorBlock::sortColorsByAbsoluteValue()
+{
+ // Dummy selection sort.
+ for( uint a = 0; a < 16; a++ ) {
+ uint max = a;
+ Color16 cmax(m_color[a]);
+
+ for( uint b = a+1; b < 16; b++ ) {
+ Color16 cb(m_color[b]);
+
+ if( cb.u > cmax.u ) {
+ max = b;
+ cmax = cb;
+ }
+ }
+ swap( m_color[a], m_color[max] );
+ }
+}
diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h
new file mode 100644
index 00000000000..72049be5f3c
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/ColorBlock.h
@@ -0,0 +1,116 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#ifndef _DDS_COLORBLOCK_H
+#define _DDS_COLORBLOCK_H
+
+#include <Color.h>
+#include <Image.h>
+
+/// Uncompressed 4x4 color block.
+struct ColorBlock
+{
+ ColorBlock();
+ ColorBlock(const ColorBlock & block);
+ ColorBlock(const Image * img, uint x, uint y);
+
+ void init(const Image * img, uint x, uint y);
+
+ void swizzleDXT5n();
+ void splatX();
+ void splatY();
+
+ uint countUniqueColors() const;
+ Color32 averageColor() const;
+ bool hasAlpha() const;
+
+ void diameterRange(Color32 * start, Color32 * end) const;
+ void luminanceRange(Color32 * start, Color32 * end) const;
+ void boundsRange(Color32 * start, Color32 * end) const;
+ void boundsRangeAlpha(Color32 * start, Color32 * end) const;
+ void bestFitRange(Color32 * start, Color32 * end) const;
+
+ void sortColorsByAbsoluteValue();
+
+ float volume() const;
+
+ // Accessors
+ const Color32 * colors() const;
+
+ Color32 color(uint i) const;
+ Color32 & color(uint i);
+
+ Color32 color(uint x, uint y) const;
+ Color32 & color(uint x, uint y);
+
+private:
+
+ Color32 m_color[4*4];
+
+};
+
+
+/// Get pointer to block colors.
+inline const Color32 * ColorBlock::colors() const
+{
+ return m_color;
+}
+
+/// Get block color.
+inline Color32 ColorBlock::color(uint i) const
+{
+ return m_color[i];
+}
+
+/// Get block color.
+inline Color32 & ColorBlock::color(uint i)
+{
+ return m_color[i];
+}
+
+/// Get block color.
+inline Color32 ColorBlock::color(uint x, uint y) const
+{
+ return m_color[y * 4 + x];
+}
+
+/// Get block color.
+inline Color32 & ColorBlock::color(uint x, uint y)
+{
+ return m_color[y * 4 + x];
+}
+
+#endif // _DDS_COLORBLOCK_H
diff --git a/source/blender/imbuf/intern/dds/Common.h b/source/blender/imbuf/intern/dds/Common.h
new file mode 100644
index 00000000000..0c687e2ca9a
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Common.h
@@ -0,0 +1,56 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef _DDS_COMMON_H
+#define _DDS_COMMON_H
+
+#ifndef min
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#endif
+#ifndef max
+#define max(a,b) ((a) >= (b) ? (a) : (b))
+#endif
+#ifndef clamp
+#define clamp(x,a,b) min(max((x), (a)), (b))
+#endif
+
+template<typename T>
+inline void
+swap(T & a, T & b)
+{
+ T tmp = a;
+ a = b;
+ b = tmp;
+}
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint;
+typedef unsigned int uint32;
+typedef unsigned long long uint64;
+
+#endif
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
new file mode 100644
index 00000000000..f842c756ce1
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp
@@ -0,0 +1,1023 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#include <DirectDrawSurface.h>
+#include <BlockDXT.h>
+#include <PixelFormat.h>
+
+#include <stdio.h> // printf
+#include <math.h> // sqrt
+#include <sys/types.h>
+
+/*** declarations ***/
+
+#if !defined(MAKEFOURCC)
+# define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((uint)((unsigned char)(ch0)) | \
+ ((uint)((unsigned char)(ch1)) << 8) | \
+ ((uint)((unsigned char)(ch2)) << 16) | \
+ ((uint)((unsigned char)(ch3)) << 24 ))
+#endif
+
+static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
+static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
+static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
+static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
+static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
+static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
+static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B');
+static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1');
+static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
+
+// 32 bit RGB formats.
+static const uint D3DFMT_R8G8B8 = 20;
+static const uint D3DFMT_A8R8G8B8 = 21;
+static const uint D3DFMT_X8R8G8B8 = 22;
+static const uint D3DFMT_R5G6B5 = 23;
+static const uint D3DFMT_X1R5G5B5 = 24;
+static const uint D3DFMT_A1R5G5B5 = 25;
+static const uint D3DFMT_A4R4G4B4 = 26;
+static const uint D3DFMT_R3G3B2 = 27;
+static const uint D3DFMT_A8 = 28;
+static const uint D3DFMT_A8R3G3B2 = 29;
+static const uint D3DFMT_X4R4G4B4 = 30;
+static const uint D3DFMT_A2B10G10R10 = 31;
+static const uint D3DFMT_A8B8G8R8 = 32;
+static const uint D3DFMT_X8B8G8R8 = 33;
+static const uint D3DFMT_G16R16 = 34;
+static const uint D3DFMT_A2R10G10B10 = 35;
+
+static const uint D3DFMT_A16B16G16R16 = 36;
+
+// Palette formats.
+static const uint D3DFMT_A8P8 = 40;
+static const uint D3DFMT_P8 = 41;
+
+// Luminance formats.
+static const uint D3DFMT_L8 = 50;
+static const uint D3DFMT_A8L8 = 51;
+static const uint D3DFMT_A4L4 = 52;
+static const uint D3DFMT_L16 = 81;
+
+// Floating point formats
+static const uint D3DFMT_R16F = 111;
+static const uint D3DFMT_G16R16F = 112;
+static const uint D3DFMT_A16B16G16R16F = 113;
+static const uint D3DFMT_R32F = 114;
+static const uint D3DFMT_G32R32F = 115;
+static const uint D3DFMT_A32B32G32R32F = 116;
+
+static const uint DDSD_CAPS = 0x00000001U;
+static const uint DDSD_PIXELFORMAT = 0x00001000U;
+static const uint DDSD_WIDTH = 0x00000004U;
+static const uint DDSD_HEIGHT = 0x00000002U;
+static const uint DDSD_PITCH = 0x00000008U;
+static const uint DDSD_MIPMAPCOUNT = 0x00020000U;
+static const uint DDSD_LINEARSIZE = 0x00080000U;
+static const uint DDSD_DEPTH = 0x00800000U;
+
+static const uint DDSCAPS_COMPLEX = 0x00000008U;
+static const uint DDSCAPS_TEXTURE = 0x00001000U;
+static const uint DDSCAPS_MIPMAP = 0x00400000U;
+static const uint DDSCAPS2_VOLUME = 0x00200000U;
+static const uint DDSCAPS2_CUBEMAP = 0x00000200U;
+
+static const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U;
+static const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U;
+static const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U;
+static const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U;
+static const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U;
+static const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U;
+static const uint DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000FC00U;
+
+static const uint DDPF_ALPHAPIXELS = 0x00000001U;
+static const uint DDPF_ALPHA = 0x00000002U;
+static const uint DDPF_FOURCC = 0x00000004U;
+static const uint DDPF_RGB = 0x00000040U;
+static const uint DDPF_PALETTEINDEXED1 = 0x00000800U;
+static const uint DDPF_PALETTEINDEXED2 = 0x00001000U;
+static const uint DDPF_PALETTEINDEXED4 = 0x00000008U;
+static const uint DDPF_PALETTEINDEXED8 = 0x00000020U;
+static const uint DDPF_LUMINANCE = 0x00020000U;
+static const uint DDPF_ALPHAPREMULT = 0x00008000U;
+static const uint DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag.
+
+ // DX10 formats.
+ enum DXGI_FORMAT
+ {
+ DXGI_FORMAT_UNKNOWN = 0,
+
+ DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
+ DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
+ DXGI_FORMAT_R32G32B32A32_UINT = 3,
+ DXGI_FORMAT_R32G32B32A32_SINT = 4,
+
+ DXGI_FORMAT_R32G32B32_TYPELESS = 5,
+ DXGI_FORMAT_R32G32B32_FLOAT = 6,
+ DXGI_FORMAT_R32G32B32_UINT = 7,
+ DXGI_FORMAT_R32G32B32_SINT = 8,
+
+ DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
+ DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
+ DXGI_FORMAT_R16G16B16A16_UNORM = 11,
+ DXGI_FORMAT_R16G16B16A16_UINT = 12,
+ DXGI_FORMAT_R16G16B16A16_SNORM = 13,
+ DXGI_FORMAT_R16G16B16A16_SINT = 14,
+
+ DXGI_FORMAT_R32G32_TYPELESS = 15,
+ DXGI_FORMAT_R32G32_FLOAT = 16,
+ DXGI_FORMAT_R32G32_UINT = 17,
+ DXGI_FORMAT_R32G32_SINT = 18,
+
+ DXGI_FORMAT_R32G8X24_TYPELESS = 19,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
+ DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
+
+ DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
+ DXGI_FORMAT_R10G10B10A2_UNORM = 24,
+ DXGI_FORMAT_R10G10B10A2_UINT = 25,
+
+ DXGI_FORMAT_R11G11B10_FLOAT = 26,
+
+ DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
+ DXGI_FORMAT_R8G8B8A8_UNORM = 28,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
+ DXGI_FORMAT_R8G8B8A8_UINT = 30,
+ DXGI_FORMAT_R8G8B8A8_SNORM = 31,
+ DXGI_FORMAT_R8G8B8A8_SINT = 32,
+
+ DXGI_FORMAT_R16G16_TYPELESS = 33,
+ DXGI_FORMAT_R16G16_FLOAT = 34,
+ DXGI_FORMAT_R16G16_UNORM = 35,
+ DXGI_FORMAT_R16G16_UINT = 36,
+ DXGI_FORMAT_R16G16_SNORM = 37,
+ DXGI_FORMAT_R16G16_SINT = 38,
+
+ DXGI_FORMAT_R32_TYPELESS = 39,
+ DXGI_FORMAT_D32_FLOAT = 40,
+ DXGI_FORMAT_R32_FLOAT = 41,
+ DXGI_FORMAT_R32_UINT = 42,
+ DXGI_FORMAT_R32_SINT = 43,
+
+ DXGI_FORMAT_R24G8_TYPELESS = 44,
+ DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
+
+ DXGI_FORMAT_R8G8_TYPELESS = 48,
+ DXGI_FORMAT_R8G8_UNORM = 49,
+ DXGI_FORMAT_R8G8_UINT = 50,
+ DXGI_FORMAT_R8G8_SNORM = 51,
+ DXGI_FORMAT_R8G8_SINT = 52,
+
+ DXGI_FORMAT_R16_TYPELESS = 53,
+ DXGI_FORMAT_R16_FLOAT = 54,
+ DXGI_FORMAT_D16_UNORM = 55,
+ DXGI_FORMAT_R16_UNORM = 56,
+ DXGI_FORMAT_R16_UINT = 57,
+ DXGI_FORMAT_R16_SNORM = 58,
+ DXGI_FORMAT_R16_SINT = 59,
+
+ DXGI_FORMAT_R8_TYPELESS = 60,
+ DXGI_FORMAT_R8_UNORM = 61,
+ DXGI_FORMAT_R8_UINT = 62,
+ DXGI_FORMAT_R8_SNORM = 63,
+ DXGI_FORMAT_R8_SINT = 64,
+ DXGI_FORMAT_A8_UNORM = 65,
+
+ DXGI_FORMAT_R1_UNORM = 66,
+
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
+
+ DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
+ DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
+
+ DXGI_FORMAT_BC1_TYPELESS = 70,
+ DXGI_FORMAT_BC1_UNORM = 71,
+ DXGI_FORMAT_BC1_UNORM_SRGB = 72,
+
+ DXGI_FORMAT_BC2_TYPELESS = 73,
+ DXGI_FORMAT_BC2_UNORM = 74,
+ DXGI_FORMAT_BC2_UNORM_SRGB = 75,
+
+ DXGI_FORMAT_BC3_TYPELESS = 76,
+ DXGI_FORMAT_BC3_UNORM = 77,
+ DXGI_FORMAT_BC3_UNORM_SRGB = 78,
+
+ DXGI_FORMAT_BC4_TYPELESS = 79,
+ DXGI_FORMAT_BC4_UNORM = 80,
+ DXGI_FORMAT_BC4_SNORM = 81,
+
+ DXGI_FORMAT_BC5_TYPELESS = 82,
+ DXGI_FORMAT_BC5_UNORM = 83,
+ DXGI_FORMAT_BC5_SNORM = 84,
+
+ DXGI_FORMAT_B5G6R5_UNORM = 85,
+ DXGI_FORMAT_B5G5R5A1_UNORM = 86,
+ DXGI_FORMAT_B8G8R8A8_UNORM = 87,
+ DXGI_FORMAT_B8G8R8X8_UNORM = 88,
+ };
+
+ enum D3D10_RESOURCE_DIMENSION
+ {
+ D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
+ D3D10_RESOURCE_DIMENSION_BUFFER = 1,
+ D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2,
+ D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3,
+ D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4,
+ };
+
+/*** implementation ***/
+
+void mem_read(Stream & mem, DDSPixelFormat & pf)
+{
+ mem_read(mem, pf.size);
+ mem_read(mem, pf.flags);
+ mem_read(mem, pf.fourcc);
+ mem_read(mem, pf.bitcount);
+ mem_read(mem, pf.rmask);
+ mem_read(mem, pf.gmask);
+ mem_read(mem, pf.bmask);
+ mem_read(mem, pf.amask);
+}
+
+void mem_read(Stream & mem, DDSCaps & caps)
+{
+ mem_read(mem, caps.caps1);
+ mem_read(mem, caps.caps2);
+ mem_read(mem, caps.caps3);
+ mem_read(mem, caps.caps4);
+}
+
+void mem_read(Stream & mem, DDSHeader10 & header)
+{
+ mem_read(mem, header.dxgiFormat);
+ mem_read(mem, header.resourceDimension);
+ mem_read(mem, header.miscFlag);
+ mem_read(mem, header.arraySize);
+ mem_read(mem, header.reserved);
+}
+
+void mem_read(Stream & mem, DDSHeader & header)
+{
+ mem_read(mem, header.fourcc);
+ mem_read(mem, header.size);
+ mem_read(mem, header.flags);
+ mem_read(mem, header.height);
+ mem_read(mem, header.width);
+ mem_read(mem, header.pitch);
+ mem_read(mem, header.depth);
+ mem_read(mem, header.mipmapcount);
+ for (uint i = 0; i < 11; i++) mem_read(mem, header.reserved[i]);
+ mem_read(mem, header.pf);
+ mem_read(mem, header.caps);
+ mem_read(mem, header.notused);
+
+ if (header.hasDX10Header())
+ {
+ mem_read(mem, header.header10);
+ }
+}
+
+
+
+DDSHeader::DDSHeader()
+{
+ this->fourcc = FOURCC_DDS;
+ this->size = 124;
+ this->flags = (DDSD_CAPS|DDSD_PIXELFORMAT);
+ this->height = 0;
+ this->width = 0;
+ this->pitch = 0;
+ this->depth = 0;
+ this->mipmapcount = 0;
+ for (uint i = 0; i < 11; i++) this->reserved[i] = 0;
+
+ // Store version information on the reserved header attributes.
+ this->reserved[9] = MAKEFOURCC('N', 'V', 'T', 'T');
+ this->reserved[10] = (0 << 16) | (9 << 8) | (5); // major.minor.revision
+
+ this->pf.size = 32;
+ this->pf.flags = 0;
+ this->pf.fourcc = 0;
+ this->pf.bitcount = 0;
+ this->pf.rmask = 0;
+ this->pf.gmask = 0;
+ this->pf.bmask = 0;
+ this->pf.amask = 0;
+ this->caps.caps1 = DDSCAPS_TEXTURE;
+ this->caps.caps2 = 0;
+ this->caps.caps3 = 0;
+ this->caps.caps4 = 0;
+ this->notused = 0;
+
+ this->header10.dxgiFormat = DXGI_FORMAT_UNKNOWN;
+ this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_UNKNOWN;
+ this->header10.miscFlag = 0;
+ this->header10.arraySize = 0;
+ this->header10.reserved = 0;
+}
+
+void DDSHeader::setWidth(uint w)
+{
+ this->flags |= DDSD_WIDTH;
+ this->width = w;
+}
+
+void DDSHeader::setHeight(uint h)
+{
+ this->flags |= DDSD_HEIGHT;
+ this->height = h;
+}
+
+void DDSHeader::setDepth(uint d)
+{
+ this->flags |= DDSD_DEPTH;
+ this->height = d;
+}
+
+void DDSHeader::setMipmapCount(uint count)
+{
+ if (count == 0 || count == 1)
+ {
+ this->flags &= ~DDSD_MIPMAPCOUNT;
+ this->mipmapcount = 0;
+
+ if (this->caps.caps2 == 0) {
+ this->caps.caps1 = DDSCAPS_TEXTURE;
+ }
+ else {
+ this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
+ }
+ }
+ else
+ {
+ this->flags |= DDSD_MIPMAPCOUNT;
+ this->mipmapcount = count;
+
+ this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
+ }
+}
+
+void DDSHeader::setTexture2D()
+{
+ this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
+}
+
+void DDSHeader::setTexture3D()
+{
+ this->caps.caps2 = DDSCAPS2_VOLUME;
+
+ this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
+}
+
+void DDSHeader::setTextureCube()
+{
+ this->caps.caps1 |= DDSCAPS_COMPLEX;
+ this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES;
+
+ this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
+ this->header10.arraySize = 6;
+}
+
+void DDSHeader::setLinearSize(uint size)
+{
+ this->flags &= ~DDSD_PITCH;
+ this->flags |= DDSD_LINEARSIZE;
+ this->pitch = size;
+}
+
+void DDSHeader::setPitch(uint pitch)
+{
+ this->flags &= ~DDSD_LINEARSIZE;
+ this->flags |= DDSD_PITCH;
+ this->pitch = pitch;
+}
+
+void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
+{
+ // set fourcc pixel format.
+ this->pf.flags = DDPF_FOURCC;
+ this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
+ this->pf.bitcount = 0;
+ this->pf.rmask = 0;
+ this->pf.gmask = 0;
+ this->pf.bmask = 0;
+ this->pf.amask = 0;
+}
+
+void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
+{
+ // Make sure the masks are correct.
+ if ((rmask & gmask) || \
+ (rmask & bmask) || \
+ (rmask & amask) || \
+ (gmask & bmask) || \
+ (gmask & amask) || \
+ (bmask & amask)) {
+ printf("DDS: bad RGBA masks, pixel format not set\n");
+ return;
+ }
+
+ this->pf.flags = DDPF_RGB;
+
+ if (amask != 0) {
+ this->pf.flags |= DDPF_ALPHAPIXELS;
+ }
+
+ if (bitcount == 0)
+ {
+ // Compute bit count from the masks.
+ uint total = rmask | gmask | bmask | amask;
+ while(total != 0) {
+ bitcount++;
+ total >>= 1;
+ }
+ }
+
+ if (!(bitcount > 0 && bitcount <= 32)) {
+ printf("DDS: bad bit count, pixel format not set\n");
+ return;
+ }
+
+ // Align to 8.
+ if (bitcount < 8) bitcount = 8;
+ else if (bitcount < 16) bitcount = 16;
+ else if (bitcount < 24) bitcount = 24;
+ else bitcount = 32;
+
+ this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask);
+ this->pf.bitcount = bitcount;
+ this->pf.rmask = rmask;
+ this->pf.gmask = gmask;
+ this->pf.bmask = bmask;
+ this->pf.amask = amask;
+}
+
+void DDSHeader::setDX10Format(uint format)
+{
+ this->pf.flags = 0;
+ this->header10.dxgiFormat = format;
+}
+
+void DDSHeader::setNormalFlag(bool b)
+{
+ if (b) this->pf.flags |= DDPF_NORMAL;
+ else this->pf.flags &= ~DDPF_NORMAL;
+}
+
+bool DDSHeader::hasDX10Header() const
+{
+ return this->pf.flags == 0;
+}
+
+DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header()
+{
+ mem_read(stream, header);
+}
+
+DirectDrawSurface::~DirectDrawSurface()
+{
+}
+
+bool DirectDrawSurface::isValid() const
+{
+ if (header.fourcc != FOURCC_DDS || header.size != 124)
+ {
+ return false;
+ }
+
+ const uint required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT);
+ if( (header.flags & required) != required ) {
+ return false;
+ }
+
+ if (header.pf.size != 32) {
+ return false;
+ }
+
+ /* in some files DDSCAPS_TEXTURE is missing: silently ignore */
+ /*
+ if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) {
+ return false;
+ }
+ */
+
+ return true;
+}
+
+bool DirectDrawSurface::isSupported() const
+{
+ if (header.pf.flags & DDPF_FOURCC)
+ {
+ if (header.pf.fourcc != FOURCC_DXT1 &&
+ header.pf.fourcc != FOURCC_DXT2 &&
+ header.pf.fourcc != FOURCC_DXT3 &&
+ header.pf.fourcc != FOURCC_DXT4 &&
+ header.pf.fourcc != FOURCC_DXT5 &&
+ header.pf.fourcc != FOURCC_RXGB &&
+ header.pf.fourcc != FOURCC_ATI1 &&
+ header.pf.fourcc != FOURCC_ATI2)
+ {
+ // Unknown fourcc code.
+ return false;
+ }
+ }
+ else if (header.pf.flags & DDPF_RGB)
+ {
+ // All RGB formats are supported now.
+ }
+ else
+ {
+ return false;
+ }
+
+ if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES)
+ {
+ // Cubemaps must contain all faces.
+ return false;
+ }
+
+ if (isTexture3D())
+ {
+ // @@ 3D textures not supported yet.
+ return false;
+ }
+
+ return true;
+}
+
+
+uint DirectDrawSurface::mipmapCount() const
+{
+ if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount;
+ else return 0;
+}
+
+
+uint DirectDrawSurface::width() const
+{
+ if (header.flags & DDSD_WIDTH) return header.width;
+ else return 1;
+}
+
+uint DirectDrawSurface::height() const
+{
+ if (header.flags & DDSD_HEIGHT) return header.height;
+ else return 1;
+}
+
+uint DirectDrawSurface::depth() const
+{
+ if (header.flags & DDSD_DEPTH) return header.depth;
+ else return 1;
+}
+
+bool DirectDrawSurface::hasAlpha() const
+{
+ if ((header.pf.flags & DDPF_RGB) && (header.pf.amask == 0))
+ {
+ return false;
+ }
+ else if (header.pf.fourcc == FOURCC_DXT1)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+bool DirectDrawSurface::isTexture2D() const
+{
+ return !isTexture3D() && !isTextureCube();
+}
+
+bool DirectDrawSurface::isTexture3D() const
+{
+ return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0;
+}
+
+bool DirectDrawSurface::isTextureCube() const
+{
+ return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0;
+}
+
+void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
+{
+ stream.seek(offset(face, mipmap));
+
+ uint w = width();
+ uint h = height();
+
+ // Compute width and height.
+ for (uint m = 0; m < mipmap; m++)
+ {
+ w = max(1U, w / 2);
+ h = max(1U, h / 2);
+ }
+
+ img->allocate(w, h);
+
+ if (header.pf.flags & DDPF_RGB)
+ {
+ readLinearImage(img);
+ }
+ else if (header.pf.flags & DDPF_FOURCC)
+ {
+ readBlockImage(img);
+ }
+}
+
+void DirectDrawSurface::readLinearImage(Image * img)
+{
+
+ const uint w = img->width();
+ const uint h = img->height();
+
+ uint rshift, rsize;
+ PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize);
+
+ uint gshift, gsize;
+ PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize);
+
+ uint bshift, bsize;
+ PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize);
+
+ uint ashift, asize;
+ PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize);
+
+ uint byteCount = (header.pf.bitcount + 7) / 8;
+
+ if (byteCount > 4)
+ {
+ /* just in case... we could have segfaults later on if byteCount > 4 */
+ printf("DDS: bitcount too large");
+ return;
+ }
+
+ if (header.pf.amask != 0)
+ {
+ img->setFormat(Image::Format_ARGB);
+ }
+
+ // Read linear RGB images.
+ for (uint y = 0; y < h; y++)
+ {
+ for (uint x = 0; x < w; x++)
+ {
+ uint c = 0;
+ mem_read(stream, (unsigned char *)(&c), byteCount);
+
+ Color32 pixel(0, 0, 0, 0xFF);
+ pixel.r = PixelFormat::convert(c >> rshift, rsize, 8);
+ pixel.g = PixelFormat::convert(c >> gshift, gsize, 8);
+ pixel.b = PixelFormat::convert(c >> bshift, bsize, 8);
+ pixel.a = PixelFormat::convert(c >> ashift, asize, 8);
+
+ img->pixel(x, y) = pixel;
+ }
+ }
+}
+
+void DirectDrawSurface::readBlockImage(Image * img)
+{
+ const uint w = img->width();
+ const uint h = img->height();
+
+ const uint bw = (w + 3) / 4;
+ const uint bh = (h + 3) / 4;
+
+ for (uint by = 0; by < bh; by++)
+ {
+ for (uint bx = 0; bx < bw; bx++)
+ {
+ ColorBlock block;
+
+ // Read color block.
+ readBlock(&block);
+
+ // Write color block.
+ for (uint y = 0; y < min(4U, h-4*by); y++)
+ {
+ for (uint x = 0; x < min(4U, w-4*bx); x++)
+ {
+ img->pixel(4*bx+x, 4*by+y) = block.color(x, y);
+ }
+ }
+ }
+ }
+}
+
+static Color32 buildNormal(uint8 x, uint8 y)
+{
+ float nx = 2 * (x / 255.0f) - 1;
+ float ny = 2 * (y / 255.0f) - 1;
+ float nz = 0.0f;
+ if (1 - nx*nx - ny*ny > 0) nz = sqrt(1 - nx*nx - ny*ny);
+ uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255);
+
+ return Color32(x, y, z);
+}
+
+
+void DirectDrawSurface::readBlock(ColorBlock * rgba)
+{
+ if (header.pf.fourcc == FOURCC_DXT1)
+ {
+ BlockDXT1 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+ }
+ else if (header.pf.fourcc == FOURCC_DXT2 ||
+ header.pf.fourcc == FOURCC_DXT3)
+ {
+ BlockDXT3 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+ }
+ else if (header.pf.fourcc == FOURCC_DXT4 ||
+ header.pf.fourcc == FOURCC_DXT5 ||
+ header.pf.fourcc == FOURCC_RXGB)
+ {
+ BlockDXT5 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+
+ if (header.pf.fourcc == FOURCC_RXGB)
+ {
+ // Swap R & A.
+ for (int i = 0; i < 16; i++)
+ {
+ Color32 & c = rgba->color(i);
+ uint tmp = c.r;
+ c.r = c.a;
+ c.a = tmp;
+ }
+ }
+ }
+ else if (header.pf.fourcc == FOURCC_ATI1)
+ {
+ BlockATI1 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+ }
+ else if (header.pf.fourcc == FOURCC_ATI2)
+ {
+ BlockATI2 block;
+ mem_read(stream, block);
+ block.decodeBlock(rgba);
+ }
+
+ // If normal flag set, convert to normal.
+ if (header.pf.flags & DDPF_NORMAL)
+ {
+ if (header.pf.fourcc == FOURCC_ATI2)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ Color32 & c = rgba->color(i);
+ c = buildNormal(c.r, c.g);
+ }
+ }
+ else if (header.pf.fourcc == FOURCC_DXT5)
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ Color32 & c = rgba->color(i);
+ c = buildNormal(c.a, c.g);
+ }
+ }
+ }
+}
+
+
+uint DirectDrawSurface::blockSize() const
+{
+ switch(header.pf.fourcc)
+ {
+ case FOURCC_DXT1:
+ case FOURCC_ATI1:
+ return 8;
+ case FOURCC_DXT2:
+ case FOURCC_DXT3:
+ case FOURCC_DXT4:
+ case FOURCC_DXT5:
+ case FOURCC_RXGB:
+ case FOURCC_ATI2:
+ return 16;
+ };
+
+ // Not a block image.
+ return 0;
+}
+
+uint DirectDrawSurface::mipmapSize(uint mipmap) const
+{
+ uint w = width();
+ uint h = height();
+ uint d = depth();
+
+ for (uint m = 0; m < mipmap; m++)
+ {
+ w = max(1U, w / 2);
+ h = max(1U, h / 2);
+ d = max(1U, d / 2);
+ }
+
+ if (header.pf.flags & DDPF_FOURCC)
+ {
+ // @@ How are 3D textures aligned?
+ w = (w + 3) / 4;
+ h = (h + 3) / 4;
+ return blockSize() * w * h;
+ }
+ else if (header.pf.flags & DDPF_RGB)
+ {
+ // Align pixels to bytes.
+ uint byteCount = (header.pf.bitcount + 7) / 8;
+
+ // Align pitch to 4 bytes.
+ uint pitch = 4 * ((w * byteCount + 3) / 4);
+
+ return pitch * h * d;
+ }
+ else {
+ printf("DDS: mipmap format not supported\n");
+ return(0);
+ };
+}
+
+uint DirectDrawSurface::faceSize() const
+{
+ const uint count = mipmapCount();
+ uint size = 0;
+
+ for (uint m = 0; m < count; m++)
+ {
+ size += mipmapSize(m);
+ }
+
+ return size;
+}
+
+uint DirectDrawSurface::offset(const uint face, const uint mipmap)
+{
+ uint size = 128; //sizeof(DDSHeader);
+
+ if (face != 0)
+ {
+ size += face * faceSize();
+ }
+
+ for (uint m = 0; m < mipmap; m++)
+ {
+ size += mipmapSize(m);
+ }
+
+ return size;
+}
+
+
+void DirectDrawSurface::printInfo() const
+{
+ /* printf("FOURCC: %c%c%c%c\n", ((unsigned char *)&header.fourcc)[0], ((unsigned char *)&header.fourcc)[1], ((unsigned char *)&header.fourcc)[2], ((unsigned char *)&header.fourcc)[3]); */
+ printf("Flags: 0x%.8X\n", header.flags);
+ if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n");
+ if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n");
+ if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n");
+ if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n");
+ if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n");
+ if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n");
+ if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n");
+ if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n");
+
+ printf("Height: %d\n", header.height);
+ printf("Width: %d\n", header.width);
+ printf("Depth: %d\n", header.depth);
+ if (header.flags & DDSD_PITCH) printf("Pitch: %d\n", header.pitch);
+ else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %d\n", header.pitch);
+ printf("Mipmap count: %d\n", header.mipmapcount);
+
+ printf("Pixel Format:\n");
+ /* printf("\tSize: %d\n", header.pf.size); */
+ printf("\tFlags: 0x%.8X\n", header.pf.flags);
+ if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n");
+ if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n");
+ if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n");
+ if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n");
+ if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n");
+ if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n");
+ if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n");
+ if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n");
+ if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n");
+ if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n");
+
+ printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF));
+ printf("\tBit count: %d\n", header.pf.bitcount);
+ printf("\tRed mask: 0x%.8X\n", header.pf.rmask);
+ printf("\tGreen mask: 0x%.8X\n", header.pf.gmask);
+ printf("\tBlue mask: 0x%.8X\n", header.pf.bmask);
+ printf("\tAlpha mask: 0x%.8X\n", header.pf.amask);
+
+ printf("Caps:\n");
+ printf("\tCaps 1: 0x%.8X\n", header.caps.caps1);
+ if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n");
+ if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n");
+ if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n");
+
+ printf("\tCaps 2: 0x%.8X\n", header.caps.caps2);
+ if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n");
+ else if (header.caps.caps2 & DDSCAPS2_CUBEMAP)
+ {
+ printf("\t\tDDSCAPS2_CUBEMAP\n");
+ if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n");
+ else {
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n");
+ if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n");
+ }
+ }
+
+ printf("\tCaps 3: 0x%.8X\n", header.caps.caps3);
+ printf("\tCaps 4: 0x%.8X\n", header.caps.caps4);
+
+ if (header.pf.flags == 0)
+ {
+ printf("DX10 Header:\n");
+ printf("\tDXGI Format: %u\n", header.header10.dxgiFormat);
+ printf("\tResource dimension: %u\n", header.header10.resourceDimension);
+ printf("\tMisc flag: %u\n", header.header10.miscFlag);
+ printf("\tArray size: %u\n", header.header10.arraySize);
+ }
+
+ if (header.reserved[9] == MAKEFOURCC('N', 'V', 'T', 'T'))
+ {
+ int major = (header.reserved[10] >> 16) & 0xFF;
+ int minor = (header.reserved[10] >> 8) & 0xFF;
+ int revision= header.reserved[10] & 0xFF;
+
+ printf("Version:\n");
+ printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision);
+ }
+}
+
diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
new file mode 100644
index 00000000000..d29d82f53f9
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h
@@ -0,0 +1,181 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef _DDS_DIRECTDRAWSURFACE_H
+#define _DDS_DIRECTDRAWSURFACE_H
+
+#include <Common.h>
+#include <Stream.h>
+#include <ColorBlock.h>
+#include <Image.h>
+
+struct DDSPixelFormat
+{
+ uint size;
+ uint flags;
+ uint fourcc;
+ uint bitcount;
+ uint rmask;
+ uint gmask;
+ uint bmask;
+ uint amask;
+};
+
+struct DDSCaps
+{
+ uint caps1;
+ uint caps2;
+ uint caps3;
+ uint caps4;
+};
+
+/// DDS file header for DX10.
+struct DDSHeader10
+{
+ uint dxgiFormat;
+ uint resourceDimension;
+ uint miscFlag;
+ uint arraySize;
+ uint reserved;
+};
+
+/// DDS file header.
+struct DDSHeader
+{
+ uint fourcc;
+ uint size;
+ uint flags;
+ uint height;
+ uint width;
+ uint pitch;
+ uint depth;
+ uint mipmapcount;
+ uint reserved[11];
+ DDSPixelFormat pf;
+ DDSCaps caps;
+ uint notused;
+ DDSHeader10 header10;
+
+
+ // Helper methods.
+ DDSHeader();
+
+ void setWidth(uint w);
+ void setHeight(uint h);
+ void setDepth(uint d);
+ void setMipmapCount(uint count);
+ void setTexture2D();
+ void setTexture3D();
+ void setTextureCube();
+ void setLinearSize(uint size);
+ void setPitch(uint pitch);
+ void setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3);
+ void setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask);
+ void setDX10Format(uint format);
+ void setNormalFlag(bool b);
+
+ bool hasDX10Header() const;
+};
+
+/// DirectDraw Surface. (DDS)
+class DirectDrawSurface
+{
+public:
+ DirectDrawSurface(unsigned char *mem, uint size);
+ ~DirectDrawSurface();
+
+ bool isValid() const;
+ bool isSupported() const;
+
+ uint mipmapCount() const;
+ uint width() const;
+ uint height() const;
+ uint depth() const;
+ bool isTexture2D() const;
+ bool isTexture3D() const;
+ bool isTextureCube() const;
+ bool hasAlpha() const; /* false for DXT1, true for all other DXTs */
+
+ void mipmap(Image * img, uint f, uint m);
+ // void mipmap(FloatImage * img, uint f, uint m);
+
+ void printInfo() const;
+
+private:
+
+ uint blockSize() const;
+ uint faceSize() const;
+ uint mipmapSize(uint m) const;
+
+ uint offset(uint f, uint m);
+
+ void readLinearImage(Image * img);
+ void readBlockImage(Image * img);
+ void readBlock(ColorBlock * rgba);
+
+
+private:
+ Stream stream; // memory where DDS file resides
+ DDSHeader header;
+};
+
+void mem_read(Stream & mem, DDSPixelFormat & pf);
+void mem_read(Stream & mem, DDSCaps & caps);
+void mem_read(Stream & mem, DDSHeader & header);
+void mem_read(Stream & mem, DDSHeader10 & header);
+
+#endif // _DDS_DIRECTDRAWSURFACE_H
diff --git a/source/blender/imbuf/intern/dds/Image.cpp b/source/blender/imbuf/intern/dds/Image.cpp
new file mode 100644
index 00000000000..d8be7857c3f
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Image.cpp
@@ -0,0 +1,132 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#include <Color.h>
+#include <Image.h>
+
+#include <stdio.h> // printf
+
+Image::Image() : m_width(0), m_height(0), m_format(Format_RGB), m_data(0)
+{
+}
+
+Image::~Image()
+{
+ free();
+}
+
+void Image::allocate(uint w, uint h)
+{
+ free();
+ m_width = w;
+ m_height = h;
+ m_data = new Color32[w * h];
+}
+
+void Image::free()
+{
+ if (m_data) delete [] m_data;
+ m_data = 0;
+}
+
+
+uint Image::width() const
+{
+ return m_width;
+}
+
+uint Image::height() const
+{
+ return m_height;
+}
+
+const Color32 * Image::scanline(uint h) const
+{
+ if (h >= m_height) {
+ printf("DDS: scanline beyond dimensions of image");
+ return m_data;
+ }
+ return m_data + h * m_width;
+}
+
+Color32 * Image::scanline(uint h)
+{
+ if (h >= m_height) {
+ printf("DDS: scanline beyond dimensions of image");
+ return m_data;
+ }
+ return m_data + h * m_width;
+}
+
+const Color32 * Image::pixels() const
+{
+ return m_data;
+}
+
+Color32 * Image::pixels()
+{
+ return m_data;
+}
+
+const Color32 & Image::pixel(uint idx) const
+{
+ if (idx >= m_width * m_height) {
+ printf("DDS: pixel beyond dimensions of image");
+ return m_data[0];
+ }
+ return m_data[idx];
+}
+
+Color32 & Image::pixel(uint idx)
+{
+ if (idx >= m_width * m_height) {
+ printf("DDS: pixel beyond dimensions of image");
+ return m_data[0];
+ }
+ return m_data[idx];
+}
+
+
+Image::Format Image::format() const
+{
+ return m_format;
+}
+
+void Image::setFormat(Image::Format f)
+{
+ m_format = f;
+}
+
diff --git a/source/blender/imbuf/intern/dds/Image.h b/source/blender/imbuf/intern/dds/Image.h
new file mode 100644
index 00000000000..0241839d01d
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Image.h
@@ -0,0 +1,104 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// This code is in the public domain -- castanyo@yahoo.es
+
+#ifndef _DDS_IMAGE_H
+#define _DDS_IMAGE_H
+
+#include <Common.h>
+#include <Color.h>
+
+/// 32 bit RGBA image.
+class Image
+{
+public:
+
+ enum Format
+ {
+ Format_RGB,
+ Format_ARGB,
+ };
+
+ Image();
+ ~Image();
+
+ void allocate(uint w, uint h);
+ /*
+ bool load(const char * name);
+
+ void wrap(void * data, uint w, uint h);
+ void unwrap();
+ */
+
+ uint width() const;
+ uint height() const;
+
+ const Color32 * scanline(uint h) const;
+ Color32 * scanline(uint h);
+
+ const Color32 * pixels() const;
+ Color32 * pixels();
+
+ const Color32 & pixel(uint idx) const;
+ Color32 & pixel(uint idx);
+
+ const Color32 & pixel(uint x, uint y) const;
+ Color32 & pixel(uint x, uint y);
+
+ Format format() const;
+ void setFormat(Format f);
+
+private:
+ void free();
+
+private:
+ uint m_width;
+ uint m_height;
+ Format m_format;
+ Color32 * m_data;
+};
+
+
+inline const Color32 & Image::pixel(uint x, uint y) const
+{
+ return pixel(y * width() + x);
+}
+
+inline Color32 & Image::pixel(uint x, uint y)
+{
+ return pixel(y * width() + x);
+}
+
+#endif // _DDS_IMAGE_H
diff --git a/source/blender/imbuf/intern/dds/Makefile b/source/blender/imbuf/intern/dds/Makefile
new file mode 100644
index 00000000000..88d59080a47
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Makefile
@@ -0,0 +1,63 @@
+#
+# $Id: Makefile 7037 2006-03-12 14:11:23Z ton $
+#
+# ***** BEGIN GPL/BL DUAL 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. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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 (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = dds
+DIR = $(OCGDIR)/blender/imbuf/dds
+SOURCEDIR = source/blender/imbuf/intern/dds
+
+include nan_compile.mk
+include nan_definitions.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I$(NAN_JPEG)/include
+CPPFLAGS += -I$(NAN_PNG)/include
+CPPFLAGS += -I$(NAN_ZLIB)/include
+CPPFLAGS += -I$(NAN_TIFF)/include
+CPPFLAGS += -I../../../include
+CPPFLAGS += -I../../../blenkernel
+CPPFLAGS += -I../../../blenlib
+CPPFLAGS += -I../../../avi
+CPPFLAGS += -I../../../quicktime
+# path to the guarded memory allocator
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+# This is not really needed, but until /include is cleaned, it must be
+# there for proper compilation.
+# - No, it is also needed in antialias, for listbase (nzc)
+CPPFLAGS += -I../../../makesdna
+# external interface of this module
+CPPFLAGS += -I../..
+CPPFLAGS += -I..
+CPPFLAGS += -I.
+CPPFLAGS += -DWITH_DDS
diff --git a/source/blender/imbuf/intern/dds/PixelFormat.h b/source/blender/imbuf/intern/dds/PixelFormat.h
new file mode 100644
index 00000000000..93f55f8266a
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/PixelFormat.h
@@ -0,0 +1,110 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+ * This file is based on a similar file from the NVIDIA texture tools
+ * (http://nvidia-texture-tools.googlecode.com/)
+ *
+ * Original license from NVIDIA follows.
+ */
+
+// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef _DDS_PIXELFORMAT_H
+#define _DDS_PIXELFORMAT_H
+
+#include <Common.h>
+
+ namespace PixelFormat
+ {
+
+ // Convert component @a c having @a inbits to the returned value having @a outbits.
+ inline uint convert(uint c, uint inbits, uint outbits)
+ {
+ if (inbits == 0)
+ {
+ return 0;
+ }
+ else if (inbits >= outbits)
+ {
+ // truncate
+ return c >> (inbits - outbits);
+ }
+ else
+ {
+ // bitexpand
+ return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits);
+ }
+ }
+
+ // Get pixel component shift and size given its mask.
+ inline void maskShiftAndSize(uint mask, uint * shift, uint * size)
+ {
+ if (!mask)
+ {
+ *shift = 0;
+ *size = 0;
+ return;
+ }
+
+ *shift = 0;
+ while((mask & 1) == 0) {
+ ++(*shift);
+ mask >>= 1;
+ }
+
+ *size = 0;
+ while((mask & 1) == 1) {
+ ++(*size);
+ mask >>= 1;
+ }
+ }
+
+ } // PixelFormat namespace
+
+#endif // _DDS_IMAGE_PIXELFORMAT_H
diff --git a/source/blender/imbuf/intern/dds/SConscript b/source/blender/imbuf/intern/dds/SConscript
new file mode 100644
index 00000000000..d005bae02be
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/SConscript
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+Import ('env')
+
+source_files = ['dds_api.cpp', 'DirectDrawSurface.cpp', 'Stream.cpp', 'BlockDXT.cpp', 'ColorBlock.cpp', 'Image.cpp']
+
+incs = ['.',
+ '../../',
+ '../..',
+ '..',
+ '../../../makesdna',
+ '../../../blenkernel',
+ '../../../blenlib',
+ 'intern/include',
+ '#/intern/guardedalloc']
+
+
+defs = ['WITH_DDS']
+
+env.BlenderLib ('bf_dds', source_files, incs, defs, libtype=['core','player'], priority = [90, 200])
diff --git a/source/blender/imbuf/intern/dds/Stream.cpp b/source/blender/imbuf/intern/dds/Stream.cpp
new file mode 100644
index 00000000000..2340598b4fa
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Stream.cpp
@@ -0,0 +1,99 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <Stream.h>
+
+#include <stdio.h> // printf
+#include <string.h> // memcpy
+
+unsigned int Stream::seek(unsigned int p)
+{
+ if (p > size) {
+ printf("DDS: trying to seek beyond end of stream (corrupt file?)");
+ }
+ else {
+ pos = p;
+ }
+
+ return pos;
+}
+
+unsigned int mem_read(Stream & mem, unsigned long long & i)
+{
+ if (mem.pos + 8 > mem.size) {
+ printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ return(0);
+ };
+ memcpy(&i, mem.mem + mem.pos, 8); // @@ todo: make sure little endian
+ mem.pos += 8;
+ return(8);
+}
+
+unsigned int mem_read(Stream & mem, unsigned int & i)
+{
+ if (mem.pos + 4 > mem.size) {
+ printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ return(0);
+ };
+ memcpy(&i, mem.mem + mem.pos, 4); // @@ todo: make sure little endian
+ mem.pos += 4;
+ return(4);
+}
+
+unsigned int mem_read(Stream & mem, unsigned short & i)
+{
+ if (mem.pos + 2 > mem.size) {
+ printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ return(0);
+ };
+ memcpy(&i, mem.mem + mem.pos, 2); // @@ todo: make sure little endian
+ mem.pos += 2;
+ return(2);
+}
+
+unsigned int mem_read(Stream & mem, unsigned char & i)
+{
+ if (mem.pos + 1 > mem.size) {
+ printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ return(0);
+ };
+ i = (mem.mem + mem.pos)[0];
+ mem.pos += 1;
+ return(1);
+}
+
+unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt)
+{
+ if (mem.pos + cnt > mem.size) {
+ printf("DDS: trying to read beyond end of stream (corrupt file?)");
+ return(0);
+ };
+ memcpy(i, mem.mem + mem.pos, cnt);
+ mem.pos += cnt;
+ return(cnt);
+}
+
diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h
new file mode 100644
index 00000000000..373e68db44e
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/Stream.h
@@ -0,0 +1,49 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/* simple memory stream functions with buffer overflow check */
+
+#ifndef _STREAM_H
+#define _STREAM_H
+
+struct Stream
+{
+ unsigned char *mem; // location in memory
+ unsigned int size; // size
+ unsigned int pos; // current position
+ Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {};
+ unsigned int seek(unsigned int p);
+};
+
+unsigned int mem_read(Stream & mem, unsigned long long & i);
+unsigned int mem_read(Stream & mem, unsigned int & i);
+unsigned int mem_read(Stream & mem, unsigned short & i);
+unsigned int mem_read(Stream & mem, unsigned char & i);
+unsigned int mem_read(Stream & mem, unsigned char *i, unsigned int cnt);
+
+#endif // _STREAM_H
+
diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp
new file mode 100644
index 00000000000..3de30b9f183
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/dds_api.cpp
@@ -0,0 +1,132 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <dds_api.h>
+#include <Stream.h>
+#include <DirectDrawSurface.h>
+#include <stdio.h> // printf
+#include <fstream>
+
+extern "C" {
+
+#include "imbuf.h"
+#include "imbuf_patch.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "IMB_allocimbuf.h"
+
+
+short imb_save_dds(struct ImBuf * ibuf, char *name, int flags)
+{
+ return(0); /* todo: finish this function */
+
+ /* check image buffer */
+ if (ibuf == 0) return (0);
+ if (ibuf->rect == 0) return (0);
+
+ /* open file for writing */
+ std::ofstream fildes(name);
+
+ /* write header */
+ fildes << "DDS ";
+ fildes.close();
+
+ return(1);
+}
+
+int imb_is_a_dds(unsigned char *mem) // note: use at most first 32 bytes
+{
+ /* heuristic check to see if mem contains a DDS file */
+ /* header.fourcc == FOURCC_DDS */
+ if ((mem[0] != 'D') || (mem[1] != 'D') || (mem[2] != 'S') || (mem[3] != ' ')) return(0);
+ /* header.size == 124 */
+ if ((mem[4] != 124) || mem[5] || mem[6] || mem[7]) return(0);
+ return(1);
+}
+
+struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags)
+{
+ struct ImBuf * ibuf = 0;
+ DirectDrawSurface dds(mem, size); /* reads header */
+ unsigned char bits_per_pixel;
+ unsigned int *rect;
+ Image img;
+ unsigned int numpixels = 0;
+ int col;
+ unsigned char *cp = (unsigned char *) &col;
+ Color32 pixel;
+ Color32 *pixels = 0;
+
+ /* check if DDS is valid and supported */
+ if (!dds.isValid()) {
+ printf("DDS: not valid; header follows\n");
+ dds.printInfo();
+ return(0);
+ }
+ if (!dds.isSupported()) {
+ printf("DDS: format not supported\n");
+ return(0);
+ }
+ if ((dds.width() > 65535) || (dds.height() > 65535)) {
+ printf("DDS: dimensions too large\n");
+ return(0);
+ }
+
+ /* convert DDS into ImBuf */
+ if (dds.hasAlpha()) bits_per_pixel = 32;
+ else bits_per_pixel = 24;
+ ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0, 0);
+ if (ibuf == 0) return(0); /* memory allocation failed */
+
+ ibuf->ftype = DDS;
+
+ if ((flags & IB_test) == 0) {
+ if (!imb_addrectImBuf(ibuf)) return(ibuf);
+ if (ibuf->rect == 0) return(ibuf);
+
+ rect = ibuf->rect;
+ dds.mipmap(&img, 0, 0); /* load first face, first mipmap */
+ pixels = img.pixels();
+ numpixels = dds.width() * dds.height();
+ cp[3] = 0xff; /* default alpha if alpha channel is not present */
+
+ for (unsigned int i = 0; i < numpixels; i++) {
+ pixel = pixels[i];
+ cp[0] = pixel.r; /* set R component of col */
+ cp[1] = pixel.g; /* set G component of col */
+ cp[2] = pixel.b; /* set B component of col */
+ if (bits_per_pixel == 32)
+ cp[3] = pixel.a; /* set A component of col */
+ rect[i] = col;
+ }
+ IMB_flipy(ibuf);
+ }
+
+ return(ibuf);
+}
+
+} // extern "C"
diff --git a/source/blender/imbuf/intern/dds/dds_api.h b/source/blender/imbuf/intern/dds/dds_api.h
new file mode 100644
index 00000000000..8a0f966dd68
--- /dev/null
+++ b/source/blender/imbuf/intern/dds/dds_api.h
@@ -0,0 +1,43 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * Contributors: Amorilia (amorilia@gamebox.net)
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef _DDS_API_H
+#define _DDS_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+short imb_save_dds(struct ImBuf *ibuf, char *name, int flags);
+int imb_is_a_dds(unsigned char *mem); /* use only first 32 bytes of mem */
+struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DDS_API_H */
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index a4fab4a3572..8db07f581f5 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -174,7 +174,7 @@ void IMB_gamwarp(struct ImBuf *ibuf, double gamma)
}
}
-#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val))
+#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.99f*val))
void IMB_rect_from_float(struct ImBuf *ibuf)
{
diff --git a/source/blender/imbuf/intern/dynlibtiff.c b/source/blender/imbuf/intern/dynlibtiff.c
index cdcb995bcff..4a96af8bf2b 100644
--- a/source/blender/imbuf/intern/dynlibtiff.c
+++ b/source/blender/imbuf/intern/dynlibtiff.c
@@ -83,13 +83,19 @@ void libtiff_loadlibtiff(void)
/* Try to find libtiff in a couple of standard places */
libtiff = PIL_dynlib_open("libtiff.so");
if (libtiff != NULL) return;
+ libtiff = PIL_dynlib_open("libtiff.so.3");
+ if (libtiff != NULL) return;
libtiff = PIL_dynlib_open("libtiff.dll");
if (libtiff != NULL) return;
libtiff = PIL_dynlib_open("/usr/lib/libtiff.so");
if (libtiff != NULL) return;
- /* OSX has version specific library */
libtiff = PIL_dynlib_open("/usr/lib/libtiff.so.3");
if (libtiff != NULL) return;
+ /* OSX has version specific library */
+#ifdef __x86_64__
+ libtiff = PIL_dynlib_open("/usr/lib64/libtiff.so.3");
+ if (libtiff != NULL) return;
+#endif
libtiff = PIL_dynlib_open("/usr/local/lib/libtiff.so");
if (libtiff != NULL) return;
/* For solaris */
diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c
index fd9dac1af2b..1be5cf99e19 100644
--- a/source/blender/imbuf/intern/filter.c
+++ b/source/blender/imbuf/intern/filter.c
@@ -240,18 +240,72 @@ void IMB_filter(struct ImBuf *ibuf)
imb_filterx(ibuf);
}
-#define EXTEND_PIXEL(a, w) if((a)[3]) {r+= w*(a)[0]; g+= w*(a)[1]; b+= w*(a)[2]; tot+=w;}
+#define EXTEND_PIXEL(color, w) if((color)[3]) {r+= w*(color)[0]; g+= w*(color)[1]; b+= w*(color)[2]; a+= w*(color)[3]; tot+=w;}
-/* if alpha is zero, it checks surrounding pixels and averages color. sets new alphas to 255 */
-void IMB_filter_extend(struct ImBuf *ibuf)
+/* if alpha is zero, it checks surrounding pixels and averages color. sets new alphas to 1.0
+ *
+ * When a mask is given, only effect pixels with a mask value of 1, defined as BAKE_MASK_MARGIN in rendercore.c
+ * */
+void IMB_filter_extend(struct ImBuf *ibuf, char *mask)
{
register char *row1, *row2, *row3;
- register char *cp;
+ register char *cp;
int rowlen, x, y;
rowlen= ibuf->x;
- if(ibuf->rect) {
+
+ if (ibuf->rect_float) {
+ float *temprect;
+ float *row1f, *row2f, *row3f;
+ float *fp;
+ temprect= MEM_dupallocN(ibuf->rect_float);
+
+ for(y=1; y<=ibuf->y; y++) {
+ /* setup rows */
+ row1f= (float *)(temprect + (y-2)*rowlen*4);
+ row2f= row1f + 4*rowlen;
+ row3f= row2f + 4*rowlen;
+ if(y==1)
+ row1f= row2f;
+ else if(y==ibuf->y)
+ row3f= row2f;
+
+ fp= (float *)(ibuf->rect_float + (y-1)*rowlen*4);
+
+ for(x=0; x<rowlen; x++) {
+ if((mask==NULL && fp[3]==0.0f) || (mask && mask[((y-1)*rowlen)+x]==1)) {
+ int tot= 0;
+ float r=0.0f, g=0.0f, b=0.0f, a=0.0f;
+
+ EXTEND_PIXEL(row1f, 1);
+ EXTEND_PIXEL(row2f, 2);
+ EXTEND_PIXEL(row3f, 1);
+ EXTEND_PIXEL(row1f+4, 2);
+ EXTEND_PIXEL(row3f+4, 2);
+ if(x!=rowlen-1) {
+ EXTEND_PIXEL(row1f+8, 1);
+ EXTEND_PIXEL(row2f+8, 2);
+ EXTEND_PIXEL(row3f+8, 1);
+ }
+ if(tot) {
+ fp[0]= r/tot;
+ fp[1]= g/tot;
+ fp[2]= b/tot;
+ fp[3]= a/tot;
+ }
+ }
+ fp+=4;
+
+ if(x!=0) {
+ row1f+=4; row2f+=4; row3f+=4;
+ }
+ }
+ }
+
+ MEM_freeN(temprect);
+ }
+ else if(ibuf->rect) {
int *temprect;
/* make a copy, to prevent flooding */
@@ -270,8 +324,9 @@ void IMB_filter_extend(struct ImBuf *ibuf)
cp= (char *)(ibuf->rect + (y-1)*rowlen);
for(x=0; x<rowlen; x++) {
- if(cp[3]==0) {
- int tot= 0, r=0, g=0, b=0;
+ /*if(cp[3]==0) {*/
+ if((mask==NULL && cp[3]==0) || (mask && mask[((y-1)*rowlen)+x]==1)) {
+ int tot= 0, r=0, g=0, b=0, a=0;
EXTEND_PIXEL(row1, 1);
EXTEND_PIXEL(row2, 2);
@@ -287,10 +342,10 @@ void IMB_filter_extend(struct ImBuf *ibuf)
cp[0]= r/tot;
cp[1]= g/tot;
cp[2]= b/tot;
- cp[3]= 255;
+ cp[3]= a/tot;
}
}
- cp+=4;
+ cp+=4;
if(x!=0) {
row1+=4; row2+=4; row3+=4;
diff --git a/source/blender/imbuf/intern/gen_dynlibtiff.py b/source/blender/imbuf/intern/gen_dynlibtiff.py
index 1ee0275854a..de3236da6c2 100755
--- a/source/blender/imbuf/intern/gen_dynlibtiff.py
+++ b/source/blender/imbuf/intern/gen_dynlibtiff.py
@@ -125,13 +125,19 @@ void libtiff_loadlibtiff(void)
/* Try to find libtiff in a couple of standard places */
libtiff = PIL_dynlib_open("libtiff.so");
if (libtiff != NULL) return;
+ libtiff = PIL_dynlib_open("libtiff.so.3");
+ if (libtiff != NULL) return;
libtiff = PIL_dynlib_open("libtiff.dll");
if (libtiff != NULL) return;
libtiff = PIL_dynlib_open("/usr/lib/libtiff.so");
if (libtiff != NULL) return;
- /* OSX has version specific library */
libtiff = PIL_dynlib_open("/usr/lib/libtiff.so.3");
if (libtiff != NULL) return;
+ /* OSX has version specific library */
+#ifdef __x86_64__
+ libtiff = PIL_dynlib_open("/usr/lib64/libtiff.so.3");
+ if (libtiff != NULL) return;
+#endif
libtiff = PIL_dynlib_open("/usr/local/lib/libtiff.so");
if (libtiff != NULL) return;
/* For solaris */
diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c
index f98244c5a0f..aa09fc3ee38 100644
--- a/source/blender/imbuf/intern/imageprocess.c
+++ b/source/blender/imbuf/intern/imageprocess.c
@@ -42,26 +42,37 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "math.h"
+
+/* This define should be relocated to a global header some where Kent Mein
+I stole it from util.h in the plugins api */
+#define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
/* Only this one is used liberally here, and in imbuf */
void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf)
{
- int size, do_float=0;
+ int size;
unsigned char rt, *cp = (unsigned char *)ibuf->rect;
float rtf, *cpf = ibuf->rect_float;
-
- if (ibuf->rect_float) do_float = 1;
- size = ibuf->x * ibuf->y;
-
- while(size-- > 0) {
- rt= cp[0];
- cp[0]= cp[3];
- cp[3]= rt;
- rt= cp[1];
- cp[1]= cp[2];
- cp[2]= rt;
- cp+= 4;
- if (do_float) {
+
+ if (ibuf->rect) {
+ size = ibuf->x * ibuf->y;
+
+ while(size-- > 0) {
+ rt= cp[0];
+ cp[0]= cp[3];
+ cp[3]= rt;
+ rt= cp[1];
+ cp[1]= cp[2];
+ cp[2]= rt;
+ cp+= 4;
+ }
+ }
+
+ if (ibuf->rect_float) {
+ size = ibuf->x * ibuf->y;
+
+ while(size-- > 0) {
rtf= cpf[0];
cpf[0]= cpf[3];
cpf[3]= rtf;
@@ -73,3 +84,224 @@ void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf)
}
}
+/**************************************************************************
+* INTERPOLATIONS
+*
+* Reference and docs:
+* http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms
+***************************************************************************/
+
+/* BICUBIC Interpolation functions */
+/* More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation
+*/
+/* function assumes out to be zero'ed, only does RGBA */
+static float P(float k){
+ float aux;
+ aux=(float)(1.0f/6.0f)*( pow( MAX2(k+2.0f,0) , 3.0f ) - 4.0f * pow( MAX2(k+1.0f,0) , 3.0f ) + 6.0f * pow( MAX2(k,0) , 3.0f ) - 4.0f * pow( MAX2(k-1.0f,0) , 3.0f));
+ return aux ;
+}
+
+void bicubic_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, int yout)
+{
+ int i,j,n,m,x1,y1;
+ unsigned char *dataI,*outI;
+ float a,b, outR,outG,outB,outA,*dataF,*outF;
+ int do_rect, do_float;
+
+ if (in == NULL) return;
+ if (in->rect == NULL && in->rect_float == NULL) return;
+
+ do_rect= (out->rect != NULL);
+ do_float= (out->rect_float != NULL);
+
+ i= (int)floor(x);
+ j= (int)floor(y);
+ a= x - i;
+ b= y - j;
+
+ outR= 0.0f;
+ outG= 0.0f;
+ outB= 0.0f;
+ outA= 0.0f;
+ for(n= -1; n<= 2; n++){
+ for(m= -1; m<= 2; m++){
+ x1= i+n;
+ y1= j+m;
+ if (x1>0 && x1 < in->x && y1>0 && y1<in->y) {
+ if (do_float) {
+ dataF= in->rect_float + in->x * y1 * 4 + 4*x1;
+ outR+= dataF[0] * P(n-a) * P(b-m);
+ outG+= dataF[1] * P(n-a) * P(b-m);
+ outB+= dataF[2] * P(n-a) * P(b-m);
+ outA+= dataF[3] * P(n-a) * P(b-m);
+ }
+ if (do_rect) {
+ dataI= (unsigned char*)in->rect + in->x * y1 * 4 + 4*x1;
+ outR+= dataI[0] * P(n-a) * P(b-m);
+ outG+= dataI[1] * P(n-a) * P(b-m);
+ outB+= dataI[2] * P(n-a) * P(b-m);
+ outA+= dataI[3] * P(n-a) * P(b-m);
+ }
+ }
+ }
+ }
+ if (do_rect) {
+ outI= (unsigned char *)out->rect + out->x * yout * 4 + 4*xout;
+ outI[0]= (int)outR;
+ outI[1]= (int)outG;
+ outI[2]= (int)outB;
+ outI[3]= (int)outA;
+ }
+ if (do_float) {
+ outF= (float *)out->rect_float + out->x * yout * 4 + 4*xout;
+ outF[0]= outR;
+ outF[1]= outG;
+ outF[2]= outB;
+ outF[3]= outA;
+ }
+}
+
+/* function assumes out to be zero'ed, only does RGBA */
+/* BILINEAR INTERPOLATION */
+void bilinear_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, int yout)
+{
+ float *row1, *row2, *row3, *row4, a, b, *outF;
+ unsigned char *row1I, *row2I, *row3I, *row4I, *outI;
+ float a_b, ma_b, a_mb, ma_mb;
+ float empty[4]= {0.0f, 0.0f, 0.0f, 0.0f};
+ unsigned char emptyI[4]= {0, 0, 0, 0};
+ int y1, y2, x1, x2;
+ int do_rect, do_float;
+
+ if (in==NULL) return;
+ if (in->rect==NULL && in->rect_float==NULL) return;
+
+ do_rect= (out->rect != NULL);
+ do_float= (out->rect_float != NULL);
+
+ x1= (int)floor(u);
+ x2= (int)ceil(u);
+ y1= (int)floor(v);
+ y2= (int)ceil(v);
+
+ // sample area entirely outside image?
+ if (x2<0 || x1>in->x-1 || y2<0 || y1>in->y-1) return;
+
+ if (do_rect)
+ outI=(unsigned char *)out->rect + out->x * yout * 4 + 4*xout;
+ else
+ outI= NULL;
+ if (do_float)
+ outF=(float *)out->rect_float + out->x * yout * 4 + 4*xout;
+ else
+ outF= NULL;
+
+ if (do_float) {
+ // sample including outside of edges of image
+ if (x1<0 || y1<0) row1= empty;
+ else row1= (float *)in->rect_float + in->x * y1 * 4 + 4*x1;
+
+ if (x1<0 || y2>in->y-1) row2= empty;
+ else row2= (float *)in->rect_float + in->x * y2 * 4 + 4*x1;
+
+ if (x2>in->x-1 || y1<0) row3= empty;
+ else row3= (float *)in->rect_float + in->x * y1 * 4 + 4*x2;
+
+ if (x2>in->x-1 || y2>in->y-1) row4= empty;
+ else row4= (float *)in->rect_float + in->x * y2 * 4 + 4*x2;
+
+ a= u-floor(u);
+ b= v-floor(v);
+ a_b= a*b; ma_b= (1.0f-a)*b; a_mb= a*(1.0f-b); ma_mb= (1.0f-a)*(1.0f-b);
+
+ outF[0]= ma_mb*row1[0] + a_mb*row3[0] + ma_b*row2[0]+ a_b*row4[0];
+ outF[1]= ma_mb*row1[1] + a_mb*row3[1] + ma_b*row2[1]+ a_b*row4[1];
+ outF[2]= ma_mb*row1[2] + a_mb*row3[2] + ma_b*row2[2]+ a_b*row4[2];
+ outF[3]= ma_mb*row1[3] + a_mb*row3[3] + ma_b*row2[3]+ a_b*row4[3];
+ }
+ if (do_rect) {
+ // sample including outside of edges of image
+ if (x1<0 || y1<0) row1I= emptyI;
+ else row1I= (unsigned char *)in->rect + in->x * y1 * 4 + 4*x1;
+
+ if (x1<0 || y2>in->y-1) row2I= emptyI;
+ else row2I= (unsigned char *)in->rect + in->x * y2 * 4 + 4*x1;
+
+ if (x2>in->x-1 || y1<0) row3I= emptyI;
+ else row3I= (unsigned char *)in->rect + in->x * y1 * 4 + 4*x2;
+
+ if (x2>in->x-1 || y2>in->y-1) row4I= emptyI;
+ else row4I= (unsigned char *)in->rect + in->x * y2 * 4 + 4*x2;
+
+ a= u-floor(u);
+ b= v-floor(v);
+ a_b= a*b; ma_b= (1.0f-a)*b; a_mb= a*(1.0f-b); ma_mb= (1.0f-a)*(1.0f-b);
+
+ outI[0]= ma_mb*row1I[0] + a_mb*row3I[0] + ma_b*row2I[0]+ a_b*row4I[0];
+ outI[1]= ma_mb*row1I[1] + a_mb*row3I[1] + ma_b*row2I[1]+ a_b*row4I[1];
+ outI[2]= ma_mb*row1I[2] + a_mb*row3I[2] + ma_b*row2I[2]+ a_b*row4I[2];
+ outI[3]= ma_mb*row1I[3] + a_mb*row3I[3] + ma_b*row2I[3]+ a_b*row4I[3];
+ }
+}
+
+/* function assumes out to be zero'ed, only does RGBA */
+/* NEAREST INTERPOLATION */
+void neareast_interpolation(ImBuf *in, ImBuf *out, float u, float v,int xout, int yout)
+{
+ float *outF,*dataF;
+ unsigned char *dataI,*outI;
+ int y1, x1;
+ int do_rect, do_float;
+
+ if (in==NULL) return;
+ if (in->rect==NULL && in->rect_float==NULL) return;
+
+ do_rect= (out->rect != NULL);
+ do_float= (out->rect_float != NULL);
+
+ x1= (int)(u);
+ y1= (int)(v);
+
+ if (do_rect)
+ outI=(unsigned char *)out->rect + out->x * yout * 4 + 4*xout;
+ else
+ outI= NULL;
+ if (do_float)
+ outF=(float *)out->rect_float + out->x * yout * 4 + 4*xout;
+ else
+ outF= NULL;
+
+ // sample area entirely outside image?
+ if (x1<0 || x1>in->x-1 || y1<0 || y1>in->y-1) return;
+
+ // sample including outside of edges of image
+ if (x1<0 || y1<0) {
+ if (do_rect) {
+ outI[0]= 0;
+ outI[1]= 0;
+ outI[2]= 0;
+ outI[3]= 0;
+ }
+ if (do_float) {
+ outF[0]= 0.0f;
+ outF[1]= 0.0f;
+ outF[2]= 0.0f;
+ outF[3]= 0.0f;
+ }
+ } else {
+ dataI= (unsigned char *)in->rect + in->x * y1 * 4 + 4*x1;
+ if (do_rect) {
+ outI[0]= dataI[0];
+ outI[1]= dataI[1];
+ outI[2]= dataI[2];
+ outI[3]= dataI[3];
+ }
+ dataF= in->rect_float + in->x * y1 * 4 + 4*x1;
+ if (do_float) {
+ outF[0]= dataF[0];
+ outF[1]= dataF[1];
+ outF[2]= dataF[2];
+ outF[3]= dataF[3];
+ }
+ }
+}
diff --git a/source/blender/imbuf/intern/imginfo.c b/source/blender/imbuf/intern/imginfo.c
new file mode 100644
index 00000000000..37bde9e5ac3
--- /dev/null
+++ b/source/blender/imbuf/intern/imginfo.c
@@ -0,0 +1,158 @@
+/**
+ * $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 (C) 2005 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Austin Benesh. Ton Roosendaal.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "BLI_blenlib.h"
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "IMB_imginfo.h"
+
+
+
+void IMB_imginfo_free(struct ImBuf* img)
+{
+ ImgInfo *info;
+
+ if (!img)
+ return;
+ if (!img->img_info) {
+ return;
+ }
+ info = img->img_info;
+ while (info) {
+ ImgInfo* next = info->next;
+ MEM_freeN(info->key);
+ MEM_freeN(info->value);
+ MEM_freeN(info);
+ info = next;
+ }
+}
+
+int IMB_imginfo_get_field(struct ImBuf* img, const char* key, char* field, int len)
+{
+ ImgInfo *info;
+ int retval = 0;
+
+ if (!img)
+ return 0;
+ if (!img->img_info) {
+ return 0;
+ }
+ info = img->img_info;
+ while (info) {
+ if (strcmp(key, info->key) == 0) {
+ BLI_strncpy(field, info->value, len);
+ retval = 1;
+ break;
+ }
+ info = info->next;
+ }
+ return retval;
+}
+
+int IMB_imginfo_add_field(struct ImBuf* img, const char* key, const char* field)
+{
+ ImgInfo *info;
+ ImgInfo *last;
+
+ if (!img)
+ return 0;
+
+ if (!img->img_info) {
+ img->img_info = MEM_callocN(sizeof(ImgInfo), "ImgInfo");
+ info = img->img_info;
+ } else {
+ info = img->img_info;
+ last = info;
+ while (info) {
+ last = info;
+ info = info->next;
+ }
+ info = MEM_callocN(sizeof(ImgInfo), "ImgInfo");
+ last->next = info;
+ }
+ info->key = BLI_strdup(key);
+ info->value = BLI_strdup(field);
+ return 1;
+}
+
+int IMB_imginfo_del_field(struct ImBuf *img, const char *key)
+{
+ ImgInfo *p, *p1;
+
+ if ((!img) || (!img->img_info))
+ return (0);
+
+ p = img->img_info;
+ p1 = NULL;
+ while (p) {
+ if (!strcmp (key, p->key)) {
+ if (p1)
+ p1->next = p->next;
+ else
+ img->img_info = p->next;
+
+ MEM_freeN(p->key);
+ MEM_freeN(p->value);
+ MEM_freeN(p);
+ return (1);
+ }
+ p1 = p;
+ p = p->next;
+ }
+ return (0);
+}
+
+int IMB_imginfo_change_field(struct ImBuf *img, const char *key, const char *field)
+{
+ ImgInfo *p;
+
+ if (!img)
+ return (0);
+
+ if (!img->img_info)
+ return (IMB_imginfo_add_field (img, key, field));
+
+ p = img->img_info;
+ while (p) {
+ if (!strcmp (key, p->key)) {
+ MEM_freeN (p->value);
+ p->value = BLI_strdup (field);
+ return (1);
+ }
+ p = p->next;
+ }
+
+ return (IMB_imginfo_add_field (img, key, field));
+}
diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c
index cd90adda27a..eab07c19265 100644
--- a/source/blender/imbuf/intern/jpeg.c
+++ b/source/blender/imbuf/intern/jpeg.c
@@ -41,6 +41,7 @@
#include "imbuf_patch.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
+#include "IMB_imginfo.h"
#include "IMB_jpeg.h"
#include "jpeglib.h"
@@ -244,11 +245,14 @@ static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct * cinfo, int f
int x, y, depth, r, g, b, k;
struct ImBuf * ibuf = 0;
uchar * rect;
+ jpeg_saved_marker_ptr marker;
+ char *str, *key, *value;
/* install own app1 handler */
ibuf_ftype = 0;
jpeg_set_marker_processor(cinfo, 0xe1, handle_app1);
cinfo->dct_method = JDCT_FLOAT;
+ jpeg_save_markers(cinfo, JPEG_COM, 0xffff);
if (jpeg_read_header(cinfo, FALSE) == JPEG_HEADER_OK) {
x = cinfo->image_width;
@@ -335,6 +339,64 @@ static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct * cinfo, int f
}
}
}
+
+ marker= cinfo->marker_list;
+ while(marker) {
+ if(marker->marker != JPEG_COM)
+ goto next_stamp_marker;
+
+ /*
+ * Because JPEG format don't support the
+ * pair "key/value" like PNG, we store the
+ * stampinfo in a single "encode" string:
+ * "Blender:key:value"
+ *
+ * That is why we need split it to the
+ * common key/value here.
+ */
+ if(strncmp((char *) marker->data, "Blender", 7)) {
+ /*
+ * Maybe the file have text that
+ * we don't know "what it's", in that
+ * case we keep the text (with a
+ * key "None").
+ * This is only for don't "lose"
+ * the information when we write
+ * it back to disk.
+ */
+ IMB_imginfo_add_field(ibuf, "None", (char *) marker->data);
+ ibuf->flags |= IB_imginfo;
+ goto next_stamp_marker;
+ }
+
+ str = BLI_strdup ((char *) marker->data);
+ key = strchr (str, ':');
+ /*
+ * A little paranoid, but the file maybe
+ * is broken... and a "extra" check is better
+ * that a segfaul ;)
+ */
+ if (!key) {
+ MEM_freeN(str);
+ goto next_stamp_marker;
+ }
+
+ key++;
+ value = strchr (key, ':');
+ if (!value) {
+ MEM_freeN(str);
+ goto next_stamp_marker;
+ }
+
+ *value = '\0'; /* need finish the key string */
+ value++;
+ IMB_imginfo_add_field(ibuf, key, value);
+ ibuf->flags |= IB_imginfo;
+ MEM_freeN(str);
+next_stamp_marker:
+ marker= marker->next;
+ }
+
jpeg_finish_decompress(cinfo);
}
@@ -345,7 +407,7 @@ static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct * cinfo, int f
return(ibuf);
}
-ImBuf * imb_ibJpegImageFromFilename (char * filename, int flags)
+ImBuf * imb_ibJpegImageFromFilename (const char * filename, int flags)
{
struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
struct jpeg_error_mgr jerr;
@@ -391,7 +453,8 @@ static void write_jpeg(struct jpeg_compress_struct * cinfo, struct ImBuf * ibuf)
uchar * rect;
int x, y;
char neogeo[128];
-
+ ImgInfo *iptr;
+ char *text;
jpeg_start_compress(cinfo, TRUE);
@@ -401,6 +464,33 @@ static void write_jpeg(struct jpeg_compress_struct * cinfo, struct ImBuf * ibuf)
memcpy(neogeo + 6, &ibuf_ftype, 4);
jpeg_write_marker(cinfo, 0xe1, (JOCTET*) neogeo, 10);
+ if(ibuf->img_info) {
+ /* key + max value + "Blender" */
+ text= MEM_mallocN(530, "stamp info read");
+ iptr= ibuf->img_info;
+ while(iptr) {
+ if (!strcmp (iptr->key, "None")) {
+ jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) iptr->value, strlen (iptr->value) + 1);
+ goto next_stamp_info;
+ }
+
+ /*
+ * The JPEG format don't support a pair "key/value"
+ * like PNG, so we "encode" the stamp in a
+ * single string:
+ * "Blender:key:value"
+ *
+ * The first "Blender" is a simple identify to help
+ * in the read process.
+ */
+ sprintf (text, "Blender:%s:%s", iptr->key, iptr->value);
+ jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *) text, strlen (text)+1);
+next_stamp_info:
+ iptr = iptr->next;
+ }
+ MEM_freeN(text);
+ }
+
row_pointer[0] =
mallocstruct(JSAMPLE,
cinfo->input_components *
diff --git a/source/blender/imbuf/intern/md5.c b/source/blender/imbuf/intern/md5.c
new file mode 100644
index 00000000000..a3165467b53
--- /dev/null
+++ b/source/blender/imbuf/intern/md5.c
@@ -0,0 +1,361 @@
+/* md5.c - Functions to compute MD5 message digest of files or memory blocks
+ according to the definition of MD5 in RFC 1321 from April 1992.
+ Copyright (C) 1995 Software Foundation, Inc.
+
+ 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+# include <stdlib.h>
+# include <string.h>
+
+#include "md5.h"
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n) \
+ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+ 64-byte boundary. (RFC 1321, 3.1: Step 1) */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
+
+
+/* Initialize structure containing state of computation.
+ (RFC 1321, 3.3: Step 3) */
+void
+md5_init_ctx (ctx)
+ struct md5_ctx *ctx;
+{
+ ctx->A = 0x67452301;
+ ctx->B = 0xefcdab89;
+ ctx->C = 0x98badcfe;
+ ctx->D = 0x10325476;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF. The result must
+ be in little endian byte order. */
+void *
+md5_read_ctx (ctx, resbuf)
+ const struct md5_ctx *ctx;
+ void *resbuf;
+{
+ ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+ ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+ ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+ ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
+
+ return resbuf;
+}
+
+/* Compute MD5 message digest for bytes read from STREAM. The
+ resulting message digest number will be written into the 16 bytes
+ beginning at RESBLOCK. */
+int
+md5_stream (stream, resblock)
+ FILE *stream;
+ void *resblock;
+{
+ /* Important: BLOCKSIZE must be a multiple of 64. */
+#define BLOCKSIZE 4096
+ struct md5_ctx ctx;
+ md5_uint32 len[2];
+ char buffer[BLOCKSIZE + 72];
+ size_t pad, sum;
+
+ /* Initialize the computation context. */
+ md5_init_ctx (&ctx);
+
+ len[0] = 0;
+ len[1] = 0;
+
+ /* Iterate over full file contents. */
+ while (1)
+ {
+ /* We read the file in blocks of BLOCKSIZE bytes. One call of the
+ computation function processes the whole buffer so that with the
+ next round of the loop another block can be read. */
+ size_t n;
+ sum = 0;
+
+ /* Read block. Take care for partial reads. */
+ do
+ {
+ n = fread (buffer, 1, BLOCKSIZE - sum, stream);
+
+ sum += n;
+ }
+ while (sum < BLOCKSIZE && n != 0);
+ if (n == 0 && ferror (stream))
+ return 1;
+
+ /* RFC 1321 specifies the possible length of the file up to 2^64 bits.
+ Here we only compute the number of bytes. Do a double word
+ increment. */
+ len[0] += sum;
+ if (len[0] < sum)
+ ++len[1];
+
+ /* If end of file is reached, end the loop. */
+ if (n == 0)
+ break;
+
+ /* Process buffer with BLOCKSIZE bytes. Note that
+ BLOCKSIZE % 64 == 0
+ */
+ md5_process_block (buffer, BLOCKSIZE, &ctx);
+ }
+
+ /* We can copy 64 byte because the buffer is always big enough. FILLBUF
+ contains the needed bits. */
+ memcpy (&buffer[sum], fillbuf, 64);
+
+ /* Compute amount of padding bytes needed. Alignment is done to
+ (N + PAD) % 64 == 56
+ There is always at least one byte padded. I.e. even the alignment
+ is correctly aligned 64 padding bytes are added. */
+ pad = sum & 63;
+ pad = pad >= 56 ? 64 + 56 - pad : 56 - pad;
+
+ /* Put the 64-bit file length in *bits* at the end of the buffer. */
+ *(md5_uint32 *) &buffer[sum + pad] = SWAP (len[0] << 3);
+ *(md5_uint32 *) &buffer[sum + pad + 4] = SWAP ((len[1] << 3)
+ | (len[0] >> 29));
+
+ /* Process last bytes. */
+ md5_process_block (buffer, sum + pad + 8, &ctx);
+
+ /* Construct result in desired memory. */
+ md5_read_ctx (&ctx, resblock);
+ return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
+ result is always in little endian byte order, so that a byte-wise
+ output yields to the wanted ASCII representation of the message
+ digest. */
+void *
+md5_buffer (buffer, len, resblock)
+ const char *buffer;
+ size_t len;
+ void *resblock;
+{
+ struct md5_ctx ctx;
+ char restbuf[64 + 72];
+ size_t blocks = len & ~63;
+ size_t pad, rest;
+
+ /* Initialize the computation context. */
+ md5_init_ctx (&ctx);
+
+ /* Process whole buffer but last len % 64 bytes. */
+ md5_process_block (buffer, blocks, &ctx);
+
+ /* REST bytes are not processed yet. */
+ rest = len - blocks;
+ /* Copy to own buffer. */
+ memcpy (restbuf, &buffer[blocks], rest);
+ /* Append needed fill bytes at end of buffer. We can copy 64 byte
+ because the buffer is always big enough. */
+ memcpy (&restbuf[rest], fillbuf, 64);
+
+ /* PAD bytes are used for padding to correct alignment. Note that
+ always at least one byte is padded. */
+ pad = rest >= 56 ? 64 + 56 - rest : 56 - rest;
+
+ /* Put length of buffer in *bits* in last eight bytes. */
+ *(md5_uint32 *) &restbuf[rest + pad] = (md5_uint32) SWAP (len << 3);
+ *(md5_uint32 *) &restbuf[rest + pad + 4] = (md5_uint32) SWAP (len >> 29);
+
+ /* Process last bytes. */
+ md5_process_block (restbuf, rest + pad + 8, &ctx);
+
+ /* Put result in desired memory area. */
+ return md5_read_ctx (&ctx, resblock);
+}
+
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+ and defined in the RFC 1321. The first function is a little bit optimized
+ (as found in Colin Plumbs public domain implementation). */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+ It is assumed that LEN % 64 == 0. */
+
+void
+md5_process_block (buffer, len, ctx)
+ const void *buffer;
+ size_t len;
+ struct md5_ctx *ctx;
+{
+ md5_uint32 correct_words[16];
+ const md5_uint32 *words = buffer;
+ size_t nwords = len / sizeof (md5_uint32);
+ const md5_uint32 *endp = words + nwords;
+ md5_uint32 A = ctx->A;
+ md5_uint32 B = ctx->B;
+ md5_uint32 C = ctx->C;
+ md5_uint32 D = ctx->D;
+
+ /* Process all bytes in the buffer with 64 bytes in each round of
+ the loop. */
+ while (words < endp)
+ {
+ md5_uint32 *cwp = correct_words;
+ md5_uint32 A_save = A;
+ md5_uint32 B_save = B;
+ md5_uint32 C_save = C;
+ md5_uint32 D_save = D;
+
+ /* First round: using the given function, the context and a constant
+ the next context is computed. Because the algorithms processing
+ unit is a 32-bit word and it is determined to work on words in
+ little endian byte order we perhaps have to change the byte order
+ before the computation. To reduce the work for the next steps
+ we store the swapped words in the array CORRECT_WORDS. */
+
+#define OP(a, b, c, d, s, T) \
+ do \
+ { \
+ a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
+ ++words; \
+ CYCLIC (a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* It is unfortunate that C does not provide an operator for
+ cyclic rotation. Hope the C compiler is smart enough. */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+ /* Before we start, one word to the strange constants.
+ They are defined in RFC 1321 as
+
+ T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+ */
+
+ /* Round 1. */
+ OP (A, B, C, D, 7, 0xd76aa478);
+ OP (D, A, B, C, 12, 0xe8c7b756);
+ OP (C, D, A, B, 17, 0x242070db);
+ OP (B, C, D, A, 22, 0xc1bdceee);
+ OP (A, B, C, D, 7, 0xf57c0faf);
+ OP (D, A, B, C, 12, 0x4787c62a);
+ OP (C, D, A, B, 17, 0xa8304613);
+ OP (B, C, D, A, 22, 0xfd469501);
+ OP (A, B, C, D, 7, 0x698098d8);
+ OP (D, A, B, C, 12, 0x8b44f7af);
+ OP (C, D, A, B, 17, 0xffff5bb1);
+ OP (B, C, D, A, 22, 0x895cd7be);
+ OP (A, B, C, D, 7, 0x6b901122);
+ OP (D, A, B, C, 12, 0xfd987193);
+ OP (C, D, A, B, 17, 0xa679438e);
+ OP (B, C, D, A, 22, 0x49b40821);
+
+ /* For the second to fourth round we have the possibly swapped words
+ in CORRECT_WORDS. Redefine the macro to take an additional first
+ argument specifying the function to use. */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T) \
+ do \
+ { \
+ a += f (b, c, d) + correct_words[k] + T; \
+ CYCLIC (a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* Round 2. */
+ OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
+ OP (FG, D, A, B, C, 6, 9, 0xc040b340);
+ OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+ OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
+ OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
+ OP (FG, D, A, B, C, 10, 9, 0x02441453);
+ OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+ OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
+ OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
+ OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
+ OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
+ OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
+ OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
+ OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
+ OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
+ OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+ /* Round 3. */
+ OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
+ OP (FH, D, A, B, C, 8, 11, 0x8771f681);
+ OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+ OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+ OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
+ OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
+ OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
+ OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+ OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
+ OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
+ OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
+ OP (FH, B, C, D, A, 6, 23, 0x04881d05);
+ OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
+ OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+ OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+ OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
+
+ /* Round 4. */
+ OP (FI, A, B, C, D, 0, 6, 0xf4292244);
+ OP (FI, D, A, B, C, 7, 10, 0x432aff97);
+ OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+ OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
+ OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
+ OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
+ OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+ OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
+ OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
+ OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+ OP (FI, C, D, A, B, 6, 15, 0xa3014314);
+ OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+ OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
+ OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+ OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
+ OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
+
+ /* Add the starting values of the context. */
+ A += A_save;
+ B += B_save;
+ C += C_save;
+ D += D_save;
+ }
+
+ /* Put checksum in context given as argument. */
+ ctx->A = A;
+ ctx->B = B;
+ ctx->C = C;
+ ctx->D = D;
+}
+
diff --git a/source/blender/imbuf/intern/md5.h b/source/blender/imbuf/intern/md5.h
new file mode 100644
index 00000000000..8b0d946430e
--- /dev/null
+++ b/source/blender/imbuf/intern/md5.h
@@ -0,0 +1,116 @@
+/* md5.h - Declaration of functions and data types used for MD5 sum
+ computing library functions.
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+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, 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. */
+
+#ifndef _MD5_H
+#define _MD5_H
+
+#include <stdio.h>
+
+#if defined HAVE_LIMITS_H || _LIBC
+# include <limits.h>
+#endif
+
+/* The following contortions are an attempt to use the C preprocessor
+ to determine an unsigned integral type that is 32 bits wide. An
+ alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+ doing that would require that the configure script compile and *run*
+ the resulting executable. Locally running cross-compiled executables
+ is usually not possible. */
+
+#if defined __STDC__ && __STDC__
+# define UINT_MAX_32_BITS 4294967295U
+#else
+# define UINT_MAX_32_BITS 0xFFFFFFFF
+#endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+ This should be valid for all systems GNU cares about because
+ that doesn't include 16-bit systems, and only modern systems
+ (that certainly have <limits.h>) have 64+-bit integral types. */
+
+#ifndef UINT_MAX
+# define UINT_MAX UINT_MAX_32_BITS
+#endif
+
+#if UINT_MAX == UINT_MAX_32_BITS
+ typedef unsigned int md5_uint32;
+#else
+# if USHRT_MAX == UINT_MAX_32_BITS
+ typedef unsigned short md5_uint32;
+# else
+# if ULONG_MAX == UINT_MAX_32_BITS
+ typedef unsigned long md5_uint32;
+# else
+ /* The following line is intended to evoke an error.
+ Using #error is not portable enough. */
+ "Cannot determine unsigned 32-bit data type."
+# endif
+# endif
+#endif
+
+#undef __P
+#if defined (__STDC__) && __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+
+/* Structure to save state of computation between the single steps. */
+struct md5_ctx
+{
+ md5_uint32 A;
+ md5_uint32 B;
+ md5_uint32 C;
+ md5_uint32 D;
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+ (RFC 1321, 3.3: Step 3) */
+void md5_init_ctx __P ((struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+ initialzation function update the context for the next LEN bytes
+ starting at BUFFER.
+ It is necessary that LEN is a multiple of 64!!! */
+void md5_process_block __P ((const void *buffer, size_t len,
+ struct md5_ctx *ctx));
+
+/* Put result from CTX in first 16 bytes following RESBUF. The result is
+ always in little endian byte order, so that a byte-wise output yields
+ to the wanted ASCII representation of the message digest. */
+void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
+
+
+/* Compute MD5 message digest for bytes read from STREAM. The
+ resulting message digest number will be written into the 16 bytes
+ beginning at RESBLOCK. */
+int md5_stream __P ((FILE *stream, void *resblock));
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
+ result is always in little endian byte order, so that a byte-wise
+ output yields to the wanted ASCII representation of the message
+ digest. */
+void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
+
+#endif
+
diff --git a/source/blender/imbuf/intern/openexr/Makefile b/source/blender/imbuf/intern/openexr/Makefile
index 65b9a058e01..a3b79c951dd 100644
--- a/source/blender/imbuf/intern/openexr/Makefile
+++ b/source/blender/imbuf/intern/openexr/Makefile
@@ -36,10 +36,6 @@ DIR = $(OCGDIR)/blender/imbuf/openexr
include nan_compile.mk
-ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows"))
- CFLAGS += -funsigned-char
-endif
-
CFLAGS += $(LEVEL_1_C_WARNINGS)
CPPFLAGS += -I../../../makesdna
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 3cbada812b9..8f94c2cec3d 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -362,6 +362,7 @@ typedef struct ExrHandle {
OutputFile *ofile;
int tilex, tiley;
int width, height;
+ int mipmap;
ListBase channels; /* flattened out, ExrChannel */
ListBase layers; /* hierarchical, pointing in end to ExrChannel */
@@ -450,7 +451,7 @@ void IMB_exr_begin_write(void *handle, char *filename, int width, int height, in
data->ofile = new OutputFile(filename, header);
}
-void IMB_exrtile_begin_write(void *handle, char *filename, int width, int height, int tilex, int tiley)
+void IMB_exrtile_begin_write(void *handle, char *filename, int mipmap, int width, int height, int tilex, int tiley)
{
ExrHandle *data= (ExrHandle *)handle;
Header header (width, height);
@@ -460,11 +461,12 @@ void IMB_exrtile_begin_write(void *handle, char *filename, int width, int height
data->tiley= tiley;
data->width= width;
data->height= height;
+ data->mipmap= mipmap;
for(echan= (ExrChannel *)data->channels.first; echan; echan= echan->next)
header.channels().insert (echan->name, Channel (FLOAT));
- header.setTileDescription (TileDescription (tilex, tiley, ONE_LEVEL));
+ header.setTileDescription (TileDescription (tilex, tiley, (mipmap)? MIPMAP_LEVELS: ONE_LEVEL));
header.lineOrder() = RANDOM_Y;
header.compression() = RLE_COMPRESSION;
@@ -478,7 +480,7 @@ int IMB_exr_begin_read(void *handle, char *filename, int *width, int *height)
{
ExrHandle *data= (ExrHandle *)handle;
- if(BLI_exists(filename)) {
+ if(BLI_exists(filename) && BLI_filepathsize(filename)>32) { /* 32 is arbitrary, but zero length files crashes exr */
data->ifile = new InputFile(filename);
if(data->ifile) {
Box2i dw = data->ifile->header().dataWindow();
@@ -533,7 +535,7 @@ void IMB_exrtile_clear_channels(void *handle)
BLI_freelistN(&data->channels);
}
-void IMB_exrtile_write_channels(void *handle, int partx, int party)
+void IMB_exrtile_write_channels(void *handle, int partx, int party, int level)
{
ExrHandle *data= (ExrHandle *)handle;
FrameBuffer frameBuffer;
@@ -547,9 +549,14 @@ void IMB_exrtile_write_channels(void *handle, int partx, int party)
}
data->tofile->setFrameBuffer (frameBuffer);
- // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley);
- data->tofile->writeTile (partx/data->tilex, party/data->tiley);
-
+
+ try {
+ // printf("write tile %d %d\n", partx/data->tilex, party/data->tiley);
+ data->tofile->writeTile (partx/data->tilex, party/data->tiley, level);
+ }
+ catch (const std::exception &exc) {
+ std::cerr << "OpenEXR-writeTile: ERROR: " << exc.what() << std::endl;
+ }
}
void IMB_exr_write_channels(void *handle)
@@ -615,7 +622,6 @@ void IMB_exr_multilayer_convert(void *handle, void *base,
void IMB_exr_close(void *handle)
{
ExrHandle *data= (ExrHandle *)handle;
- ExrChannel *echan;
ExrLayer *lay;
ExrPass *pass;
@@ -778,28 +784,28 @@ static ExrHandle *imb_exr_begin_read_mem(InputFile *file, int width, int height)
/* we can have RGB(A), XYZ(W), UVA */
if(pass->totchan==3 || pass->totchan==4) {
if(pass->chan[0]->chan_id=='B' || pass->chan[1]->chan_id=='B' || pass->chan[2]->chan_id=='B') {
- lookup['R']= 0;
- lookup['G']= 1;
- lookup['B']= 2;
- lookup['A']= 3;
+ lookup[(unsigned int)'R']= 0;
+ lookup[(unsigned int)'G']= 1;
+ lookup[(unsigned int)'B']= 2;
+ lookup[(unsigned int)'A']= 3;
}
else if(pass->chan[0]->chan_id=='Y' || pass->chan[1]->chan_id=='Y' || pass->chan[2]->chan_id=='Y') {
- lookup['X']= 0;
- lookup['Y']= 1;
- lookup['Z']= 2;
- lookup['W']= 3;
+ lookup[(unsigned int)'X']= 0;
+ lookup[(unsigned int)'Y']= 1;
+ lookup[(unsigned int)'Z']= 2;
+ lookup[(unsigned int)'W']= 3;
}
else {
- lookup['U']= 0;
- lookup['V']= 1;
- lookup['A']= 2;
+ lookup[(unsigned int)'U']= 0;
+ lookup[(unsigned int)'V']= 1;
+ lookup[(unsigned int)'A']= 2;
}
for(a=0; a<pass->totchan; a++) {
echan= pass->chan[a];
- echan->rect= pass->rect + lookup[echan->chan_id];
+ echan->rect= pass->rect + lookup[(unsigned int)echan->chan_id];
echan->xstride= pass->totchan;
echan->ystride= width*pass->totchan;
- pass->chan_id[ lookup[echan->chan_id] ]= echan->chan_id;
+ pass->chan_id[ (unsigned int)lookup[(unsigned int)echan->chan_id] ]= echan->chan_id;
}
}
else { /* unknown */
@@ -831,6 +837,7 @@ typedef struct RGBA
} RGBA;
+#if 0
static void exr_print_filecontents(InputFile *file)
{
const ChannelList &channels = file->header().channels();
@@ -841,6 +848,7 @@ static void exr_print_filecontents(InputFile *file)
printf("OpenEXR-load: Found channel %s of type %d\n", i.name(), channel.type);
}
}
+#endif
static int exr_has_zbuffer(InputFile *file)
{
@@ -848,7 +856,6 @@ static int exr_has_zbuffer(InputFile *file)
for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i)
{
- const Channel &channel = i.channel();
if(strcmp("Z", i.name())==0)
return 1;
}
diff --git a/source/blender/imbuf/intern/openexr/openexr_multi.h b/source/blender/imbuf/intern/openexr/openexr_multi.h
index ca4f7405f44..be4d1314a80 100644
--- a/source/blender/imbuf/intern/openexr/openexr_multi.h
+++ b/source/blender/imbuf/intern/openexr/openexr_multi.h
@@ -46,13 +46,13 @@ void IMB_exr_add_channel (void *handle, const char *layname, const char *passn
int IMB_exr_begin_read (void *handle, char *filename, int *width, int *height);
void IMB_exr_begin_write (void *handle, char *filename, int width, int height, int compress);
-void IMB_exrtile_begin_write (void *handle, char *filename, int width, int height, int tilex, int tiley);
+void IMB_exrtile_begin_write (void *handle, char *filename, int mipmap, int width, int height, int tilex, int tiley);
void IMB_exr_set_channel (void *handle, char *layname, char *passname, int xstride, int ystride, float *rect);
void IMB_exr_read_channels (void *handle);
void IMB_exr_write_channels (void *handle);
-void IMB_exrtile_write_channels (void *handle, int partx, int party);
+void IMB_exrtile_write_channels (void *handle, int partx, int party, int level);
void IMB_exrtile_clear_channels (void *handle);
void IMB_exr_multilayer_convert (void *handle, void *base,
@@ -71,13 +71,13 @@ void IMB_exr_add_channel (void *handle, const char *layname, const char *chann
int IMB_exr_begin_read (void *handle, char *filename, int *width, int *height) {return 0;}
void IMB_exr_begin_write (void *handle, char *filename, int width, int height, int compress) {}
-void IMB_exrtile_begin_write (void *handle, char *filename, int width, int height, int tilex, int tiley) {}
+void IMB_exrtile_begin_write (void *handle, char *filename, int mipmap, int width, int height, int tilex, int tiley) {}
void IMB_exr_set_channel (void *handle, char *layname, char *channame, int xstride, int ystride, float *rect) {}
void IMB_exr_read_channels (void *handle) {}
void IMB_exr_write_channels (void *handle) {}
-void IMB_exrtile_write_channels (void *handle, int partx, int party) {}
+void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) {}
void IMB_exrtile_clear_channels (void *handle) {}
void IMB_exr_multilayer_convert (void *handle, void *base,
diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c
index 46c5232a61a..c77ff7ea56f 100644
--- a/source/blender/imbuf/intern/png.c
+++ b/source/blender/imbuf/intern/png.c
@@ -43,6 +43,7 @@
#include "IMB_allocimbuf.h"
#include "IMB_cmap.h"
+#include "IMB_imginfo.h"
#include "IMB_png.h"
typedef struct PNGReadStruct {
@@ -100,6 +101,7 @@ short imb_savepng(struct ImBuf *ibuf, char *name, int flags)
{
png_structp png_ptr;
png_infop info_ptr;
+
unsigned char *pixels = 0;
unsigned char *from, *to;
png_bytepp row_pointers = 0;
@@ -219,6 +221,34 @@ short imb_savepng(struct ImBuf *ibuf, char *name, int flags)
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
+ /* image text info */
+ if (ibuf->img_info) {
+ png_text* imginfo;
+ ImgInfo* iptr;
+ int num_text = 0;
+ iptr = ibuf->img_info;
+ while (iptr) {
+ num_text++;
+ iptr = iptr->next;
+ }
+
+ imginfo = MEM_callocN(num_text*sizeof(png_text), "png_imginfo");
+ iptr = ibuf->img_info;
+ num_text = 0;
+ while (iptr) {
+
+ imginfo[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
+ imginfo[num_text].key = iptr->key;
+ imginfo[num_text].text = iptr->value;
+ num_text++;
+ iptr = iptr->next;
+ }
+
+ png_set_text(png_ptr, info_ptr, imginfo, num_text);
+ MEM_freeN(imginfo);
+
+ }
+
// write the file header information
png_write_info(png_ptr, info_ptr);
@@ -409,6 +439,15 @@ struct ImBuf *imb_loadpng(unsigned char *mem, int size, int flags)
break;
}
+ if (flags & IB_imginfo) {
+ png_text* text_chunks;
+ int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL);
+ for(i = 0; i < count; i++) {
+ IMB_imginfo_add_field(ibuf, text_chunks[i].key, text_chunks[i].text);
+ ibuf->flags |= IB_imginfo;
+ }
+ }
+
png_read_end(png_ptr, info_ptr);
}
diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c
index 75be790a4cc..3cb9ca79ffc 100644
--- a/source/blender/imbuf/intern/radiance_hdr.c
+++ b/source/blender/imbuf/intern/radiance_hdr.c
@@ -161,8 +161,10 @@ static void FLOAT2RGBE(fCOLOR fcol, RGBE rgbe)
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;
+ // For recognition, Blender only loads first 32 bytes, so use #?RADIANCE id instead
+ // update: actually, the 'RADIANCE' part is just an optional program name, the magic word is really only the '#?' part
+ //if (strstr((char*)buf, "#?RADIANCE")) return 1;
+ if (strstr((char*)buf, "#?")) return 1;
// if (strstr((char*)buf, "32-bit_rle_rgbe")) return 1;
return 0;
}
@@ -176,7 +178,6 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags)
int found=0;
int width=0, height=0;
int x, y;
- int ir, ig, ib;
unsigned char* ptr;
unsigned char* rect;
char oriY[80], oriX[80];
@@ -225,18 +226,14 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags)
*rect_float++ = fcol[GRN];
*rect_float++ = fcol[BLU];
*rect_float++ = 1.0f;
-
/* Also old oldstyle for the rest of blender which is not using floats yet */
-/* very weird mapping! (ton) */
- 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));
+ // e: changed to simpler tonemapping, previous code was rather slow (is this actually still relevant at all?)
+ fcol[RED] = fcol[RED]/(1.f + fcol[RED]);
+ fcol[GRN] = fcol[GRN]/(1.f + fcol[GRN]);
+ fcol[BLU] = fcol[BLU]/(1.f + fcol[BLU]);
+ *rect++ = (unsigned char)((fcol[RED] < 0.f) ? 0 : ((fcol[RED] > 1.f) ? 255 : (255.f*fcol[RED])));
+ *rect++ = (unsigned char)((fcol[GRN] < 0.f) ? 0 : ((fcol[GRN] > 1.f) ? 255 : (255.f*fcol[GRN])));
+ *rect++ = (unsigned char)((fcol[BLU] < 0.f) ? 0 : ((fcol[BLU] > 1.f) ? 255 : (255.f*fcol[BLU])));
*rect++ = 255;
}
}
@@ -328,10 +325,10 @@ static void writeHeader(FILE *file, int width, int height)
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);
+ fprintf(file, "FORMAT=32-bit_rle_rgbe");
+ fputc(10, file);
fputc(10, file);
fprintf(file, "-Y %d +X %d", height, width);
fputc(10, file);
diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c
index bfa6200d23b..ec0f17a8c2b 100644
--- a/source/blender/imbuf/intern/readimage.c
+++ b/source/blender/imbuf/intern/readimage.c
@@ -59,6 +59,10 @@
#include "openexr/openexr_api.h"
#endif
+#ifdef WITH_DDS
+#include "dds/dds_api.h"
+#endif
+
#ifdef WITH_QUICKTIME
#if defined(_WIN32) || defined (__APPLE__)
#include "quicktime_import.h"
@@ -153,6 +157,11 @@ ImBuf *IMB_ibImageFromMemory(int *mem, int size, int flags) {
ibuf = imb_load_openexr((uchar *)mem, size, flags);
if (ibuf) return (ibuf);
#endif
+
+#ifdef WITH_DDS
+ ibuf = imb_load_dds((uchar *)mem, size, flags);
+ if (ibuf) return (ibuf);
+#endif
#ifdef WITH_QUICKTIME
#if defined(_WIN32) || defined (__APPLE__)
@@ -259,7 +268,7 @@ struct ImBuf *IMB_loadifffile(int file, int flags) {
}
-struct ImBuf *IMB_loadiffname(char *naam, int flags) {
+struct ImBuf *IMB_loadiffname(const char *naam, int flags) {
int file;
struct ImBuf *ibuf;
int buf[1];
diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c
index 85c5e07bb8e..5a907e71258 100644
--- a/source/blender/imbuf/intern/rectop.c
+++ b/source/blender/imbuf/intern/rectop.c
@@ -517,3 +517,87 @@ void IMB_rectfill(struct ImBuf *drect, float col[4])
}
}
+/* maybe we should use BKE_utildefines.h */
+#define FTOCHAR(val) (val<=0.0f ? 0: (val>=1.0f ? 255: (char)(255.99f*val)))
+#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c)
+#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
+
+void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, float *col, int x1, int y1, int x2, int y2)
+{
+ int i, j;
+ float a; /* alpha */
+ float ai; /* alpha inverted */
+ float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */
+ if ((!rect && !rectf) || (!col) || col[3]==0.0)
+ return;
+
+ /* sanity checks for coords */
+ CLAMP(x1, 0, width);
+ CLAMP(x2, 0, width);
+ CLAMP(y1, 0, height);
+ CLAMP(y2, 0, height);
+
+ if (x1>x2) SWAP(int,x1,x2);
+ if (y1>y2) SWAP(int,y1,y2);
+ if (x1==x2 || y1==y2) return;
+
+ a = col[3];
+ ai = 1-a;
+ aich = ai/255.0f;
+
+ if (rect) {
+ unsigned char *pixel;
+ unsigned char chr=0, chg=0, chb=0;
+ float fr=0, fg=0, fb=0;
+
+ if (a == 1.0) {
+ chr = FTOCHAR(col[0]);
+ chg = FTOCHAR(col[1]);
+ chb = FTOCHAR(col[2]);
+ } else {
+ fr = col[0]*a;
+ fg = col[1]*a;
+ fb = col[2]*a;
+ }
+ for (j = 0; j < y2-y1; j++) {
+ for (i = 0; i < x2-x1; i++) {
+ pixel = rect + 4 * (((y1 + j) * width) + (x1 + i));
+ if (pixel >= rect && pixel < rect+ (4 * (width * height))) {
+ if (a == 1.0) {
+ pixel[0] = chr;
+ pixel[1] = chg;
+ pixel[2] = chb;
+ } else {
+ pixel[0] = (char)((fr + ((float)pixel[0]*aich))*255.0f);
+ pixel[1] = (char)((fg + ((float)pixel[1]*aich))*255.0f);
+ pixel[2] = (char)((fb + ((float)pixel[2]*aich))*255.0f);
+ }
+ }
+ }
+ }
+ }
+
+ if (rectf) {
+ float *pixel;
+ for (j = 0; j < y2-y1; j++) {
+ for (i = 0; i < x2-x1; i++) {
+ pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i));
+ if (a == 1.0) {
+ pixel[0] = col[0];
+ pixel[1] = col[1];
+ pixel[2] = col[2];
+ } else {
+ pixel[0] = (col[0]*a) + (pixel[0]*ai);
+ pixel[1] = (col[1]*a) + (pixel[1]*ai);
+ pixel[2] = (col[2]*a) + (pixel[2]*ai);
+ }
+ }
+ }
+ }
+}
+
+void IMB_rectfill_area(struct ImBuf *ibuf, float *col, int x1, int y1, int x2, int y2)
+{
+ if (!ibuf) return;
+ buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, x1, y1, x2, y2);
+}
diff --git a/source/blender/imbuf/intern/rotate.c b/source/blender/imbuf/intern/rotate.c
index 13edfbf0a33..8f5fb39d956 100644
--- a/source/blender/imbuf/intern/rotate.c
+++ b/source/blender/imbuf/intern/rotate.c
@@ -43,46 +43,85 @@
void IMB_flipy(struct ImBuf * ibuf)
{
- short x, y;
- unsigned int *top, *bottom, do_float=0, *line;
- float *topf=NULL, *bottomf=NULL, *linef=NULL;
+ int x, y;
if (ibuf == NULL) return;
- if (ibuf->rect == NULL) return;
-
- if (ibuf->rect_float) do_float =1;
- x = ibuf->x;
- y = ibuf->y;
+ if (ibuf->rect) {
+ unsigned int *top, *bottom, *line;
+
+ x = ibuf->x;
+ y = ibuf->y;
- top = ibuf->rect;
- bottom = top + ((y-1) * x);
- line= MEM_mallocN(x*sizeof(int), "linebuf");
+ top = ibuf->rect;
+ bottom = top + ((y-1) * x);
+ line= MEM_mallocN(x*sizeof(int), "linebuf");
- if (do_float) {
+ y >>= 1;
+
+ for(;y>0;y--) {
+ memcpy(line, top, x*sizeof(int));
+ memcpy(top, bottom, x*sizeof(int));
+ memcpy(bottom, line, x*sizeof(int));
+ bottom -= x;
+ top+= x;
+ }
+
+ MEM_freeN(line);
+ }
+
+ if (ibuf->rect_float) {
+ float *topf=NULL, *bottomf=NULL, *linef=NULL;
+
+ x = ibuf->x;
+ y = ibuf->y;
+
topf= ibuf->rect_float;
bottomf = topf + 4*((y-1) * x);
linef= MEM_mallocN(4*x*sizeof(float), "linebuff");
- }
- y >>= 1;
-
- for(;y>0;y--) {
-
- memcpy(line, top, x*sizeof(int));
- memcpy(top, bottom, x*sizeof(int));
- memcpy(bottom, line, x*sizeof(int));
- bottom -= x;
- top+= x;
-
- if(do_float) {
+
+ y >>= 1;
+
+ for(;y>0;y--) {
memcpy(linef, topf, 4*x*sizeof(float));
memcpy(topf, bottomf, 4*x*sizeof(float));
memcpy(bottomf, linef, 4*x*sizeof(float));
bottomf -= 4*x;
topf+= 4*x;
}
+
+ MEM_freeN(linef);
+ }
+}
+
+void IMB_flipx(struct ImBuf * ibuf)
+{
+ short x, y, xr, xl, yi;
+ unsigned int px;
+ float px_f[4];
+
+ if (ibuf == NULL) return;
+
+ x = ibuf->x;
+ y = ibuf->y;
+
+ if (ibuf->rect) {
+ for(yi=y-1;yi>=0;yi--) {
+ for(xr=x-1, xl=0; xr>=xl; xr--, xl++) {
+ px = ibuf->rect[(x*yi)+xr];
+ ibuf->rect[(x*yi)+xr] = ibuf->rect[(x*yi)+xl];
+ ibuf->rect[(x*yi)+xl] = px;
+ }
+ }
}
- MEM_freeN(line);
- if(linef) MEM_freeN(linef);
+ if (ibuf->rect_float) {
+ for(yi=y-1;yi>=0;yi--) {
+ for(xr=x-1, xl=0; xr>=xl; xr--, xl++) {
+ memcpy(&px_f, &ibuf->rect_float[((x*yi)+xr)*4], 4*sizeof(float));
+ memcpy(&ibuf->rect_float[((x*yi)+xr)*4], &ibuf->rect_float[((x*yi)+xl)*4], 4*sizeof(float));
+ memcpy(&ibuf->rect_float[((x*yi)+xl)*4], &px_f, 4*sizeof(float));
+ }
+ }
+ }
}
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index cd933cb0767..80731213140 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -483,6 +483,468 @@ struct ImBuf *IMB_halflace(struct ImBuf *ibuf1)
return (ibuf2);
}
+/* q_scale_linear_interpolation helper functions */
+
+static void enlarge_picture_byte(
+ unsigned char* src, unsigned char* dst, int src_width,
+ int src_height, int dst_width, int dst_height)
+{
+ double ratiox = (double) (dst_width - 1.0)
+ / (double) (src_width - 1.001);
+ double ratioy = (double) (dst_height - 1.0)
+ / (double) (src_height - 1.001);
+ unsigned long x_src, dx_src, x_dst;
+ unsigned long y_src, dy_src, y_dst;
+
+ dx_src = 65536.0 / ratiox;
+ dy_src = 65536.0 / ratioy;
+
+ y_src = 0;
+ for (y_dst = 0; y_dst < dst_height; y_dst++) {
+ unsigned char* line1 = src + (y_src >> 16) * 4 * src_width;
+ unsigned char* line2 = line1 + 4 * src_width;
+ unsigned long weight1y = 65536 - (y_src & 0xffff);
+ unsigned long weight2y = 65536 - weight1y;
+
+ if ((y_src >> 16) == src_height - 1) {
+ line2 = line1;
+ }
+
+ x_src = 0;
+ for (x_dst = 0; x_dst < dst_width; x_dst++) {
+ unsigned long weight1x = 65536 - (x_src & 0xffff);
+ unsigned long weight2x = 65536 - weight1x;
+
+ unsigned long x = (x_src >> 16) * 4;
+
+ *dst++ = ((((line1[x] * weight1y) >> 16)
+ * weight1x) >> 16)
+ + ((((line2[x] * weight2y) >> 16)
+ * weight1x) >> 16)
+ + ((((line1[4 + x] * weight1y) >> 16)
+ * weight2x) >> 16)
+ + ((((line2[4 + x] * weight2y) >> 16)
+ * weight2x) >> 16);
+
+ *dst++ = ((((line1[x + 1] * weight1y) >> 16)
+ * weight1x) >> 16)
+ + ((((line2[x + 1] * weight2y) >> 16)
+ * weight1x) >> 16)
+ + ((((line1[4 + x + 1] * weight1y) >> 16)
+ * weight2x) >> 16)
+ + ((((line2[4 + x + 1] * weight2y) >> 16)
+ * weight2x) >> 16);
+
+ *dst++ = ((((line1[x + 2] * weight1y) >> 16)
+ * weight1x) >> 16)
+ + ((((line2[x + 2] * weight2y) >> 16)
+ * weight1x) >> 16)
+ + ((((line1[4 + x + 2] * weight1y) >> 16)
+ * weight2x) >> 16)
+ + ((((line2[4 + x + 2] * weight2y) >> 16)
+ * weight2x) >> 16);
+
+ *dst++ = ((((line1[x + 3] * weight1y) >> 16)
+ * weight1x) >> 16)
+ + ((((line2[x + 3] * weight2y) >> 16)
+ * weight1x) >> 16)
+ + ((((line1[4 + x + 3] * weight1y) >> 16)
+ * weight2x) >> 16)
+ + ((((line2[4 + x + 3] * weight2y) >> 16)
+ * weight2x) >> 16);
+
+ x_src += dx_src;
+ }
+ y_src += dy_src;
+ }
+}
+
+struct scale_outpix_byte {
+ unsigned long r;
+ unsigned long g;
+ unsigned long b;
+ unsigned long a;
+
+ unsigned long weight;
+};
+
+static void shrink_picture_byte(
+ unsigned char* src, unsigned char* dst, int src_width,
+ int src_height, int dst_width, int dst_height)
+{
+ double ratiox = (double) (dst_width) / (double) (src_width);
+ double ratioy = (double) (dst_height) / (double) (src_height);
+ unsigned long x_src, dx_dst, x_dst;
+ unsigned long y_src, dy_dst, y_dst;
+ long y_counter;
+ unsigned char * dst_begin = dst;
+
+ struct scale_outpix_byte * dst_line1 = NULL;
+ struct scale_outpix_byte * dst_line2 = NULL;
+
+ dst_line1 = (struct scale_outpix_byte*) MEM_callocN(
+ (dst_width + 1) * sizeof(struct scale_outpix_byte),
+ "shrink_picture_byte 1");
+ dst_line2 = (struct scale_outpix_byte*) MEM_callocN(
+ (dst_width + 1) * sizeof(struct scale_outpix_byte),
+ "shrink_picture_byte 2");
+
+ dx_dst = 65536.0 * ratiox;
+ dy_dst = 65536.0 * ratioy;
+
+ y_dst = 0;
+ y_counter = 65536;
+ for (y_src = 0; y_src < src_height; y_src++) {
+ unsigned char* line = src + y_src * 4 * src_width;
+ unsigned long weight1y = 65536 - (y_dst & 0xffff);
+ unsigned long weight2y = 65536 - weight1y;
+ x_dst = 0;
+ for (x_src = 0; x_src < src_width; x_src++) {
+ unsigned long weight1x = 65536 - (x_dst & 0xffff);
+ unsigned long weight2x = 65536 - weight1x;
+
+ unsigned long x = x_dst >> 16;
+
+ unsigned long w;
+
+ w = (weight1y * weight1x) >> 16;
+
+ dst_line1[x].r += (line[0] * w) >> 16;
+ dst_line1[x].g += (line[1] * w) >> 16;
+ dst_line1[x].b += (line[2] * w) >> 16;
+ dst_line1[x].a += (line[3] * w) >> 16;
+ dst_line1[x].weight += w;
+
+ w = (weight2y * weight1x) >> 16;
+
+ dst_line2[x].r += (line[0] * w) >> 16;
+ dst_line2[x].g += (line[1] * w) >> 16;
+ dst_line2[x].b += (line[2] * w) >> 16;
+ dst_line2[x].a += (line[3] * w) >> 16;
+ dst_line2[x].weight += w;
+
+ w = (weight1y * weight2x) >> 16;
+
+ dst_line1[x+1].r += (line[0] * w) >> 16;
+ dst_line1[x+1].g += (line[1] * w) >> 16;
+ dst_line1[x+1].b += (line[2] * w) >> 16;
+ dst_line1[x+1].a += (line[3] * w) >> 16;
+ dst_line1[x+1].weight += w;
+
+ w = (weight2y * weight2x) >> 16;
+
+ dst_line2[x+1].r += (line[0] * w) >> 16;
+ dst_line2[x+1].g += (line[1] * w) >> 16;
+ dst_line2[x+1].b += (line[2] * w) >> 16;
+ dst_line2[x+1].a += (line[3] * w) >> 16;
+ dst_line2[x+1].weight += w;
+
+ x_dst += dx_dst;
+ line += 4;
+ }
+
+ y_dst += dy_dst;
+ y_counter -= dy_dst;
+ if (y_counter < 0) {
+ unsigned long x;
+ struct scale_outpix_byte * temp;
+
+ y_counter += 65536;
+
+ for (x=0; x < dst_width; x++) {
+ unsigned long f = 0x80000000UL
+ / dst_line1[x].weight;
+ *dst++ = (dst_line1[x].r * f) >> 15;
+ *dst++ = (dst_line1[x].g * f) >> 15;
+ *dst++ = (dst_line1[x].b * f) >> 15;
+ *dst++ = (dst_line1[x].a * f) >> 15;
+ }
+ memset(dst_line1, 0, dst_width *
+ sizeof(struct scale_outpix_byte));
+ temp = dst_line1;
+ dst_line1 = dst_line2;
+ dst_line2 = temp;
+ }
+ }
+ if (dst - dst_begin < dst_width * dst_height * 4) {
+ unsigned long x;
+ for (x = 0; x < dst_width; x++) {
+ unsigned long f = 0x80000000UL / dst_line1[x].weight;
+ *dst++ = (dst_line1[x].r * f) >> 15;
+ *dst++ = (dst_line1[x].g * f) >> 15;
+ *dst++ = (dst_line1[x].b * f) >> 15;
+ *dst++ = (dst_line1[x].a * f) >> 15;
+ }
+ }
+ MEM_freeN(dst_line1);
+ MEM_freeN(dst_line2);
+}
+
+
+static void q_scale_byte(unsigned char* in, unsigned char* out, int in_width,
+ int in_height, int dst_width, int dst_height)
+{
+ if (dst_width > in_width && dst_height > in_height) {
+ enlarge_picture_byte(in, out, in_width, in_height,
+ dst_width, dst_height);
+ } else if (dst_width < in_width && dst_height < in_height) {
+ shrink_picture_byte(in, out, in_width, in_height,
+ dst_width, dst_height);
+ }
+}
+
+static void enlarge_picture_float(
+ float* src, float* dst, int src_width,
+ int src_height, int dst_width, int dst_height)
+{
+ double ratiox = (double) (dst_width - 1.0)
+ / (double) (src_width - 1.001);
+ double ratioy = (double) (dst_height - 1.0)
+ / (double) (src_height - 1.001);
+ unsigned long x_dst;
+ unsigned long y_dst;
+ double x_src, dx_src;
+ double y_src, dy_src;
+
+ dx_src = 1.0 / ratiox;
+ dy_src = 1.0 / ratioy;
+
+ y_src = 0;
+ for (y_dst = 0; y_dst < dst_height; y_dst++) {
+ float* line1 = src + ((int) y_src) * 4 * src_width;
+ float* line2 = line1 + 4 * src_width;
+ float weight1y = 1.0 - (y_src - (int) y_src);
+ float weight2y = 1.0 - weight1y;
+
+ if ((int) y_src == src_height - 1) {
+ line2 = line1;
+ }
+
+ x_src = 0;
+ for (x_dst = 0; x_dst < dst_width; x_dst++) {
+ float weight1x = 1.0 - (x_src - (int) x_src);
+ float weight2x = 1.0 - weight1x;
+
+ float w11 = weight1y * weight1x;
+ float w21 = weight2y * weight1x;
+ float w12 = weight1y * weight2x;
+ float w22 = weight2y * weight2x;
+
+ unsigned long x = ((int) x_src) * 4;
+
+ *dst++ = line1[x] * w11
+ + line2[x] * w21
+ + line1[4 + x] * w12
+ + line2[4 + x] * w22;
+
+ *dst++ = line1[x + 1] * w11
+ + line2[x + 1] * w21
+ + line1[4 + x + 1] * w12
+ + line2[4 + x + 1] * w22;
+
+ *dst++ = line1[x + 2] * w11
+ + line2[x + 2] * w21
+ + line1[4 + x + 2] * w12
+ + line2[4 + x + 2] * w22;
+
+ *dst++ = line1[x + 3] * w11
+ + line2[x + 3] * w21
+ + line1[4 + x + 3] * w12
+ + line2[4 + x + 3] * w22;
+
+ x_src += dx_src;
+ }
+ y_src += dy_src;
+ }
+}
+
+struct scale_outpix_float {
+ float r;
+ float g;
+ float b;
+ float a;
+
+ float weight;
+};
+
+static void shrink_picture_float(
+ float* src, float* dst, int src_width,
+ int src_height, int dst_width, int dst_height)
+{
+ double ratiox = (double) (dst_width) / (double) (src_width);
+ double ratioy = (double) (dst_height) / (double) (src_height);
+ unsigned long x_src;
+ unsigned long y_src;
+ float dx_dst, x_dst;
+ float dy_dst, y_dst;
+ float y_counter;
+ float * dst_begin = dst;
+
+ struct scale_outpix_float * dst_line1;
+ struct scale_outpix_float * dst_line2;
+
+ dst_line1 = (struct scale_outpix_float*) MEM_callocN(
+ (dst_width + 1) * sizeof(struct scale_outpix_float),
+ "shrink_picture_float 1");
+ dst_line2 = (struct scale_outpix_float*) MEM_callocN(
+ (dst_width + 1) * sizeof(struct scale_outpix_float),
+ "shrink_picture_float 2");
+
+ dx_dst = ratiox;
+ dy_dst = ratioy;
+
+ y_dst = 0;
+ y_counter = 1.0;
+ for (y_src = 0; y_src < src_height; y_src++) {
+ float* line = src + y_src * 4 * src_width;
+ unsigned long weight1y = 1.0 - (y_dst - (int) y_dst);
+ unsigned long weight2y = 1.0 - weight1y;
+ x_dst = 0;
+ for (x_src = 0; x_src < src_width; x_src++) {
+ unsigned long weight1x = 1.0 - (x_dst - (int) x_dst);
+ unsigned long weight2x = 1.0 - weight1x;
+
+ unsigned long x = (int) x_dst;
+
+ float w;
+
+ w = weight1y * weight1x;
+
+ dst_line1[x].r += line[0] * w;
+ dst_line1[x].g += line[1] * w;
+ dst_line1[x].b += line[2] * w;
+ dst_line1[x].a += line[3] * w;
+ dst_line1[x].weight += w;
+
+ w = weight2y * weight1x;
+
+ dst_line2[x].r += line[0] * w;
+ dst_line2[x].g += line[1] * w;
+ dst_line2[x].b += line[2] * w;
+ dst_line2[x].a += line[3] * w;
+ dst_line2[x].weight += w;
+
+ w = weight1y * weight2x;
+
+ dst_line1[x+1].r += line[0] * w;
+ dst_line1[x+1].g += line[1] * w;
+ dst_line1[x+1].b += line[2] * w;
+ dst_line1[x+1].a += line[3] * w;
+ dst_line1[x+1].weight += w;
+
+ w = weight2y * weight2x;
+
+ dst_line2[x+1].r += line[0] * w;
+ dst_line2[x+1].g += line[1] * w;
+ dst_line2[x+1].b += line[2] * w;
+ dst_line2[x+1].a += line[3] * w;
+ dst_line2[x+1].weight += w;
+
+ x_dst += dx_dst;
+ line += 4;
+ }
+
+ y_dst += dy_dst;
+ y_counter -= dy_dst;
+ if (y_counter < 0) {
+ unsigned long x;
+ struct scale_outpix_float * temp;
+
+ y_counter += 1.0;
+
+ for (x=0; x < dst_width; x++) {
+ float f = 1.0 / dst_line1[x].weight;
+ *dst++ = dst_line1[x].r * f;
+ *dst++ = dst_line1[x].g * f;
+ *dst++ = dst_line1[x].b * f;
+ *dst++ = dst_line1[x].a * f;
+ }
+ memset(dst_line1, 0, dst_width *
+ sizeof(struct scale_outpix_float));
+ temp = dst_line1;
+ dst_line1 = dst_line2;
+ dst_line2 = temp;
+ }
+ }
+ if (dst - dst_begin < dst_width * dst_height * 4) {
+ unsigned long x;
+ for (x = 0; x < dst_width; x++) {
+ float f = 1.0 / dst_line1[x].weight;
+ *dst++ = dst_line1[x].r * f;
+ *dst++ = dst_line1[x].g * f;
+ *dst++ = dst_line1[x].b * f;
+ *dst++ = dst_line1[x].a * f;
+ }
+ }
+ MEM_freeN(dst_line1);
+ MEM_freeN(dst_line2);
+}
+
+
+static void q_scale_float(float* in, float* out, int in_width,
+ int in_height, int dst_width, int dst_height)
+{
+ if (dst_width > in_width && dst_height > in_height) {
+ enlarge_picture_float(in, out, in_width, in_height,
+ dst_width, dst_height);
+ } else if (dst_width < in_width && dst_height < in_height) {
+ shrink_picture_float(in, out, in_width, in_height,
+ dst_width, dst_height);
+ }
+}
+
+/* q_scale_linear_interpolation (derived from ppmqscale, http://libdv.sf.net)
+
+ q stands for quick _and_ quality :)
+
+ only handles common cases when we either
+
+ scale both, x and y or
+ shrink both, x and y
+
+ but that is pretty fast:
+ * does only blit once instead of two passes like the old code
+ (fewer cache misses)
+ * uses fixed point integer arithmetic for byte buffers
+ * doesn't branch in tight loops
+
+ Should be comparable in speed to the ImBuf ..._fast functions at least
+ for byte-buffers.
+
+*/
+static int q_scale_linear_interpolation(
+ struct ImBuf *ibuf, int newx, int newy)
+{
+ if ((newx > ibuf->x && newy < ibuf->y) ||
+ (newx < ibuf->x && newy > ibuf->y)) {
+ return FALSE;
+ }
+
+ if (ibuf->rect) {
+ unsigned char * newrect =
+ MEM_mallocN(newx * newy * sizeof(int), "q_scale rect");
+ q_scale_byte((unsigned char *)ibuf->rect, newrect, ibuf->x, ibuf->y,
+ newx, newy);
+
+ imb_freerectImBuf(ibuf);
+ ibuf->mall |= IB_rect;
+ ibuf->rect = (unsigned int *) newrect;
+ }
+ if (ibuf->rect_float) {
+ float * newrect =
+ MEM_mallocN(newx * newy * 4 *sizeof(float),
+ "q_scale rectfloat");
+ q_scale_float(ibuf->rect_float, newrect, ibuf->x, ibuf->y,
+ newx, newy);
+ imb_freerectfloatImBuf(ibuf);
+ ibuf->mall |= IB_rectfloat;
+ ibuf->rect_float = newrect;
+ }
+ ibuf->x = newx;
+ ibuf->y = newy;
+
+ return TRUE;
+}
static struct ImBuf *scaledownx(struct ImBuf *ibuf, int newx)
{
@@ -1113,11 +1575,18 @@ struct ImBuf *IMB_scaleImBuf(struct ImBuf * ibuf, short newx, short newy)
{
if (ibuf==NULL) return (0);
if (ibuf->rect==NULL && ibuf->rect_float==NULL) return (ibuf);
+
+ if (newx == ibuf->x && newy == ibuf->y) { return ibuf; }
- // scaleup / scaledown functions below change ibuf->x and ibuf->y
- // so we first scale the Z-buffer (if any)
+ /* scaleup / scaledown functions below change ibuf->x and ibuf->y
+ so we first scale the Z-buffer (if any) */
scalefast_Z_ImBuf(ibuf, newx, newy);
+ /* try to scale common cases in a fast way */
+ if (q_scale_linear_interpolation(ibuf, newx, newy)) {
+ return ibuf;
+ }
+
if (newx < ibuf->x) if (newx) scaledownx(ibuf,newx);
if (newy < ibuf->y) if (newy) scaledowny(ibuf,newy);
if (newx > ibuf->x) if (newx) scaleupx(ibuf,newx);
diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c
new file mode 100644
index 00000000000..718b0537b48
--- /dev/null
+++ b/source/blender/imbuf/intern/thumbs.c
@@ -0,0 +1,459 @@
+/**
+ * $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 (C) 2007 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Andrea Weikert.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/* also defined in BKE_utildefines, repeated here to avoid dependency */
+#define FILE_MAX 240
+
+#include "BLI_blenlib.h"
+#include "MEM_guardedalloc.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "IMB_thumbs.h"
+#include "IMB_imginfo.h"
+
+
+#include "md5.h"
+
+#ifdef WIN32
+#include <windows.h> /* need to include windows.h so _WIN32_IE is defined */
+#ifndef _WIN32_IE
+#define _WIN32_IE 0x0400 /* minimal requirements for SHGetSpecialFolderPath on MINGW MSVC has this defined already */
+#endif
+#include <shlobj.h> /* for SHGetSpecialFolderPath, has to be done before BLI_winstuff because 'near' is disabled through BLI_windstuff */
+#include "BLI_winstuff.h"
+#include <process.h> /* getpid */
+#include <direct.h> /* chdir */
+#else
+#include <unistd.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#define URI_MAX FILE_MAX*3 + 8
+
+static int get_thumb_dir( char* dir , ThumbSize size)
+{
+#ifdef WIN32
+ /* yes, applications shouldn't store data there, but so does GIMP :)*/
+ SHGetSpecialFolderPath(0, dir, CSIDL_PROFILE, 0);
+#else
+ char* home = getenv("HOME");
+ if (!home) return 0;
+ BLI_strncpy(dir, home, FILE_MAX);
+#endif
+ switch(size) {
+ case THB_NORMAL:
+ strcat(dir, "/.thumbnails/normal/");
+ break;
+ case THB_LARGE:
+ strcat(dir, "/.thumbnails/large/");
+ break;
+ case THB_FAIL:
+ strcat(dir, "/.thumbnails/fail/blender/");
+ break;
+ default:
+ return 0; /* unknown size */
+ }
+ return 1;
+}
+
+/** ----- begin of adapted code from glib ---
+ * The following code is adapted from function g_escape_uri_string from the gnome glib
+ * Source: http://svn.gnome.org/viewcvs/glib/trunk/glib/gconvert.c?view=markup
+ * released under the Gnu General Public License.
+ */
+typedef enum {
+ UNSAFE_ALL = 0x1, /* Escape all unsafe characters */
+ UNSAFE_ALLOW_PLUS = 0x2, /* Allows '+' */
+ UNSAFE_PATH = 0x8, /* Allows '/', '&', '=', ':', '@', '+', '$' and ',' */
+ UNSAFE_HOST = 0x10, /* Allows '/' and ':' and '@' */
+ UNSAFE_SLASHES = 0x20 /* Allows all characters except for '/' and '%' */
+} UnsafeCharacterSet;
+
+static const unsigned char acceptable[96] = {
+ /* A table of the ASCII chars from space (32) to DEL (127) */
+ /* ! " # $ % & ' ( ) * + , - . / */
+ 0x00,0x3F,0x20,0x20,0x28,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x2A,0x28,0x3F,0x3F,0x1C,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x20,
+ /* @ A B C D E F G H I J K L M N O */
+ 0x38,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F,
+ /* ` a b c d e f g h i j k l m n o */
+ 0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+ /* p q r s t u v w x y z { | } ~ DEL */
+ 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20
+};
+
+static const char hex[17] = "0123456789abcdef";
+
+/* Note: This escape function works on file: URIs, but if you want to
+ * escape something else, please read RFC-2396 */
+void escape_uri_string (const char *string, char* escaped_string, int len,UnsafeCharacterSet mask)
+{
+#define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
+
+ const char *p;
+ char *q;
+ int c;
+ UnsafeCharacterSet use_mask;
+ use_mask = mask;
+
+ for (q = escaped_string, p = string; (*p != '\0') && len; p++) {
+ c = (unsigned char) *p;
+ len--;
+
+ if (!ACCEPTABLE (c)) {
+ *q++ = '%'; /* means hex coming */
+ *q++ = hex[c >> 4];
+ *q++ = hex[c & 15];
+ } else {
+ *q++ = *p;
+ }
+ }
+
+ *q = '\0';
+}
+
+void to_hex_char(char* hexbytes, const unsigned char* bytes, int len)
+{
+ const unsigned char *p;
+ char *q;
+
+ for (q = hexbytes, p = bytes; len; p++) {
+ const unsigned char c = (unsigned char) *p;
+ len--;
+ *q++ = hex[c >> 4];
+ *q++ = hex[c & 15];
+ }
+}
+
+/** ----- end of adapted code from glib --- */
+
+static int uri_from_filename( const char *dir, const char *file, char *uri )
+{
+ char orig_uri[URI_MAX];
+ const char* dirstart = dir;
+
+#ifdef WIN32
+ {
+ char vol[3];
+
+ BLI_strncpy(orig_uri, "file:///", FILE_MAX);
+ if (strlen(dir) < 2 && dir[1] != ':') {
+ /* not a correct absolute path */
+ return 0;
+ }
+ /* on windows, using always uppercase drive/volume letter in uri */
+ vol[0] = (unsigned char)toupper(dir[0]);
+ vol[1] = ':';
+ vol[2] = '\0';
+ strcat(orig_uri, vol);
+ dirstart += 2;
+ }
+#else
+ BLI_strncpy(orig_uri, "file://", FILE_MAX);
+#endif
+ strcat(orig_uri, dirstart);
+ strcat(orig_uri, file);
+ BLI_char_switch(orig_uri, '\\', '/');
+
+#ifdef WITH_ICONV
+ {
+ char uri_utf8[FILE_MAX*3+8];
+ escape_uri_string(orig_uri, uri_utf8, FILE_MAX*3+8, UNSAFE_PATH);
+ BLI_string_to_utf8(uri_utf8, uri, NULL);
+ }
+#else
+ escape_uri_string(orig_uri, uri, FILE_MAX*3+8, UNSAFE_PATH);
+#endif
+ return 1;
+}
+
+static void thumbname_from_uri(const char* uri, char* thumb)
+{
+ char hexdigest[33];
+ unsigned char digest[16];
+
+ md5_buffer( uri, strlen(uri), digest);
+ hexdigest[0] = '\0';
+ to_hex_char(hexdigest, digest, 16);
+ hexdigest[32] = '\0';
+ sprintf(thumb, "%s.png", hexdigest);
+}
+
+static int thumbpath_from_uri(const char* uri, char* path, ThumbSize size)
+{
+ char tmppath[FILE_MAX];
+ int rv = 0;
+
+ if (get_thumb_dir(tmppath, size)) {
+ char thumb[40];
+ thumbname_from_uri(uri, thumb);
+ BLI_snprintf(path, FILE_MAX, "%s%s", tmppath, thumb);
+ rv = 1;
+ }
+ return rv;
+}
+
+
+/* create thumbnail for file and returns new imbuf for thumbnail */
+ImBuf* IMB_thumb_create(const char* dir, const char* file, ThumbSize size, ThumbSource source)
+{
+ ImBuf *img = 0;
+ char uri[URI_MAX];
+ char desc[URI_MAX+22];
+ char tpath[FILE_MAX];
+ char tdir[FILE_MAX];
+ char wdir[FILE_MAX];
+ char temp[FILE_MAX];
+ char mtime[40];
+ char cwidth[40];
+ char cheight[40];
+ char thumb[40];
+ short tsize = 128;
+ short ex, ey;
+ float scaledx, scaledy;
+ struct stat info;
+
+ switch(size) {
+ case THB_NORMAL:
+ tsize = 128;
+ break;
+ case THB_LARGE:
+ tsize = 256;
+ break;
+ case THB_FAIL:
+ tsize = 0;
+ break;
+ default:
+ return 0; /* unknown size */
+ }
+
+ uri_from_filename(dir, file,uri);
+ thumbname_from_uri(uri, thumb);
+ if (get_thumb_dir(tdir, size)) {
+ BLI_snprintf(tpath, FILE_MAX, "%s%s", tdir, thumb);
+ thumb[8] = '\0'; /* shorten for tempname, not needed anymore */
+ BLI_snprintf(temp, FILE_MAX, "%sblender_%d_%s.png", tdir, abs(getpid()), thumb);
+ if (strncmp(thumb, dir, strlen(dir)) == 0) {
+ return NULL;
+ }
+ if (size == THB_FAIL) {
+ img = IMB_allocImBuf(0,0,32, IB_rect | IB_imginfo, 0);
+ if (!img) return 0;
+ } else {
+ if (THB_SOURCE_IMAGE == source) {
+ BLI_getwdN(wdir);
+ chdir(dir);
+ img = IMB_loadiffname(file, IB_rect | IB_imginfo);
+ if (img != NULL) {
+ stat(file, &info);
+ sprintf(mtime, "%ld", info.st_mtime);
+ sprintf(cwidth, "%d", img->x);
+ sprintf(cheight, "%d", img->y);
+ chdir(wdir);
+ }
+ } else if (THB_SOURCE_MOVIE == source) {
+ struct anim * anim = NULL;
+ BLI_getwdN(wdir);
+ chdir(dir);
+ anim = IMB_open_anim(file, IB_rect | IB_imginfo);
+ if (anim != NULL) {
+ img = IMB_anim_absolute(anim, 0);
+ if (img == NULL) {
+ printf("not an anim; %s\n", file);
+ } else {
+ IMB_freeImBuf(img);
+ img = IMB_anim_previewframe(anim);
+ }
+ IMB_free_anim(anim);
+ }
+ stat(file, &info);
+ sprintf(mtime, "%ld", info.st_mtime);
+ chdir(wdir);
+ }
+ if (!img) return 0;
+
+ if (img->x > img->y) {
+ scaledx = (float)tsize;
+ scaledy = ( (float)img->y/(float)img->x )*tsize;
+ }
+ else {
+ scaledy = (float)tsize;
+ scaledx = ( (float)img->x/(float)img->y )*tsize;
+ }
+ ex = (short)scaledx;
+ ey = (short)scaledy;
+
+ IMB_scaleImBuf(img, ex, ey);
+ }
+ sprintf(desc, "Thumbnail for %s", uri);
+ IMB_imginfo_change_field(img, "Description", desc);
+ IMB_imginfo_change_field(img, "Software", "Blender");
+ IMB_imginfo_change_field(img, "Thumb::URI", uri);
+ IMB_imginfo_change_field(img, "Thumb::MTime", mtime);
+ if (THB_SOURCE_IMAGE == source) {
+ IMB_imginfo_change_field(img, "Thumb::Image::Width", cwidth);
+ IMB_imginfo_change_field(img, "Thumb::Image::Height", cheight);
+ }
+ img->ftype = PNG;
+ img->depth = 32;
+ if (IMB_saveiff(img, temp, IB_rect | IB_imginfo)) {
+#ifndef WIN32
+ chmod(temp, S_IRUSR | S_IWUSR);
+#endif
+ BLI_rename(temp, tpath);
+ }
+
+ return img;
+ }
+ return img;
+}
+
+/* read thumbnail for file and returns new imbuf for thumbnail */
+ImBuf* IMB_thumb_read(const char* dir, const char* file, ThumbSize size)
+{
+ char thumb[FILE_MAX];
+ char uri[FILE_MAX*3+8];
+ ImBuf *img = 0;
+
+ if (!uri_from_filename(dir, file,uri)) {
+ return NULL;
+ }
+ if (thumbpath_from_uri(uri, thumb, size)) {
+ img = IMB_loadiffname(thumb, IB_rect | IB_imginfo);
+ }
+
+ return img;
+}
+
+/* delete all thumbs for the file */
+void IMB_thumb_delete(const char* dir, const char* file, ThumbSize size)
+{
+ char thumb[FILE_MAX];
+ char uri[FILE_MAX*3+8];
+
+ if (!uri_from_filename(dir, file,uri)) {
+ return;
+ }
+ if (thumbpath_from_uri(uri, thumb, size)) {
+ if (strncmp(thumb, dir, strlen(dir)) == 0) {
+ return;
+ }
+ if (BLI_exists(thumb)) {
+ BLI_delete(thumb, 0, 0);
+ }
+ }
+}
+
+
+/* create the thumb if necessary and manage failed and old thumbs */
+ImBuf* IMB_thumb_manage(const char* dir, const char* file, ThumbSize size, ThumbSource source)
+{
+ char path[FILE_MAX];
+ char thumb[FILE_MAX];
+ char uri[FILE_MAX*3+8];
+ struct stat st;
+ ImBuf* img = NULL;
+
+ BLI_join_dirfile(path, dir, file);
+ if (stat(path, &st)) {
+ return NULL;
+ }
+ if (!uri_from_filename(dir, file,uri)) {
+ return NULL;
+ }
+ if (thumbpath_from_uri(uri, thumb, THB_FAIL)) {
+ /* failure thumb exists, don't try recreating */
+ if (BLI_exists(thumb)) {
+ return NULL;
+ }
+ }
+
+ if (thumbpath_from_uri(uri, thumb, size)) {
+ if (strncmp(thumb, dir, strlen(dir)) == 0) {
+ img = IMB_loadiffname(path, IB_rect);
+ } else {
+ img = IMB_loadiffname(thumb, IB_rect | IB_imginfo);
+ if (img) {
+ char mtime[40];
+ if (!IMB_imginfo_get_field(img, "Thumb::MTime", mtime, 40)) {
+ /* illegal thumb, forget it! */
+ IMB_freeImBuf(img);
+ img = 0;
+ } else {
+ time_t t = atol(mtime);
+ if (st.st_mtime != t) {
+ /* recreate all thumbs */
+ IMB_freeImBuf(img);
+ img = 0;
+ IMB_thumb_delete(dir, file, THB_NORMAL);
+ IMB_thumb_delete(dir, file, THB_LARGE);
+ IMB_thumb_delete(dir, file, THB_FAIL);
+ img = IMB_thumb_create(dir, file, size, source);
+ if(!img){
+ /* thumb creation failed, write fail thumb */
+ img = IMB_thumb_create(dir, file, THB_FAIL, source);
+ if (img) {
+ /* we don't need failed thumb anymore */
+ IMB_freeImBuf(img);
+ img = 0;
+ }
+ }
+ }
+ }
+ } else {
+ img = IMB_thumb_create(dir, file, size, source);
+ if(!img){
+ /* thumb creation failed, write fail thumb */
+ img = IMB_thumb_create(dir, file, THB_FAIL, source);
+ if (img) {
+ /* we don't need failed thumb anymore */
+ IMB_freeImBuf(img);
+ img = 0;
+ }
+ }
+ }
+ }
+ }
+
+ return img;
+}
+
+
diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c
index 6fc5fb99f8b..dfa4e5831ba 100644
--- a/source/blender/imbuf/intern/tiff.c
+++ b/source/blender/imbuf/intern/tiff.c
@@ -43,7 +43,6 @@
* used to compress images.
*/
-#include <assert.h>
#include <string.h>
#include "imbuf.h"
@@ -108,7 +107,6 @@ int imb_tiff_DummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
*
* @return: Number of bytes actually read.
* 0 = EOF.
- * -1 = Error (never returned).
*/
tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n)
{
@@ -118,8 +116,10 @@ tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n)
/* get the pointer to the in-memory file */
mfile = IMB_TIFF_GET_MEMFILE(handle);
- assert(mfile != NULL);
- assert(mfile->mem != NULL);
+ if (!mfile || !mfile->mem) {
+ fprintf(stderr, "imb_tiff_ReadProc: !mfile || !mfile->mem!\n");
+ return 0;
+ }
/* find the actual number of bytes to read (copy) */
nCopy = n;
@@ -136,7 +136,6 @@ tsize_t imb_tiff_ReadProc(thandle_t handle, tdata_t data, tsize_t n)
return (0);
/* all set -> do the read (copy) */
- assert(sizeof(unsigned char) == 1);
srcAddr = (void*)(&(mfile->mem[mfile->offset]));
memcpy((void*)data, srcAddr, nCopy);
mfile->offset += nCopy; /* advance file ptr by copied bytes */
@@ -180,8 +179,10 @@ toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence)
/* get the pointer to the in-memory file */
mfile = IMB_TIFF_GET_MEMFILE(handle);
- assert(mfile != NULL);
- assert(mfile->mem != NULL);
+ if (!mfile || !mfile->mem) {
+ fprintf(stderr, "imb_tiff_SeekProc: !mfile || !mfile->mem!\n");
+ return (-1);
+ }
/* find the location we plan to seek to */
switch (whence) {
@@ -193,7 +194,9 @@ toff_t imb_tiff_SeekProc(thandle_t handle, toff_t ofs, int whence)
break;
default:
/* no other types are supported - return an error */
- printf("Unsupported TIFF SEEK type.\n");
+ fprintf(stderr,
+ "imb_tiff_SeekProc: "
+ "Unsupported TIFF SEEK type.\n");
return (-1);
}
@@ -222,8 +225,10 @@ int imb_tiff_CloseProc(thandle_t handle)
/* get the pointer to the in-memory file */
mfile = IMB_TIFF_GET_MEMFILE(handle);
- assert(mfile != NULL);
- assert(mfile->mem != NULL); /* the file has not been closed yet */
+ if (!mfile || !mfile->mem) {
+ fprintf(stderr,"imb_tiff_CloseProc: !mfile || !mfile->mem!\n");
+ return (0);
+ }
/* virtually close the file */
mfile->mem = NULL;
@@ -246,8 +251,10 @@ toff_t imb_tiff_SizeProc(thandle_t handle)
/* get the pointer to the in-memory file */
mfile = IMB_TIFF_GET_MEMFILE(handle);
- assert(mfile != NULL);
- assert(mfile->mem != NULL);
+ if (!mfile || !mfile->mem) {
+ fprintf(stderr,"imb_tiff_SizeProc: !mfile || !mfile->mem!\n");
+ return (0);
+ }
/* return the size */
return (toff_t)(mfile->size);
@@ -305,7 +312,7 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags)
struct ImBuf *ibuf = NULL;
struct ImbTIFFMemFile memFile;
uint32 width, height;
- int bytesperpixel;
+ int bytesperpixel, bitspersample;
int success;
unsigned int pixel_i, byte_i;
uint32 *raster = NULL;
@@ -317,7 +324,10 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags)
memFile.size = size;
/* check whether or not we have a TIFF file */
- assert(size >= IMB_TIFF_NCB);
+ if (size < IMB_TIFF_NCB) {
+ fprintf(stderr, "imb_loadtiff: size < IMB_TIFF_NCB\n");
+ return NULL;
+ }
if (imb_is_a_tiff(mem) == 0)
return NULL;
@@ -336,11 +346,13 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags)
bytesperpixel = 4; /* 1 byte per channel, 4 channels */
libtiff_TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width);
libtiff_TIFFGetField(image, TIFFTAG_IMAGELENGTH, &height);
+ libtiff_TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample);
ibuf = IMB_allocImBuf(width, height, 8*bytesperpixel, 0, 0);
if (ibuf) {
ibuf->ftype = TIF;
} else {
- printf("imb_loadtiff: could not allocate memory for TIFF " \
+ fprintf(stderr,
+ "imb_loadtiff: could not allocate memory for TIFF " \
"image.\n");
libtiff_TIFFClose(image);
return NULL;
@@ -362,7 +374,8 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags)
success = libtiff_TIFFReadRGBAImage(
image, width, height, raster, 0);
if (!success) {
- printf("imb_loadtiff: This TIFF format is not " \
+ fprintf(stderr,
+ "imb_loadtiff: This TIFF format is not "
"currently supported by Blender.\n");
libtiff__TIFFfree(raster);
libtiff_TIFFClose(image);
@@ -378,7 +391,8 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags)
/* this may not be entirely necessary, but is put here
* in case sizeof(unsigned int) is not a 32-bit
* quantity */
- printf("imb_loadtiff: using (slower) component-wise " \
+ fprintf(stderr,
+ "imb_loadtiff: using (slower) component-wise "
"buffer copy.\n");
to = (unsigned char*)ibuf->rect;
for (pixel_i=0; pixel_i < width*height; pixel_i++)
@@ -405,8 +419,6 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags)
return (ibuf);
}
-
-
/**
* Saves a TIFF file.
*
@@ -422,14 +434,19 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags)
*
* @return: 1 if the function is successful, 0 on failure.
*/
+
+#define FTOUSHORT(val) ((val >= 1.0f-0.5f/65535)? 65535: (val <= 0.0f)? 0: (unsigned short)(val*65535.0f + 0.5f))
+
short imb_savetiff(struct ImBuf *ibuf, char *name, int flags)
{
TIFF *image = NULL;
- uint16 samplesperpixel;
+ uint16 samplesperpixel, bitspersample;
size_t npixels;
unsigned char *pixels = NULL;
unsigned char *from = NULL, *to = NULL;
- int x, y, from_i, to_i;
+ unsigned short *pixels16 = NULL, *to16 = NULL;
+ float *fromf = NULL;
+ int x, y, from_i, to_i, i;
int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA };
/* check for a valid number of bytes per pixel. Like the PNG writer,
@@ -437,15 +454,22 @@ short imb_savetiff(struct ImBuf *ibuf, char *name, int flags)
* to gray, RGB, RGBA respectively. */
samplesperpixel = (uint16)((ibuf->depth + 7) >> 3);
if ((samplesperpixel > 4) || (samplesperpixel == 2)) {
- printf("imb_savetiff: unsupported number of bytes per " \
+ fprintf(stderr,
+ "imb_savetiff: unsupported number of bytes per "
"pixel: %d\n", samplesperpixel);
return (0);
}
+ if((ibuf->ftype & TIF_16BIT) && ibuf->rect_float)
+ bitspersample = 16;
+ else
+ bitspersample = 8;
+
/* open TIFF file for writing */
if (flags & IB_mem) {
/* bork at the creation of a TIFF in memory */
- printf("imb_savetiff: creation of in-memory TIFF files is " \
+ fprintf(stderr,
+ "imb_savetiff: creation of in-memory TIFF files is "
"not yet supported.\n");
return (0);
} else {
@@ -453,72 +477,74 @@ short imb_savetiff(struct ImBuf *ibuf, char *name, int flags)
image = libtiff_TIFFOpen(name, "w");
}
if (image == NULL) {
- printf("imb_savetiff: could not open TIFF for writing.\n");
+ fprintf(stderr,
+ "imb_savetiff: could not open TIFF for writing.\n");
return (0);
}
/* allocate array for pixel data */
npixels = ibuf->x * ibuf->y;
- pixels = (unsigned char*)libtiff__TIFFmalloc(npixels *
- samplesperpixel * sizeof(unsigned char));
- if (pixels == NULL) {
- printf("imb_savetiff: could not allocate pixels array.\n");
+ if(ibuf->ftype & TIF_16BIT)
+ pixels16 = (unsigned short*)libtiff__TIFFmalloc(npixels *
+ samplesperpixel * sizeof(unsigned short));
+ else
+ pixels = (unsigned char*)libtiff__TIFFmalloc(npixels *
+ samplesperpixel * sizeof(unsigned char));
+
+ if (pixels == NULL && pixels16 == NULL) {
+ fprintf(stderr,
+ "imb_savetiff: could not allocate pixels array.\n");
libtiff_TIFFClose(image);
return (0);
}
- /* copy pixel data. While copying, we flip the image
- * vertically. */
- from = (unsigned char*)ibuf->rect;
- to = pixels;
+ /* setup pointers */
+ if(ibuf->ftype & TIF_16BIT) {
+ fromf = ibuf->rect_float;
+ to16 = pixels16;
+ }
+ else {
+ from = (unsigned char*)ibuf->rect;
+ to = pixels;
+ }
+
+ /* setup samples per pixel */
+ libtiff_TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, bitspersample);
libtiff_TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
- switch (samplesperpixel) {
- case 4: /* RGBA images, 8 bits per channel */
- libtiff_TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
- extraSampleTypes);
- libtiff_TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 8);
- libtiff_TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
- PHOTOMETRIC_RGB);
- for (x = 0; x < ibuf->x; x++) {
- for (y = 0; y < ibuf->y; y++) {
- from_i = 4*(y*ibuf->x+x);
- to_i = 4*((ibuf->y-y-1)*ibuf->x+x);
-
- to[to_i++] = from[from_i++];
- to[to_i++] = from[from_i++];
- to[to_i++] = from[from_i++];
- to[to_i] = from[from_i];
- }
- }
- break;
- case 3: /* RGB images, 8 bits per channel */
- libtiff_TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 8);
- libtiff_TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
- PHOTOMETRIC_RGB);
- for (x = 0; x < ibuf->x; x++) {
- for (y = 0; y < ibuf->y; y++) {
- from_i = 4*(y*ibuf->x+x);
- to_i = 3*((ibuf->y-y-1)*ibuf->x+x);
-
- to[to_i++] = from[from_i++];
- to[to_i++] = from[from_i++];
- to[to_i] = from[from_i];
- }
- }
- break;
- case 1: /* greyscale images, 1 channel with 8 bits */
- libtiff_TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 8);
- libtiff_TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
- PHOTOMETRIC_MINISBLACK);
- for (x = 0; x < ibuf->x; x++) {
- for (y = 0; y < ibuf->y; y++) {
- from_i = 4*(y*ibuf->x+x);
- to_i = 1*((ibuf->y-y-1)*ibuf->x+x);
+ if(samplesperpixel == 4) {
+ /* RGBA images */
+ libtiff_TIFFSetField(image, TIFFTAG_EXTRASAMPLES, 1,
+ extraSampleTypes);
+ libtiff_TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
+ PHOTOMETRIC_RGB);
+ }
+ else if(samplesperpixel == 3) {
+ /* RGB images */
+ libtiff_TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
+ PHOTOMETRIC_RGB);
+ }
+ else if(samplesperpixel == 1) {
+ /* greyscale images, 1 channel */
+ libtiff_TIFFSetField(image, TIFFTAG_PHOTOMETRIC,
+ PHOTOMETRIC_MINISBLACK);
+ }
+
+ /* copy pixel data. While copying, we flip the image vertically. */
+ for (x = 0; x < ibuf->x; x++) {
+ for (y = 0; y < ibuf->y; y++) {
+ from_i = 4*(y*ibuf->x+x);
+ to_i = samplesperpixel*((ibuf->y-y-1)*ibuf->x+x);
+
+ if(pixels16) {
+ for (i = 0; i < samplesperpixel; i++, to_i++, from_i++)
+ to16[to_i] = FTOUSHORT(fromf[from_i]);
+ }
+ else {
+ for (i = 0; i < samplesperpixel; i++, to_i++, from_i++)
to[to_i] = from[from_i];
- }
}
- break;
+ }
}
/* write the actual TIFF file */
@@ -531,17 +557,21 @@ short imb_savetiff(struct ImBuf *ibuf, char *name, int flags)
libtiff_TIFFSetField(image, TIFFTAG_XRESOLUTION, 150.0);
libtiff_TIFFSetField(image, TIFFTAG_YRESOLUTION, 150.0);
libtiff_TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
- if (libtiff_TIFFWriteEncodedStrip(image, 0, pixels,
- ibuf->x*ibuf->y*samplesperpixel) == -1) {
- printf("imb_savetiff: Could not write encoded TIFF.\n");
+ if (libtiff_TIFFWriteEncodedStrip(image, 0,
+ (bitspersample == 16)? (unsigned char*)pixels16: pixels,
+ ibuf->x*ibuf->y*samplesperpixel*bitspersample/8) == -1) {
+ fprintf(stderr,
+ "imb_savetiff: Could not write encoded TIFF.\n");
libtiff_TIFFClose(image);
- libtiff__TIFFfree(pixels);
+ if(pixels) libtiff__TIFFfree(pixels);
+ if(pixels16) libtiff__TIFFfree(pixels16);
return (1);
}
/* close the TIFF file */
libtiff_TIFFClose(image);
- libtiff__TIFFfree(pixels);
+ if(pixels) libtiff__TIFFfree(pixels);
+ if(pixels16) libtiff__TIFFfree(pixels16);
return (1);
}
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 69390951a25..acf15c04ed9 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -44,6 +44,11 @@
#include "IMB_targa.h"
#include "IMB_png.h"
+
+#ifdef WITH_DDS
+#include "dds/dds_api.h"
+#endif
+
#include "IMB_bmp.h"
#include "IMB_tiff.h"
#include "IMB_radiance_hdr.h"
@@ -113,6 +118,9 @@ static int IMB_ispic_name(char *name)
}
if (imb_is_a_png(buf)) return(PNG);
+#ifdef WITH_DDS
+ if (imb_is_a_dds((uchar *)buf)) return(DDS);
+#endif
if (imb_is_a_targa(buf)) return(TGA);
#ifdef WITH_OPENEXR
if (imb_is_a_openexr((uchar *)buf)) return(OPENEXR);
@@ -162,6 +170,9 @@ int IMB_ispic(char *filename)
|| BLI_testextensie(filename, ".rgb")
|| BLI_testextensie(filename, ".bmp")
|| BLI_testextensie(filename, ".png")
+#ifdef WITH_DDS
+ || BLI_testextensie(filename, ".dds")
+#endif
|| BLI_testextensie(filename, ".iff")
|| BLI_testextensie(filename, ".lbm")
|| BLI_testextensie(filename, ".gif")
@@ -188,6 +199,9 @@ int IMB_ispic(char *filename)
|| BLI_testextensie(filename, ".bmp")
|| BLI_testextensie(filename, ".png")
|| BLI_testextensie(filename, ".cin")
+#ifdef WITH_DDS
+ || BLI_testextensie(filename, ".dds")
+#endif
#ifdef WITH_BF_OPENEXR
|| BLI_testextensie(filename, ".exr")
#endif
@@ -251,6 +265,7 @@ static int isffmpeg (char *filename) {
if( BLI_testextensie(filename, ".swf") ||
BLI_testextensie(filename, ".jpg") ||
BLI_testextensie(filename, ".png") ||
+ BLI_testextensie(filename, ".dds") ||
BLI_testextensie(filename, ".tga") ||
BLI_testextensie(filename, ".bmp") ||
BLI_testextensie(filename, ".exr") ||
@@ -274,8 +289,9 @@ static int isffmpeg (char *filename) {
/* Find the first video stream */
videoStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
- if(get_codec_from_stream(pFormatCtx->streams[i])
- ->codec_type==CODEC_TYPE_VIDEO)
+ if(pFormatCtx->streams[i] &&
+ get_codec_from_stream(pFormatCtx->streams[i]) &&
+ (get_codec_from_stream(pFormatCtx->streams[i])->codec_type==CODEC_TYPE_VIDEO))
{
videoStream=i;
break;
diff --git a/source/blender/imbuf/intern/writeimage.c b/source/blender/imbuf/intern/writeimage.c
index 2e922c65827..ccca8e9f859 100644
--- a/source/blender/imbuf/intern/writeimage.c
+++ b/source/blender/imbuf/intern/writeimage.c
@@ -61,6 +61,9 @@
#ifdef WITH_OPENEXR
#include "openexr/openexr_api.h"
#endif
+#ifdef WITH_DDS
+#include "dds/dds_api.h"
+#endif
#include "IMB_iff.h"
#include "IMB_bitplanes.h"
@@ -115,6 +118,13 @@ short IMB_saveiff(struct ImBuf *ibuf, char *name, int flags)
return imb_save_openexr(ibuf, name, flags);
}
#endif
+/* not supported yet
+#ifdef WITH_DDS
+ if (IS_dds(ibuf)) {
+ return imb_save_dds(ibuf, name, flags);
+ }
+#endif
+*/
if (IS_cineon(ibuf)) {
return imb_savecineon(ibuf, name, flags);