diff options
Diffstat (limited to 'source/blender/imbuf/intern')
45 files changed, 2567 insertions, 853 deletions
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index 2c7f8bddbe6..745248d3218 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -81,6 +81,14 @@ #include <ffmpeg/swscale.h> #endif +#ifdef WITH_REDCODE +#ifdef _WIN32 /* on windows we use the one in extern instead */ +#include "libredcode/format.h" +#else +#include "libredcode/format.h" +#endif +#endif + #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -96,7 +104,7 @@ #define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff)) /* more endianness... should move to a separate file... */ -#if defined(__sgi) || defined (__sparc) || (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +#if defined(__sgi) || defined (__sparc) || (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__hppa__) || defined (__BIG_ENDIAN__) #define GET_ID GET_BIG_LONG #define LITTLE_LONG SWAP_LONG #else @@ -116,6 +124,7 @@ #define ANIM_AVI (1 << 6) #define ANIM_QTIME (1 << 7) #define ANIM_FFMPEG (1 << 8) +#define ANIM_REDCODE (1 << 9) #define ANIM5_MMAP 0 #define ANIM5_MALLOC 1 @@ -178,12 +187,16 @@ struct anim { AVFormatContext *pFormatCtx; AVCodecContext *pCodecCtx; AVCodec *pCodec; - AVFrame *pFrameRGB; AVFrame *pFrame; + AVFrame *pFrameRGB; + AVFrame *pFrameDeinterlaced; struct SwsContext *img_convert_ctx; int videoStream; #endif +#ifdef WITH_REDCODE + struct redcode_handle * redcodeCtx; +#endif }; #endif diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index be462d67238..ad7b1dce2e0 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -277,6 +277,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; @@ -442,7 +443,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)); @@ -474,6 +475,7 @@ struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf1) // set malloc flag tbuf.mall = ibuf2->mall; tbuf.c_handle = 0; + tbuf.refcounter = 0; // for now don't duplicate image info tbuf.img_info = 0; diff --git a/source/blender/imbuf/intern/amiga.c b/source/blender/imbuf/intern/amiga.c index fa13b55874a..534e4945aa3 100644 --- a/source/blender/imbuf/intern/amiga.c +++ b/source/blender/imbuf/intern/amiga.c @@ -29,8 +29,12 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef WIN32 +#ifdef _WIN32 #include <io.h> +#define open _open +#define read _read +#define close _close +#define write _write #endif #include "imbuf.h" #include "imbuf_patch.h" @@ -52,7 +56,7 @@ #define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff)) /* more endianness... should move to a separate file... */ -#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__hppa__) || defined (__BIG_ENDIAN__) #define GET_ID GET_BIG_LONG #define LITTLE_LONG SWAP_LONG #else diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c index ef3dd79db73..80bf401bec0 100644 --- a/source/blender/imbuf/intern/anim.c +++ b/source/blender/imbuf/intern/anim.c @@ -96,6 +96,16 @@ #endif +#ifdef WITH_REDCODE +#ifdef _WIN32 /* on windows we use the ones in extern instead */ +#include "libredcode/format.h" +#include "libredcode/codec.h" +#else +#include "libredcode/format.h" +#include "libredcode/codec.h" +#endif +#endif + /****/ #ifdef __sgi @@ -307,6 +317,9 @@ void IMB_free_anim_ibuf(struct anim * anim) { #ifdef WITH_FFMPEG static void free_anim_ffmpeg(struct anim * anim); #endif +#ifdef WITH_REDCODE +static void free_anim_redcode(struct anim * anim); +#endif void IMB_free_anim(struct anim * anim) { if (anim == NULL) { @@ -325,6 +338,9 @@ void IMB_free_anim(struct anim * anim) { #ifdef WITH_FFMPEG free_anim_ffmpeg(anim); #endif +#ifdef WITH_REDCODE + free_anim_redcode(anim); +#endif free(anim); } @@ -589,19 +605,31 @@ static int startffmpeg(struct anim * anim) { anim->videoStream = videoStream; anim->pFrame = avcodec_alloc_frame(); + anim->pFrameDeinterlaced = 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"); avcodec_close(anim->pCodecCtx); av_close_input_file(anim->pFormatCtx); av_free(anim->pFrameRGB); + av_free(anim->pFrameDeinterlaced); av_free(anim->pFrame); + anim->pCodecCtx = NULL; return -1; } + if (anim->ib_flags & IB_animdeinterlace) { + avpicture_fill((AVPicture*) anim->pFrameDeinterlaced, + MEM_callocN(avpicture_get_size( + anim->pCodecCtx->pix_fmt, + anim->x, anim->y), + "ffmpeg deinterlace"), + anim->pCodecCtx->pix_fmt, anim->x, anim->y); + } + if (pCodecCtx->has_b_frames) { anim->preseek = 25; /* FIXME: detect gopsize ... */ } else { @@ -614,10 +642,22 @@ static int startffmpeg(struct anim * anim) { anim->pCodecCtx->pix_fmt, anim->pCodecCtx->width, anim->pCodecCtx->height, - PIX_FMT_RGBA, + PIX_FMT_BGR32, SWS_FAST_BILINEAR | SWS_PRINT_INFO, NULL, NULL, NULL); - + + if (!anim->img_convert_ctx) { + fprintf (stderr, + "Can't transform color space??? Bailing out...\n"); + avcodec_close(anim->pCodecCtx); + av_close_input_file(anim->pFormatCtx); + av_free(anim->pFrameRGB); + av_free(anim->pFrameDeinterlaced); + av_free(anim->pFrame); + anim->pCodecCtx = NULL; + return -1; + } + return (0); } @@ -627,14 +667,15 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { AVPacket packet; int64_t pts_to_search = 0; int pos_found = 1; + int filter_y = 0; if (anim == 0) return (0); ibuf = IMB_allocImBuf(anim->x, anim->y, 24, IB_rect, 0); - avpicture_fill((AVPicture *)anim->pFrameRGB, + 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 @@ -711,35 +752,135 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { } if(frameFinished && pos_found == 1) { - 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; - - sws_scale(anim->img_convert_ctx, - anim->pFrame->data, - anim->pFrame->linesize, - 0, - anim->pCodecCtx->height, - dst2, - dstStride2); - - /* workaround: sws_scale sets alpha = 0... */ - for (i = 0; i < ibuf->x * ibuf->y; i++) { - ibuf->rect[i] |= 0xff000000; + AVFrame * input = anim->pFrame; + + /* This means the data wasnt read properly, + this check stops crashing */ + if (input->data[0]==0 && input->data[1]==0 + && input->data[2]==0 && input->data[3]==0){ + av_free_packet(&packet); + break; } - av_free_packet(&packet); - break; + if (anim->ib_flags & IB_animdeinterlace) { + if (avpicture_deinterlace( + (AVPicture*) + anim->pFrameDeinterlaced, + (const AVPicture*) + anim->pFrame, + anim->pCodecCtx->pix_fmt, + anim->pCodecCtx->width, + anim->pCodecCtx->height) + < 0) { + filter_y = 1; + } else { + input = anim->pFrameDeinterlaced; + } + } + + 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, + input->data, + input->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 { + 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, + input->data, + input->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); } + if (filter_y && ibuf) { + IMB_filtery(ibuf); + } + return(ibuf); } @@ -751,6 +892,11 @@ static void free_anim_ffmpeg(struct anim * anim) { av_close_input_file(anim->pFormatCtx); av_free(anim->pFrameRGB); av_free(anim->pFrame); + + if (anim->ib_flags & IB_animdeinterlace) { + MEM_freeN(anim->pFrameDeinterlaced->data[0]); + } + av_free(anim->pFrameDeinterlaced); sws_freeContext(anim->img_convert_ctx); } anim->duration = 0; @@ -758,6 +904,58 @@ static void free_anim_ffmpeg(struct anim * anim) { #endif +#ifdef WITH_REDCODE + +static int startredcode(struct anim * anim) { + anim->redcodeCtx = redcode_open(anim->name); + if (!anim->redcodeCtx) { + return -1; + } + anim->duration = redcode_get_length(anim->redcodeCtx); + + return 0; +} + +static ImBuf * redcode_fetchibuf(struct anim * anim, int position) { + struct ImBuf * ibuf; + struct redcode_frame * frame; + struct redcode_frame_raw * raw_frame; + + if (!anim->redcodeCtx) { + return NULL; + } + + frame = redcode_read_video_frame(anim->redcodeCtx, position); + + if (!frame) { + return NULL; + } + + raw_frame = redcode_decode_video_raw(frame, 1); + + redcode_free_frame(frame); + + if (!raw_frame) { + return NULL; + } + + ibuf = IMB_allocImBuf(raw_frame->width * 2, + raw_frame->height * 2, 32, IB_rectfloat, 0); + + redcode_decode_video_float(raw_frame, ibuf->rect_float, 1); + + return ibuf; +} + +static void free_anim_redcode(struct anim * anim) { + if (anim->redcodeCtx) { + redcode_close(anim->redcodeCtx); + anim->redcodeCtx = 0; + } + anim->duration = 0; +} + +#endif /* probeer volgende plaatje te lezen */ /* Geen plaatje, probeer dan volgende animatie te openen */ @@ -777,6 +975,10 @@ static struct ImBuf * anim_getnew(struct anim * anim) { #ifdef WITH_FFMPEG free_anim_ffmpeg(anim); #endif +#ifdef WITH_REDCODE + free_anim_redcode(anim); +#endif + if (anim->curtype != 0) return (0); anim->curtype = imb_get_anim_type(anim->name); @@ -816,8 +1018,13 @@ static struct ImBuf * anim_getnew(struct anim * anim) { ibuf = IMB_allocImBuf (anim->x, anim->y, 24, 0, 0); break; #endif +#ifdef WITH_REDCODE + case ANIM_REDCODE: + if (startredcode(anim)) return (0); + ibuf = IMB_allocImBuf (8, 8, 32, 0, 0); + break; +#endif } - return(ibuf); } @@ -839,6 +1046,7 @@ struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) { char head[256], tail[256]; unsigned short digits; int pic; + int filter_y = (anim->ib_flags & IB_animdeinterlace); if (anim == NULL) return(0); @@ -896,12 +1104,20 @@ struct ImBuf * IMB_anim_absolute(struct anim * anim, int position) { case ANIM_FFMPEG: ibuf = ffmpeg_fetchibuf(anim, position); if (ibuf) anim->curposition = position; + filter_y = 0; /* done internally */ + break; +#endif +#ifdef WITH_REDCODE + case ANIM_REDCODE: + ibuf = redcode_fetchibuf(anim, position); + if (ibuf) anim->curposition = position; break; #endif } if (ibuf) { if (anim->ib_flags & IB_ttob) IMB_flipy(ibuf); + if (filter_y) IMB_filtery(ibuf); sprintf(ibuf->name, "%s.%04d", anim->name, anim->curposition + 1); } diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 2aa276a5f53..141b8a985cf 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -164,9 +164,9 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags) } } else if (depth == 32) { for (i = x * y; i > 0; i--) { - rect[0] = bmp[0]; + rect[0] = bmp[2]; rect[1] = bmp[1]; - rect[2] = bmp[2]; + rect[2] = bmp[0]; rect[3] = bmp[3]; rect += 4; bmp += 4; } diff --git a/source/blender/imbuf/intern/cineon/SConscript b/source/blender/imbuf/intern/cineon/SConscript index 9d3bbcbc058..f887516443c 100644 --- a/source/blender/imbuf/intern/cineon/SConscript +++ b/source/blender/imbuf/intern/cineon/SConscript @@ -4,13 +4,13 @@ Import ('env') source_files = env.Glob('*.c') incs = ['.', - '../../../blenkernel', - '../../', - '..', - '../../../blenlib', - 'intern/include', - '#/intern/guardedalloc', - '../../../makesdna'] + '../../../blenkernel', + '../../', + '..', + '../../../blenlib', + 'intern/include', + '#/intern/guardedalloc', + '../../../makesdna'] defs = [] diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index 691b81745e0..514d6b5522b 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?G.scene->r.cineonblack:95; + params->whitePoint = G.scene?G.scene->r.cineonwhite:685; + params->gamma = G.scene?G.scene->r.cineongamma:1.7f; + params->doLogarithm = G.scene?G.scene->r.subimtype & R_CINEON_LOG:0; +} + 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... */ @@ -119,7 +135,13 @@ static int imb_save_dpx_cineon(ImBuf *buf, char *filename, int use_cineon, int f height = buf->y; depth = 3; - if (!buf->rect_float) return 0; + + if (!buf->rect_float) { + IMB_float_from_rect(buf); + if (!buf->rect_float) { /* in the unlikely event that converting to a float buffer fails */ + return 0; + } + } logImageSetVerbose(0); logImage = logImageCreate(filename, use_cineon, width, height, depth); diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index 20f4e0d4de4..75516bbf3ae 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -67,12 +67,12 @@ fillCineonFileInfo(CineonFile* cineon, CineonFileInformation* fileInfo, const ch static void dumpCineonFileInfo(CineonFileInformation* fileInfo) { d_printf("\n--File Information--\n"); - d_printf("Magic: %8.8lX\n", (unsigned long)ntohl(fileInfo->magic_num)); - d_printf("Image Offset %ld\n", (long)ntohl(fileInfo->image_offset)); - d_printf("Generic Header size %ld\n", (long)ntohl(fileInfo->gen_hdr_size)); - d_printf("Industry Header size %ld\n", (long)ntohl(fileInfo->ind_hdr_size)); - d_printf("User Data size %ld\n", (long)ntohl(fileInfo->user_data_size)); - d_printf("File size %ld\n", (long)ntohl(fileInfo->file_size)); + d_printf("Magic: %8.8lX\n", (uintptr_t)ntohl(fileInfo->magic_num)); + d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->image_offset)); + d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size)); + d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size)); + d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size)); + d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size)); d_printf("Version \"%s\"\n", fileInfo->vers); d_printf("File name \"%s\"\n", fileInfo->file_name); d_printf("Creation date \"%s\"\n", fileInfo->create_date); @@ -112,11 +112,11 @@ dumpCineonChannelInfo(CineonChannelInformation* chan) { default: d_printf(" (unknown)\n"); break; } d_printf(" Bits per pixel %d\n", chan->bits_per_pixel); - d_printf(" Pixels per line %ld\n", (long)ntohl(chan->pixels_per_line)); - d_printf(" Lines per image %ld\n", (long)ntohl(chan->lines_per_image)); - d_printf(" Ref low data %ld\n", (long)ntohl(chan->ref_low_data)); + d_printf(" Pixels per line %ld\n", (intptr_t)ntohl(chan->pixels_per_line)); + d_printf(" Lines per image %ld\n", (intptr_t)ntohl(chan->lines_per_image)); + d_printf(" Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data)); d_printf(" Ref low quantity %f\n", ntohf(chan->ref_low_quantity)); - d_printf(" Ref high data %ld\n", (long)ntohl(chan->ref_high_data)); + d_printf(" Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data)); d_printf(" Ref high quantity %f\n", ntohf(chan->ref_high_quantity)); } @@ -231,8 +231,8 @@ dumpCineonFormatInfo(CineonFormatInformation* formatInfo) { } else { d_printf(" positive\n"); } - d_printf("End of line padding %ld\n", (long)ntohl(formatInfo->line_padding)); - d_printf("End of channel padding %ld\n", (long)ntohl(formatInfo->channel_padding)); + d_printf("End of line padding %ld\n", (intptr_t)ntohl(formatInfo->line_padding)); + d_printf("End of channel padding %ld\n", (intptr_t)ntohl(formatInfo->channel_padding)); } static void @@ -256,8 +256,8 @@ fillCineonOriginationInfo(CineonFile* cineon, static void dumpCineonOriginationInfo(CineonOriginationInformation* originInfo) { d_printf("\n--Origination Information--\n"); - d_printf("X offset %ld\n", (long)ntohl(originInfo->x_offset)); - d_printf("Y offset %ld\n", (long)ntohl(originInfo->y_offset)); + d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset)); + d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset)); d_printf("File name \"%s\"\n", originInfo->file_name); d_printf("Creation date \"%s\"\n", originInfo->create_date); d_printf("Creation time \"%s\"\n", originInfo->create_time); @@ -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 */ @@ -525,7 +529,7 @@ cineonOpen(const char* filename) { /* let's assume cineon files are always network order */ if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) { if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n", - (unsigned long)ntohl(header.fileInfo.magic_num), filename); + (uintptr_t)ntohl(header.fileInfo.magic_num), filename); cineonClose(cineon); return 0; } @@ -613,7 +617,7 @@ cineonOpenFromMem(unsigned char *mem, unsigned int size) { cineon->file = 0; cineon->reading = 1; - verbose = 1; + verbose = 0; if (size < sizeof(CineonGenericHeader)) { if (verbose) d_printf("Not enough data for header!\n"); cineonClose(cineon); @@ -624,7 +628,7 @@ cineonOpenFromMem(unsigned char *mem, unsigned int size) { /* let's assume cineon files are always network order */ if (header.fileInfo.magic_num != ntohl(CINEON_FILE_MAGIC)) { - if (verbose) d_printf("Bad magic number %8.8lX in\n", (unsigned long)ntohl(header.fileInfo.magic_num)); + if (verbose) d_printf("Bad magic number %8.8lX in\n", (uintptr_t)ntohl(header.fileInfo.magic_num)); cineonClose(cineon); return 0; diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index b769d1e6132..8a9adc73cdc 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -58,15 +58,15 @@ fillDpxChannelInfo(DpxFile* dpx, DpxChannelInformation* chan, int des) { static void dumpDpxChannelInfo(DpxChannelInformation* chan) { - d_printf(" Signage %ld", (long)ntohl(chan->signage)); - d_printf(" Ref low data %ld\n", (long)ntohl(chan->ref_low_data)); + d_printf(" Signage %ld", (intptr_t)ntohl(chan->signage)); + d_printf(" Ref low data %ld\n", (intptr_t)ntohl(chan->ref_low_data)); d_printf(" Ref low quantity %f\n", ntohf(chan->ref_low_quantity)); - d_printf(" Ref high data %ld\n", (long)ntohl(chan->ref_high_data)); + d_printf(" Ref high data %ld\n", (intptr_t)ntohl(chan->ref_high_data)); d_printf(" Ref high quantity %f\n", ntohf(chan->ref_high_quantity)); d_printf(" Designator1: %d,", chan->designator1); d_printf(" Bits per pixel %d\n", chan->bits_per_pixel); d_printf(" Packing: %d,", ntohs(chan->packing)); - d_printf(" Data Offset: %ld,", (long)ntohl(chan->data_offset)); + d_printf(" Data Offset: %ld,", (intptr_t)ntohl(chan->data_offset)); } static void @@ -110,19 +110,19 @@ static void dumpDpxFileInfo(DpxFileInformation* fileInfo) { d_printf("\n--File Information--\n"); d_printf("Magic: %8.8lX\n", (unsigned long)ntohl(fileInfo->magic_num)); - d_printf("Image Offset %ld\n", (long)ntohl(fileInfo->offset)); + d_printf("Image Offset %ld\n", (intptr_t)ntohl(fileInfo->offset)); d_printf("Version \"%s\"\n", fileInfo->vers); - d_printf("File size %ld\n", (long)ntohl(fileInfo->file_size)); - d_printf("Ditto key %ld\n", (long)ntohl(fileInfo->ditto_key)); - d_printf("Generic Header size %ld\n", (long)ntohl(fileInfo->gen_hdr_size)); - d_printf("Industry Header size %ld\n", (long)ntohl(fileInfo->ind_hdr_size)); - d_printf("User Data size %ld\n", (long)ntohl(fileInfo->user_data_size)); + d_printf("File size %ld\n", (intptr_t)ntohl(fileInfo->file_size)); + d_printf("Ditto key %ld\n", (intptr_t)ntohl(fileInfo->ditto_key)); + d_printf("Generic Header size %ld\n", (intptr_t)ntohl(fileInfo->gen_hdr_size)); + d_printf("Industry Header size %ld\n", (intptr_t)ntohl(fileInfo->ind_hdr_size)); + d_printf("User Data size %ld\n", (intptr_t)ntohl(fileInfo->user_data_size)); d_printf("File name \"%s\"\n", fileInfo->file_name); d_printf("Creation date \"%s\"\n", fileInfo->create_date); d_printf("Creator \"%s\"\n", fileInfo->creator); d_printf("Project \"%s\"\n", fileInfo->project); d_printf("Copyright \"%s\"\n", fileInfo->copyright); - d_printf("Key %ld\n", (long)ntohl(fileInfo->key)); + d_printf("Key %ld\n", (intptr_t)ntohl(fileInfo->key)); } static void @@ -150,8 +150,8 @@ dumpDpxImageInfo(DpxImageInformation* imageInfo) { d_printf("Image orientation %d,", ntohs(imageInfo->orientation)); n = ntohs(imageInfo->channels_per_image); d_printf("Channels %d\n", n); - d_printf("Pixels per line %ld\n", (long)ntohl(imageInfo->pixels_per_line)); - d_printf("Lines per image %ld\n", (long)ntohl(imageInfo->lines_per_image)); + d_printf("Pixels per line %ld\n", (intptr_t)ntohl(imageInfo->pixels_per_line)); + d_printf("Lines per image %ld\n", (intptr_t)ntohl(imageInfo->lines_per_image)); for (i = 0; i < n; ++i) { d_printf(" --Channel %d--\n", i); dumpDpxChannelInfo(&imageInfo->channel[i]); @@ -166,12 +166,12 @@ fillDpxOriginationInfo( static void dumpDpxOriginationInfo(DpxOriginationInformation* originInfo) { d_printf("\n--Origination Information--\n"); - d_printf("X offset %ld\n", (long)ntohl(originInfo->x_offset)); - d_printf("Y offset %ld\n", (long)ntohl(originInfo->y_offset)); + d_printf("X offset %ld\n", (intptr_t)ntohl(originInfo->x_offset)); + d_printf("Y offset %ld\n", (intptr_t)ntohl(originInfo->y_offset)); d_printf("X centre %f\n", ntohf(originInfo->x_centre)); d_printf("Y centre %f\n", ntohf(originInfo->y_centre)); - d_printf("Original X %ld\n", (long)ntohl(originInfo->x_original_size)); - d_printf("Original Y %ld\n", (long)ntohl(originInfo->y_original_size)); + d_printf("Original X %ld\n", (intptr_t)ntohl(originInfo->x_original_size)); + d_printf("Original Y %ld\n", (intptr_t)ntohl(originInfo->y_original_size)); d_printf("File name \"%s\"\n", originInfo->file_name); d_printf("Creation time \"%s\"\n", originInfo->creation_time); d_printf("Input device \"%s\"\n", originInfo->input_device); @@ -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; @@ -413,7 +417,7 @@ intern_dpxOpen(int mode, const char* bytestuff, int bufsize) { /* let's assume dpx files are always network order */ if (header.fileInfo.magic_num != ntohl(DPX_FILE_MAGIC)) { if (verbose) d_printf("Bad magic number %8.8lX in \"%s\".\n", - (unsigned long)ntohl(header.fileInfo.magic_num), filename); + (uintptr_t)ntohl(header.fileInfo.magic_num), filename); dpxClose(dpx); return 0; } @@ -437,10 +441,15 @@ intern_dpxOpen(int mode, const char* bytestuff, int bufsize) { default: break; } } - dpx->bitsPerPixel = 10; - /* dpx->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel; */ - dpx->imageOffset = ntohl(header.fileInfo.offset); + /* dpx->bitsPerPixel = 10; */ + dpx->bitsPerPixel = header.imageInfo.channel[0].bits_per_pixel; + if (dpx->bitsPerPixel != 10) { + if (verbose) d_printf("Don't support depth: %d\n", dpx->bitsPerPixel); + dpxClose(dpx); + return 0; + } + dpx->imageOffset = ntohl(header.fileInfo.offset); dpx->lineBufferLength = pixelsToLongs(dpx->width * dpx->depth); dpx->lineBuffer = malloc(dpx->lineBufferLength * 4); if (dpx->lineBuffer == 0) { @@ -467,6 +476,26 @@ intern_dpxOpen(int mode, const char* bytestuff, int bufsize) { dpx->fileYPos = 0; logImageGetByteConversionDefaults(&dpx->params); + /* The SMPTE define this code: + * 2 - Linear + * 3 - Logarithmic + * + * Note that transfer_characteristics is U8, don't need + * check the byte order. + */ + switch (header.imageInfo.channel[0].transfer_characteristics) { + case 2: + dpx->params.doLogarithm= 0; + break; + case 3: + dpx->params.doLogarithm= 1; + break; + default: + if (verbose) d_printf("Un-supported Transfer Characteristics: %d\n", header.imageInfo.channel[0].transfer_characteristics); + dpxClose(dpx); + return 0; + break; + } setupLut(dpx); dpx->getRow = &dpxGetRowBytes; @@ -559,6 +588,18 @@ dpxCreate(const char* filename, int width, int height, int depth) { ++shortFilename; } initDpxMainHeader(dpx, &header, shortFilename); + logImageGetByteConversionDefaults(&dpx->params); + /* Need set the file type before write the header! + * 2 - Linear + * 3 - Logarithmic + * + * Note that transfer characteristics is U8, don't need + * check the byte order. + */ + if (dpx->params.doLogarithm == 0) + header.imageInfo.channel[0].transfer_characteristics= 2; + else + header.imageInfo.channel[0].transfer_characteristics= 3; if (fwrite(&header, sizeof(header), 1, dpx->file) == 0) { if (verbose) d_printf("Couldn't write image header\n"); @@ -566,8 +607,6 @@ dpxCreate(const char* filename, int width, int height, int depth) { return 0; } dpx->fileYPos = 0; - - logImageGetByteConversionDefaults(&dpx->params); setupLut(dpx); dpx->getRow = 0; 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..2646e8b3c12 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.h +++ b/source/blender/imbuf/intern/cineon/logImageCore.h @@ -34,7 +34,9 @@ extern "C" { #endif - +#include "BLO_sys_types.h" // for intptr_t support +#undef ntohl +#undef htonl typedef int (GetRowFn)(LogImageFile* logImage, unsigned short* row, int lineNum); typedef int (SetRowFn)(LogImageFile* logImage, const unsigned short* row, int lineNum); typedef void (CloseFn)(LogImageFile* logImage); @@ -71,17 +73,21 @@ 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; CloseFn* close; unsigned char *membuffer; - unsigned long membuffersize; + uintptr_t membuffersize; unsigned char *memcursor; }; 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/cineon/logmemfile.c b/source/blender/imbuf/intern/cineon/logmemfile.c index 20359335933..160e8453713 100644 --- a/source/blender/imbuf/intern/cineon/logmemfile.c +++ b/source/blender/imbuf/intern/cineon/logmemfile.c @@ -24,10 +24,10 @@ #include "logImageCore.h" -int logimage_fseek(void* logfile, long offsett, int origin) +int logimage_fseek(void* logfile, intptr_t offsett, int origin) { struct _Log_Image_File_t_ *file = (struct _Log_Image_File_t_*) logfile; - long offset = offsett; + intptr_t offset = offsett; if (file->file) fseek(file->file, offset, origin); else { /*we're seeking in memory*/ @@ -38,7 +38,7 @@ int logimage_fseek(void* logfile, long offsett, int origin) if (offset > file->membuffersize) return 1; file->memcursor = (file->membuffer + file->membuffersize) - offset; } else if (origin==SEEK_CUR) { - unsigned long pos = (unsigned long)file->membuffer - (unsigned long)file->memcursor; + uintptr_t pos = (uintptr_t)file->membuffer - (uintptr_t)file->memcursor; if (pos + offset > file->membuffersize) return 1; if (pos < 0) return 1; file->memcursor += offset; diff --git a/source/blender/imbuf/intern/cineon/logmemfile.h b/source/blender/imbuf/intern/cineon/logmemfile.h index 6e82cf2b145..39e2f36dad9 100644 --- a/source/blender/imbuf/intern/cineon/logmemfile.h +++ b/source/blender/imbuf/intern/cineon/logmemfile.h @@ -22,7 +22,7 @@ #ifndef _LOGMEMFILE_H #define _LOGMEMFILE_H -int logimage_fseek(void* logfile, long offsett, int origin); +int logimage_fseek(void* logfile, intptr_t offsett, int origin); int logimage_fwrite(void *buffer, unsigned int size, unsigned int count, void *logfile); int logimage_fread(void *buffer, unsigned int size, unsigned int count, void *logfile); diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp index 44435317f69..2a8a2c470c4 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.cpp +++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp @@ -61,7 +61,7 @@ BlockDXT1 ----------------------------------------------------------------------------*/ -unsigned int BlockDXT1::evaluatePalette(Color32 color_array[4]) const +uint BlockDXT1::evaluatePalette(Color32 color_array[4]) const { // Does bit expansion before interpolation. color_array[0].b = (col0.b << 3) | (col0.b >> 2); @@ -176,9 +176,9 @@ void BlockDXT1::decodeBlock(ColorBlock * block) const evaluatePalette(color_array); // Write color block. - for( unsigned int j = 0; j < 4; j++ ) { - for( unsigned int i = 0; i < 4; i++ ) { - unsigned int idx = (row[j] >> (2 * i)) & 3; + 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]; } } @@ -187,7 +187,7 @@ void BlockDXT1::decodeBlock(ColorBlock * block) const void BlockDXT1::setIndices(int * idx) { indices = 0; - for(unsigned int i = 0; i < 16; i++) { + for(uint i = 0; i < 16; i++) { indices |= (idx[i] & 3) << (2 * i); } } @@ -196,16 +196,14 @@ void BlockDXT1::setIndices(int * idx) /// Flip DXT1 block vertically. inline void BlockDXT1::flip4() { - unsigned char tmp; - swap(row[0], row[3], tmp); - swap(row[1], row[2], tmp); + swap(row[0], row[3]); + swap(row[1], row[2]); } /// Flip half DXT1 block vertically. inline void BlockDXT1::flip2() { - unsigned char tmp; - swap(row[0], row[1], tmp); + swap(row[0], row[1]); } @@ -245,16 +243,14 @@ void AlphaBlockDXT3::decodeBlock(ColorBlock * block) const /// Flip DXT3 alpha block vertically. void AlphaBlockDXT3::flip4() { - unsigned short tmp; - swap(row[0], row[3], tmp); - swap(row[1], row[2], tmp); + swap(row[0], row[3]); + swap(row[1], row[2]); } /// Flip half DXT3 alpha block vertically. void AlphaBlockDXT3::flip2() { - unsigned short tmp; - swap(row[0], row[1], tmp); + swap(row[0], row[1]); } /// Flip DXT3 block vertically. @@ -276,9 +272,9 @@ void BlockDXT3::flip2() BlockDXT5 ----------------------------------------------------------------------------*/ -void AlphaBlockDXT5::evaluatePalette(unsigned char alpha[8]) const +void AlphaBlockDXT5::evaluatePalette(uint8 alpha[8]) const { - if (alpha0 > alpha1) { + if (alpha0() > alpha1()) { evaluatePalette8(alpha); } else { @@ -286,100 +282,100 @@ void AlphaBlockDXT5::evaluatePalette(unsigned char alpha[8]) const } } -void AlphaBlockDXT5::evaluatePalette8(unsigned char alpha[8]) const +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 * alpha0 + 1 * alpha1) / 7; // bit code 010 - alpha[3] = (5 * alpha0 + 2 * alpha1) / 7; // bit code 011 - alpha[4] = (4 * alpha0 + 3 * alpha1) / 7; // bit code 100 - alpha[5] = (3 * alpha0 + 4 * alpha1) / 7; // bit code 101 - alpha[6] = (2 * alpha0 + 5 * alpha1) / 7; // bit code 110 - alpha[7] = (1 * alpha0 + 6 * alpha1) / 7; // bit code 111 + 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(unsigned char alpha[8]) const +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 * alpha0 + 1 * alpha1) / 5; // Bit code 010 - alpha[3] = (3 * alpha0 + 2 * alpha1) / 5; // Bit code 011 - alpha[4] = (2 * alpha0 + 3 * alpha1) / 5; // Bit code 100 - alpha[5] = (1 * alpha0 + 4 * alpha1) / 5; // Bit code 101 + 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(unsigned char index_array[16]) const +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; + 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(); } -unsigned int AlphaBlockDXT5::index(unsigned int index) const +uint AlphaBlockDXT5::index(uint index) const { int offset = (3 * index + 16); - return (this->u >> offset) & 0x7; + return uint((this->u >> offset) & 0x7); } -void AlphaBlockDXT5::setIndex(unsigned int index, unsigned int value) +void AlphaBlockDXT5::setIndex(uint index, uint value) { int offset = (3 * index + 16); - unsigned long long mask = ((unsigned long long)(0x7)) << offset; - this->u = (this->u & ~mask) | (((unsigned long long)(value)) << offset); + uint64 mask = uint64(0x7) << offset; + this->u = (this->u & ~mask) | (uint64(value) << offset); } void AlphaBlockDXT5::decodeBlock(ColorBlock * block) const { - unsigned char alpha_array[8]; + uint8 alpha_array[8]; evaluatePalette(alpha_array); - unsigned char index_array[16]; + uint8 index_array[16]; indices(index_array); - for(unsigned int i = 0; i < 16; i++) { + for(uint i = 0; i < 16; i++) { block->color(i).a = alpha_array[index_array[i]]; } } void AlphaBlockDXT5::flip4() { - unsigned long long * b = (unsigned long long *)this; + uint64 * b = (uint64 *)this; // @@ The masks might have to be byte swapped. - unsigned long long tmp = (*b & (unsigned long long)(0x000000000000FFFFLL)); - tmp |= (*b & (unsigned long long)(0x000000000FFF0000LL)) << 36; - tmp |= (*b & (unsigned long long)(0x000000FFF0000000LL)) << 12; - tmp |= (*b & (unsigned long long)(0x000FFF0000000000LL)) >> 12; - tmp |= (*b & (unsigned long long)(0xFFF0000000000000LL)) >> 36; + 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() { - unsigned int * b = (unsigned int *)this; + uint * b = (uint *)this; // @@ The masks might have to be byte swapped. - unsigned int tmp = (*b & 0xFF000000); + uint tmp = (*b & 0xFF000000); tmp |= (*b & 0x00000FFF) << 12; tmp |= (*b & 0x00FFF000) >> 12; @@ -393,6 +389,7 @@ void BlockDXT5::decodeBlock(ColorBlock * block) const // Decode alpha. alpha.decodeBlock(block); + } /// Flip DXT5 block vertically. @@ -413,13 +410,13 @@ void BlockDXT5::flip2() /// Decode ATI1 block. void BlockATI1::decodeBlock(ColorBlock * block) const { - unsigned char alpha_array[8]; + uint8 alpha_array[8]; alpha.evaluatePalette(alpha_array); - unsigned char index_array[16]; + uint8 index_array[16]; alpha.indices(index_array); - for(unsigned int i = 0; i < 16; i++) { + 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; @@ -442,13 +439,13 @@ void BlockATI1::flip2() /// Decode ATI2 block. void BlockATI2::decodeBlock(ColorBlock * block) const { - unsigned char alpha_array[8]; - unsigned char index_array[16]; + uint8 alpha_array[8]; + uint8 index_array[16]; x.evaluatePalette(alpha_array); x.indices(index_array); - for(unsigned int i = 0; i < 16; i++) { + for(uint i = 0; i < 16; i++) { Color32 & c = block->color(i); c.r = alpha_array[index_array[i]]; } @@ -456,7 +453,7 @@ void BlockATI2::decodeBlock(ColorBlock * block) const y.evaluatePalette(alpha_array); y.indices(index_array); - for(unsigned int i = 0; i < 16; i++) { + for(uint i = 0; i < 16; i++) { Color32 & c = block->color(i); c.g = alpha_array[index_array[i]]; c.b = 0; @@ -478,6 +475,68 @@ void BlockATI2::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); @@ -518,3 +577,12 @@ void mem_read(Stream & mem, BlockATI2 & block) 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 index 8381c4705ae..3f9a81e40c8 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -55,6 +55,7 @@ #ifndef _DDS_BLOCKDXT_H #define _DDS_BLOCKDXT_H +#include <Common.h> #include <Color.h> #include <ColorBlock.h> #include <Stream.h> @@ -65,14 +66,14 @@ struct BlockDXT1 Color16 col0; Color16 col1; union { - unsigned char row[4]; - unsigned int indices; + uint8 row[4]; + uint indices; }; bool isFourColorMode() const; - unsigned int evaluatePalette(Color32 color_array[4]) const; - unsigned int evaluatePaletteFast(Color32 color_array[4]) 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; @@ -87,7 +88,7 @@ struct BlockDXT1 /// Return true if the block uses four color mode, false otherwise. inline bool BlockDXT1::isFourColorMode() const { - return col0.u >= col1.u; // @@ > or >= ? + return col0.u > col1.u; } @@ -96,24 +97,24 @@ struct AlphaBlockDXT3 { union { struct { - unsigned int alpha0 : 4; - unsigned int alpha1 : 4; - unsigned int alpha2 : 4; - unsigned int alpha3 : 4; - unsigned int alpha4 : 4; - unsigned int alpha5 : 4; - unsigned int alpha6 : 4; - unsigned int alpha7 : 4; - unsigned int alpha8 : 4; - unsigned int alpha9 : 4; - unsigned int alphaA : 4; - unsigned int alphaB : 4; - unsigned int alphaC : 4; - unsigned int alphaD : 4; - unsigned int alphaE : 4; - unsigned int alphaF : 4; + 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; }; - unsigned short row[4]; + uint16 row[4]; }; void decodeBlock(ColorBlock * block) const; @@ -139,37 +140,59 @@ struct BlockDXT3 /// DXT5 alpha block. struct AlphaBlockDXT5 { + // uint64 unions do not compile on all platforms + /* 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 alpha0 : 8; // 8 + uint64 alpha1 : 8; // 16 + uint64 bits0 : 3; // 3 - 19 + uint64 bits1 : 3; // 6 - 22 + uint64 bits2 : 3; // 9 - 25 + uint64 bits3 : 3; // 12 - 28 + uint64 bits4 : 3; // 15 - 31 + uint64 bits5 : 3; // 18 - 34 + uint64 bits6 : 3; // 21 - 37 + uint64 bits7 : 3; // 24 - 40 + uint64 bits8 : 3; // 27 - 43 + uint64 bits9 : 3; // 30 - 46 + uint64 bitsA : 3; // 33 - 49 + uint64 bitsB : 3; // 36 - 52 + uint64 bitsC : 3; // 39 - 55 + uint64 bitsD : 3; // 42 - 58 + uint64 bitsE : 3; // 45 - 61 + uint64 bitsF : 3; // 48 - 64 }; - unsigned long long u; + uint64 u; }; + */ + uint64 u; + uint8 alpha0() const { return u & 0xffLL; }; + uint8 alpha1() const { return (u >> 8) & 0xffLL; }; + uint8 bits0() const { return (u >> 16) & 0x7LL; }; + uint8 bits1() const { return (u >> 19) & 0x7LL; }; + uint8 bits2() const { return (u >> 22) & 0x7LL; }; + uint8 bits3() const { return (u >> 25) & 0x7LL; }; + uint8 bits4() const { return (u >> 28) & 0x7LL; }; + uint8 bits5() const { return (u >> 31) & 0x7LL; }; + uint8 bits6() const { return (u >> 34) & 0x7LL; }; + uint8 bits7() const { return (u >> 37) & 0x7LL; }; + uint8 bits8() const { return (u >> 40) & 0x7LL; }; + uint8 bits9() const { return (u >> 43) & 0x7LL; }; + uint8 bitsA() const { return (u >> 46) & 0x7LL; }; + uint8 bitsB() const { return (u >> 49) & 0x7LL; }; + uint8 bitsC() const { return (u >> 52) & 0x7LL; }; + uint8 bitsD() const { return (u >> 55) & 0x7LL; }; + uint8 bitsE() const { return (u >> 58) & 0x7LL; }; + uint8 bitsF() const { return (u >> 61) & 0x7LL; }; - void evaluatePalette(unsigned char alpha[8]) const; - void evaluatePalette8(unsigned char alpha[8]) const; - void evaluatePalette6(unsigned char alpha[8]) const; - void indices(unsigned char index_array[16]) const; + 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; - unsigned int index(unsigned int index) const; - void setIndex(unsigned int index, unsigned int value); + uint index(uint index) const; + void setIndex(uint index, uint value); void decodeBlock(ColorBlock * block) const; @@ -213,6 +236,25 @@ struct BlockATI2 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); @@ -220,5 +262,6 @@ 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/CMakeLists.txt b/source/blender/imbuf/intern/dds/CMakeLists.txt new file mode 100644 index 00000000000..842f53bd88b --- /dev/null +++ b/source/blender/imbuf/intern/dds/CMakeLists.txt @@ -0,0 +1,45 @@ +# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $ +# ***** 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) 2006, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): +# +# ***** END GPL LICENSE BLOCK ***** + +FILE (GLOB SRC *.cpp) + +SET(INC + . + ../../../blenkernel + ../../../makesdna + ../../ + .. + ../../../blenlib + intern/include + ../../../../../intern/guardedalloc +) + +if(WITH_DDS) + ADD_DEFINITIONS(-DWITH_DDS) +ENDIF(WITH_DDS) + +BLENDERLIB(bf_dds "${SRC}" "${INC}") +#env.BlenderLib ('bf_dds', source_files, incs, defs, libtype=['core','player'], priority = [90, 200]) diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index 2511f6b8b30..043fba9d675 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -36,13 +36,13 @@ #include <Common.h> // Get approximate luminance. - inline static unsigned int colorLuminance(Color32 c) + inline static uint colorLuminance(Color32 c) { return c.r + c.g + c.b; } // Get the euclidean distance between the given colors. - inline static unsigned int colorDistance(Color32 c0, Color32 c1) + 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); } @@ -53,25 +53,33 @@ ColorBlock::ColorBlock() { } +/// Init the color block from an array of colors. +ColorBlock::ColorBlock(const uint * linearImage) +{ + for(uint i = 0; i < 16; i++) { + color(i) = Color32(linearImage[i]); + } +} + /// Init the color block with the contents of the given block. ColorBlock::ColorBlock(const ColorBlock & block) { - for(unsigned int i = 0; i < 16; i++) { + for(uint i = 0; i < 16; i++) { color(i) = block.color(i); } } /// Initialize this color block. -ColorBlock::ColorBlock(const Image * img, unsigned int x, unsigned int y) +ColorBlock::ColorBlock(const Image * img, uint x, uint y) { init(img, x, y); } -void ColorBlock::init(const Image * img, unsigned int x, unsigned int y) +void ColorBlock::init(const Image * img, uint x, uint y) { - const unsigned int bw = min(img->width() - x, 4U); - const unsigned int bh = min(img->height() - y, 4U); + const uint bw = min(img->width() - x, 4U); + const uint bh = min(img->height() - y, 4U); static int remainder[] = { 0, 0, 0, 0, @@ -83,10 +91,10 @@ void ColorBlock::init(const Image * img, unsigned int x, unsigned int y) // 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(unsigned int i = 0; i < 4; i++) { + for(uint i = 0; i < 4; i++) { //const int by = i % bh; const int by = remainder[(bh - 1) * 4 + i]; - for(unsigned int e = 0; e < 4; e++) { + 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); @@ -100,7 +108,7 @@ 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); + m_color[i] = Color32(0xFF, c.g, 0, c.r); } } @@ -108,7 +116,7 @@ void ColorBlock::splatX() { for(int i = 0; i < 16; i++) { - unsigned char x = m_color[i].r; + uint8 x = m_color[i].r; m_color[i] = Color32(x, x, x, x); } } @@ -117,16 +125,56 @@ void ColorBlock::splatY() { for(int i = 0; i < 16; i++) { - unsigned char y = m_color[i].g; + uint8 y = m_color[i].g; m_color[i] = Color32(y, y, y, y); } } +/// Returns true if the block has a single color. +bool ColorBlock::isSingleColor() const +{ + Color32 mask(0xFF, 0xFF, 0xFF, 0x00); + uint u = m_color[0].u & mask.u; + + for(int i = 1; i < 16; i++) + { + if (u != (m_color[i].u & mask.u)) + { + return false; + } + } + + return true; +} + +/// Returns true if the block has a single color, ignoring transparent pixels. +bool ColorBlock::isSingleColorNoAlpha() const +{ + Color32 c; + int i; + for(i = 0; i < 16; i++) + { + if (m_color[i].a != 0) c = m_color[i]; + } + + Color32 mask(0xFF, 0xFF, 0xFF, 0x00); + uint u = c.u & mask.u; + + for(; i < 16; i++) + { + if (u != (m_color[i].u & mask.u)) + { + return false; + } + } + + return true; +} /// Count number of unique colors in this color block. -unsigned int ColorBlock::countUniqueColors() const +uint ColorBlock::countUniqueColors() const { - unsigned int count = 0; + uint count = 0; // @@ This does not have to be o(n^2) for(int i = 0; i < 16; i++) @@ -149,17 +197,27 @@ unsigned int ColorBlock::countUniqueColors() const /// Get average color of the block. Color32 ColorBlock::averageColor() const { - unsigned int r, g, b, a; + uint r, g, b, a; r = g = b = a = 0; - for(unsigned int i = 0; i < 16; i++) { + 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((unsigned char)(r / 16), (unsigned char)(g / 16), (unsigned char)(b / 16), (unsigned char)(a / 16)); + 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; } @@ -167,11 +225,11 @@ Color32 ColorBlock::averageColor() const void ColorBlock::diameterRange(Color32 * start, Color32 * end) const { Color32 c0, c1; - unsigned int best_dist = 0; + uint best_dist = 0; for(int i = 0; i < 16; i++) { for (int j = i+1; j < 16; j++) { - unsigned int dist = colorDistance(m_color[i], m_color[j]); + uint dist = colorDistance(m_color[i], m_color[j]); if( dist > best_dist ) { best_dist = dist; c0 = m_color[i]; @@ -188,13 +246,13 @@ void ColorBlock::diameterRange(Color32 * start, Color32 * end) const void ColorBlock::luminanceRange(Color32 * start, Color32 * end) const { Color32 minColor, maxColor; - unsigned int minLuminance, maxLuminance; + uint minLuminance, maxLuminance; maxLuminance = minLuminance = colorLuminance(m_color[0]); - for(unsigned int i = 1; i < 16; i++) + for(uint i = 1; i < 16; i++) { - unsigned int luminance = colorLuminance(m_color[i]); + uint luminance = colorLuminance(m_color[i]); if (luminance > maxLuminance) { maxLuminance = luminance; @@ -216,7 +274,7 @@ void ColorBlock::boundsRange(Color32 * start, Color32 * end) const Color32 minColor(255, 255, 255); Color32 maxColor(0, 0, 0); - for(unsigned int i = 0; i < 16; i++) + 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; } @@ -250,7 +308,7 @@ void ColorBlock::boundsRangeAlpha(Color32 * start, Color32 * end) const Color32 minColor(255, 255, 255, 255); Color32 maxColor(0, 0, 0, 0); - for(unsigned int i = 0; i < 16; i++) + 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; } @@ -287,11 +345,11 @@ void ColorBlock::boundsRangeAlpha(Color32 * start, Color32 * end) const void ColorBlock::sortColorsByAbsoluteValue() { // Dummy selection sort. - for( unsigned int a = 0; a < 16; a++ ) { - unsigned int max = a; + for( uint a = 0; a < 16; a++ ) { + uint max = a; Color16 cmax(m_color[a]); - for( unsigned int b = a+1; b < 16; b++ ) { + for( uint b = a+1; b < 16; b++ ) { Color16 cb(m_color[b]); if( cb.u > cmax.u ) { @@ -299,9 +357,6 @@ void ColorBlock::sortColorsByAbsoluteValue() cmax = cb; } } - Color32 tmp; - swap( m_color[a], m_color[max], tmp ); + 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 index 0d195f73811..537c17346a1 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -41,23 +41,26 @@ struct ColorBlock { ColorBlock(); + ColorBlock(const uint * linearImage); ColorBlock(const ColorBlock & block); - ColorBlock(const Image * img, unsigned int x, unsigned int y); + ColorBlock(const Image * img, uint x, uint y); - void init(const Image * img, unsigned int x, unsigned int y); + void init(const Image * img, uint x, uint y); void swizzleDXT5n(); void splatX(); void splatY(); - unsigned int countUniqueColors() const; + bool isSingleColor() const; + bool isSingleColorNoAlpha() const; + 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(); @@ -66,11 +69,11 @@ struct ColorBlock // Accessors const Color32 * colors() const; - Color32 color(unsigned int i) const; - Color32 & color(unsigned int i); + Color32 color(uint i) const; + Color32 & color(uint i); - Color32 color(unsigned int x, unsigned int y) const; - Color32 & color(unsigned int x, unsigned int y); + Color32 color(uint x, uint y) const; + Color32 & color(uint x, uint y); private: @@ -86,25 +89,25 @@ inline const Color32 * ColorBlock::colors() const } /// Get block color. -inline Color32 ColorBlock::color(unsigned int i) const +inline Color32 ColorBlock::color(uint i) const { return m_color[i]; } /// Get block color. -inline Color32 & ColorBlock::color(unsigned int i) +inline Color32 & ColorBlock::color(uint i) { return m_color[i]; } /// Get block color. -inline Color32 ColorBlock::color(unsigned int x, unsigned int y) const +inline Color32 ColorBlock::color(uint x, uint y) const { return m_color[y * 4 + x]; } /// Get block color. -inline Color32 & ColorBlock::color(unsigned int x, unsigned int y) +inline Color32 & ColorBlock::color(uint x, uint y) { return m_color[y * 4 + x]; } diff --git a/source/blender/imbuf/intern/dds/Common.h b/source/blender/imbuf/intern/dds/Common.h index e504e7b1241..6f09346f770 100644 --- a/source/blender/imbuf/intern/dds/Common.h +++ b/source/blender/imbuf/intern/dds/Common.h @@ -34,8 +34,20 @@ #ifndef clamp #define clamp(x,a,b) min(max((x), (a)), (b)) #endif -#ifndef swap -#define swap(a,b,tmp) tmp=a; a=b; b=tmp; -#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 index f8eb7afa66b..0981ae88db6 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -52,103 +52,374 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. -#include <Common.h> #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) \ - ((unsigned int)((unsigned char)(ch0)) | \ - ((unsigned int)((unsigned char)(ch1)) << 8) | \ - ((unsigned int)((unsigned char)(ch2)) << 16) | \ - ((unsigned int)((unsigned char)(ch3)) << 24 )) + ((uint)((unsigned char)(ch0)) | \ + ((uint)((unsigned char)(ch1)) << 8) | \ + ((uint)((unsigned char)(ch2)) << 16) | \ + ((uint)((unsigned char)(ch3)) << 24 )) #endif -static const unsigned int FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' '); -static const unsigned int FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'); -static const unsigned int FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'); -static const unsigned int FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'); -static const unsigned int FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'); -static const unsigned int FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'); -static const unsigned int FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B'); -static const unsigned int FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1'); -static const unsigned int FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2'); - -// RGB formats. -static const unsigned int D3DFMT_R8G8B8 = 20; -static const unsigned int D3DFMT_A8R8G8B8 = 21; -static const unsigned int D3DFMT_X8R8G8B8 = 22; -static const unsigned int D3DFMT_R5G6B5 = 23; -static const unsigned int D3DFMT_X1R5G5B5 = 24; -static const unsigned int D3DFMT_A1R5G5B5 = 25; -static const unsigned int D3DFMT_A4R4G4B4 = 26; -static const unsigned int D3DFMT_R3G3B2 = 27; -static const unsigned int D3DFMT_A8 = 28; -static const unsigned int D3DFMT_A8R3G3B2 = 29; -static const unsigned int D3DFMT_X4R4G4B4 = 30; -static const unsigned int D3DFMT_A2B10G10R10 = 31; -static const unsigned int D3DFMT_A8B8G8R8 = 32; -static const unsigned int D3DFMT_X8B8G8R8 = 33; -static const unsigned int D3DFMT_G16R16 = 34; -static const unsigned int D3DFMT_A2R10G10B10 = 35; -static const unsigned int D3DFMT_A16B16G16R16 = 36; +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'); + +static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y'); + +static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0'); + +// 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 unsigned int D3DFMT_A8P8 = 40; -static const unsigned int D3DFMT_P8 = 41; +static const uint D3DFMT_A8P8 = 40; +static const uint D3DFMT_P8 = 41; // Luminance formats. -static const unsigned int D3DFMT_L8 = 50; -static const unsigned int D3DFMT_A8L8 = 51; -static const unsigned int D3DFMT_A4L4 = 52; +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 unsigned int D3DFMT_R16F = 111; -static const unsigned int D3DFMT_G16R16F = 112; -static const unsigned int D3DFMT_A16B16G16R16F = 113; -static const unsigned int D3DFMT_R32F = 114; -static const unsigned int D3DFMT_G32R32F = 115; -static const unsigned int D3DFMT_A32B32G32R32F = 116; - -static const unsigned int DDSD_CAPS = 0x00000001U; -static const unsigned int DDSD_PIXELFORMAT = 0x00001000U; -static const unsigned int DDSD_WIDTH = 0x00000004U; -static const unsigned int DDSD_HEIGHT = 0x00000002U; -static const unsigned int DDSD_PITCH = 0x00000008U; -static const unsigned int DDSD_MIPMAPCOUNT = 0x00020000U; -static const unsigned int DDSD_LINEARSIZE = 0x00080000U; -static const unsigned int DDSD_DEPTH = 0x00800000U; - -static const unsigned int DDSCAPS_COMPLEX = 0x00000008U; -static const unsigned int DDSCAPS_TEXTURE = 0x00001000U; -static const unsigned int DDSCAPS_MIPMAP = 0x00400000U; -static const unsigned int DDSCAPS2_VOLUME = 0x00200000U; -static const unsigned int DDSCAPS2_CUBEMAP = 0x00000200U; - -static const unsigned int DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U; -static const unsigned int DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U; -static const unsigned int DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U; -static const unsigned int DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U; -static const unsigned int DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U; -static const unsigned int DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U; -static const unsigned int DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000FC00U; - -static const unsigned int DDPF_ALPHAPIXELS = 0x00000001U; -static const unsigned int DDPF_ALPHA = 0x00000002U; -static const unsigned int DDPF_FOURCC = 0x00000004U; -static const unsigned int DDPF_RGB = 0x00000040U; -static const unsigned int DDPF_PALETTEINDEXED1 = 0x00000800U; -static const unsigned int DDPF_PALETTEINDEXED2 = 0x00001000U; -static const unsigned int DDPF_PALETTEINDEXED4 = 0x00000008U; -static const unsigned int DDPF_PALETTEINDEXED8 = 0x00000020U; -static const unsigned int DDPF_LUMINANCE = 0x00020000U; -static const unsigned int DDPF_ALPHAPREMULT = 0x00008000U; -static const unsigned int DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag. +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, + }; + + + const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat) + { +#define CASE(format) case DXGI_FORMAT_##format: return #format + switch(dxgiFormat) + { + CASE(UNKNOWN); + + CASE(R32G32B32A32_TYPELESS); + CASE(R32G32B32A32_FLOAT); + CASE(R32G32B32A32_UINT); + CASE(R32G32B32A32_SINT); + + CASE(R32G32B32_TYPELESS); + CASE(R32G32B32_FLOAT); + CASE(R32G32B32_UINT); + CASE(R32G32B32_SINT); + + CASE(R16G16B16A16_TYPELESS); + CASE(R16G16B16A16_FLOAT); + CASE(R16G16B16A16_UNORM); + CASE(R16G16B16A16_UINT); + CASE(R16G16B16A16_SNORM); + CASE(R16G16B16A16_SINT); + + CASE(R32G32_TYPELESS); + CASE(R32G32_FLOAT); + CASE(R32G32_UINT); + CASE(R32G32_SINT); + + CASE(R32G8X24_TYPELESS); + CASE(D32_FLOAT_S8X24_UINT); + CASE(R32_FLOAT_X8X24_TYPELESS); + CASE(X32_TYPELESS_G8X24_UINT); + + CASE(R10G10B10A2_TYPELESS); + CASE(R10G10B10A2_UNORM); + CASE(R10G10B10A2_UINT); + + CASE(R11G11B10_FLOAT); + + CASE(R8G8B8A8_TYPELESS); + CASE(R8G8B8A8_UNORM); + CASE(R8G8B8A8_UNORM_SRGB); + CASE(R8G8B8A8_UINT); + CASE(R8G8B8A8_SNORM); + CASE(R8G8B8A8_SINT); + + CASE(R16G16_TYPELESS); + CASE(R16G16_FLOAT); + CASE(R16G16_UNORM); + CASE(R16G16_UINT); + CASE(R16G16_SNORM); + CASE(R16G16_SINT); + + CASE(R32_TYPELESS); + CASE(D32_FLOAT); + CASE(R32_FLOAT); + CASE(R32_UINT); + CASE(R32_SINT); + + CASE(R24G8_TYPELESS); + CASE(D24_UNORM_S8_UINT); + CASE(R24_UNORM_X8_TYPELESS); + CASE(X24_TYPELESS_G8_UINT); + + CASE(R8G8_TYPELESS); + CASE(R8G8_UNORM); + CASE(R8G8_UINT); + CASE(R8G8_SNORM); + CASE(R8G8_SINT); + + CASE(R16_TYPELESS); + CASE(R16_FLOAT); + CASE(D16_UNORM); + CASE(R16_UNORM); + CASE(R16_UINT); + CASE(R16_SNORM); + CASE(R16_SINT); + + CASE(R8_TYPELESS); + CASE(R8_UNORM); + CASE(R8_UINT); + CASE(R8_SNORM); + CASE(R8_SINT); + CASE(A8_UNORM); + + CASE(R1_UNORM); + + CASE(R9G9B9E5_SHAREDEXP); + + CASE(R8G8_B8G8_UNORM); + CASE(G8R8_G8B8_UNORM); + + CASE(BC1_TYPELESS); + CASE(BC1_UNORM); + CASE(BC1_UNORM_SRGB); + + CASE(BC2_TYPELESS); + CASE(BC2_UNORM); + CASE(BC2_UNORM_SRGB); + + CASE(BC3_TYPELESS); + CASE(BC3_UNORM); + CASE(BC3_UNORM_SRGB); + + CASE(BC4_TYPELESS); + CASE(BC4_UNORM); + CASE(BC4_SNORM); + + CASE(BC5_TYPELESS); + CASE(BC5_UNORM); + CASE(BC5_SNORM); + + CASE(B5G6R5_UNORM); + CASE(B5G5R5A1_UNORM); + CASE(B8G8R8A8_UNORM); + CASE(B8G8R8X8_UNORM); + + default: + return "UNKNOWN"; + } +#undef CASE + } + + const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) + { + switch(resourceDimension) + { + default: + case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN"; + case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER"; + case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D"; + } + } /*** implementation ***/ @@ -172,6 +443,15 @@ void mem_read(Stream & mem, DDSCaps & caps) 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); @@ -182,12 +462,19 @@ void mem_read(Stream & mem, DDSHeader & header) mem_read(mem, header.pitch); mem_read(mem, header.depth); mem_read(mem, header.mipmapcount); - for (unsigned int i = 0; i < 11; i++) mem_read(mem, header.reserved[i]); + 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; @@ -198,11 +485,11 @@ DDSHeader::DDSHeader() this->pitch = 0; this->depth = 0; this->mipmapcount = 0; - for (unsigned int i = 0; i < 11; i++) this->reserved[i] = 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) | (3); // major.minor.revision + this->reserved[10] = (0 << 16) | (9 << 8) | (5); // major.minor.revision this->pf.size = 32; this->pf.flags = 0; @@ -217,29 +504,35 @@ DDSHeader::DDSHeader() 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(unsigned int w) +void DDSHeader::setWidth(uint w) { this->flags |= DDSD_WIDTH; this->width = w; } -void DDSHeader::setHeight(unsigned int h) +void DDSHeader::setHeight(uint h) { this->flags |= DDSD_HEIGHT; this->height = h; } -void DDSHeader::setDepth(unsigned int d) +void DDSHeader::setDepth(uint d) { this->flags |= DDSD_DEPTH; this->height = d; } -void DDSHeader::setMipmapCount(unsigned int count) +void DDSHeader::setMipmapCount(uint count) { - if (count == 0) + if (count == 0 || count == 1) { this->flags &= ~DDSD_MIPMAPCOUNT; this->mipmapcount = 0; @@ -262,47 +555,61 @@ void DDSHeader::setMipmapCount(unsigned int count) void DDSHeader::setTexture2D() { - // nothing to do here. + 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(unsigned int size) +void DDSHeader::setLinearSize(uint size) { this->flags &= ~DDSD_PITCH; this->flags |= DDSD_LINEARSIZE; this->pitch = size; } -void DDSHeader::setPitch(unsigned int pitch) +void DDSHeader::setPitch(uint pitch) { this->flags &= ~DDSD_LINEARSIZE; this->flags |= DDSD_PITCH; this->pitch = pitch; } -void DDSHeader::setFourCC(unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3) +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; + + if (this->pf.fourcc == FOURCC_ATI2) + { + this->pf.bitcount = FOURCC_A2XY; + } + else + { + this->pf.bitcount = 0; + } + this->pf.rmask = 0; this->pf.gmask = 0; this->pf.bmask = 0; this->pf.amask = 0; } -void DDSHeader::setPixelFormat(unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask) +void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask) { // Make sure the masks are correct. if ((rmask & gmask) || \ @@ -324,15 +631,25 @@ void DDSHeader::setPixelFormat(unsigned int bitcount, unsigned int rmask, unsign if (bitcount == 0) { // Compute bit count from the masks. - unsigned int total = rmask | gmask | bmask | amask; + uint total = rmask | gmask | bmask | amask; while(total != 0) { bitcount++; total >>= 1; } - // @@ Align to 8? } - this->pf.fourcc = 0; + 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; @@ -340,48 +657,33 @@ void DDSHeader::setPixelFormat(unsigned int bitcount, unsigned int rmask, unsign this->pf.amask = amask; } +void DDSHeader::setDX10Format(uint format) +{ + //this->pf.flags = 0; + this->pf.fourcc = FOURCC_DX10; + this->header10.dxgiFormat = format; +} + void DDSHeader::setNormalFlag(bool b) { if (b) this->pf.flags |= DDPF_NORMAL; else this->pf.flags &= ~DDPF_NORMAL; } -/* -void DDSHeader::swapBytes() +bool DDSHeader::hasDX10Header() const { - this->fourcc = POSH_LittleU32(this->fourcc); - this->size = POSH_LittleU32(this->size); - this->flags = POSH_LittleU32(this->flags); - this->height = POSH_LittleU32(this->height); - this->width = POSH_LittleU32(this->width); - this->pitch = POSH_LittleU32(this->pitch); - this->depth = POSH_LittleU32(this->depth); - this->mipmapcount = POSH_LittleU32(this->mipmapcount); - - for(int i = 0; i < 11; i++) { - this->reserved[i] = POSH_LittleU32(this->reserved[i]); - } - - this->pf.size = POSH_LittleU32(this->pf.size); - this->pf.flags = POSH_LittleU32(this->pf.flags); - this->pf.fourcc = POSH_LittleU32(this->pf.fourcc); - this->pf.bitcount = POSH_LittleU32(this->pf.bitcount); - this->pf.rmask = POSH_LittleU32(this->pf.rmask); - this->pf.gmask = POSH_LittleU32(this->pf.gmask); - this->pf.bmask = POSH_LittleU32(this->pf.bmask); - this->pf.amask = POSH_LittleU32(this->pf.amask); - this->caps.caps1 = POSH_LittleU32(this->caps.caps1); - this->caps.caps2 = POSH_LittleU32(this->caps.caps2); - this->caps.caps3 = POSH_LittleU32(this->caps.caps3); - this->caps.caps4 = POSH_LittleU32(this->caps.caps4); - this->notused = POSH_LittleU32(this->notused); + return this->pf.fourcc == FOURCC_DX10; // @@ This is according to AMD + //return this->pf.flags == 0; // @@ This is according to MS } -*/ - -DirectDrawSurface::DirectDrawSurface(unsigned char *mem, unsigned int size) : stream(mem, size), header() +DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header() { mem_read(stream, header); + + // some ATI2 compressed normal maps do not have their + // normal flag set, so force it here (the original nvtt don't do + // this, but the decompressor has a -forcenormal flag) + if (header.pf.fourcc == FOURCC_ATI2) header.setNormalFlag(true); } DirectDrawSurface::~DirectDrawSurface() @@ -395,7 +697,7 @@ bool DirectDrawSurface::isValid() const return false; } - const unsigned int required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT); + const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/); if( (header.flags & required) != required ) { return false; } @@ -416,78 +718,72 @@ bool DirectDrawSurface::isValid() const bool DirectDrawSurface::isSupported() const { - if (header.pf.flags & DDPF_FOURCC) + if (header.hasDX10Header()) { - 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) + else { - if (header.pf.bitcount == 24) + if (header.pf.flags & DDPF_FOURCC) { - return true; + 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.bitcount == 32) + else if (header.pf.flags & DDPF_RGB) { - return true; + // All RGB formats are supported now. } else { - // Unsupported pixel format. return false; } - } - else - { - return false; - } - - if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) - { - // Cubemaps must contain all faces. - 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; + if (isTexture3D()) + { + // @@ 3D textures not supported yet. + return false; + } } return true; } -unsigned int DirectDrawSurface::mipmapCount() const +uint DirectDrawSurface::mipmapCount() const { if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount; - else return 0; + else return 1; } -unsigned int DirectDrawSurface::width() const +uint DirectDrawSurface::width() const { if (header.flags & DDSD_WIDTH) return header.width; else return 1; } -unsigned int DirectDrawSurface::height() const +uint DirectDrawSurface::height() const { if (header.flags & DDSD_HEIGHT) return header.height; else return 1; } -unsigned int DirectDrawSurface::depth() const +uint DirectDrawSurface::depth() const { if (header.flags & DDSD_DEPTH) return header.depth; else return 1; @@ -509,14 +805,37 @@ bool DirectDrawSurface::hasAlpha() const } } +bool DirectDrawSurface::isTexture1D() const +{ + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D; + } + return false; +} + bool DirectDrawSurface::isTexture2D() const { - return !isTexture3D() && !isTextureCube(); + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D; + } + else + { + return !isTexture3D() && !isTextureCube(); + } } bool DirectDrawSurface::isTexture3D() const { + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D; + } + else + { return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0; + } } bool DirectDrawSurface::isTextureCube() const @@ -524,18 +843,23 @@ bool DirectDrawSurface::isTextureCube() const return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } -void DirectDrawSurface::mipmap(Image * img, unsigned int face, unsigned int mipmap) +void DirectDrawSurface::setNormalFlag(bool b) +{ + header.setNormalFlag(b); +} + +void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) { stream.seek(offset(face, mipmap)); - unsigned int w = width(); - unsigned int h = height(); + uint w = width(); + uint h = height(); // Compute width and height. - for (unsigned int m = 0; m < mipmap; m++) + for (uint m = 0; m < mipmap; m++) { - w = max(w/2, 1U); - h = max(h/2, 1U); + w = max(1U, w / 2); + h = max(1U, h / 2); } img->allocate(w, h); @@ -550,94 +874,57 @@ void DirectDrawSurface::mipmap(Image * img, unsigned int face, unsigned int mipm } } -/* helper function for readLinearImage */ -void maskShiftAndSize(unsigned int mask, unsigned int * shift, unsigned int * 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; - } -} - -/* helper function for readLinearImage */ -unsigned int convert(unsigned int c, unsigned int inbits, unsigned int outbits) -{ - if (inbits == 0) { - return 0; - } - else if (inbits == outbits) - { - return c; - } - else if (inbits > outbits) - { - // truncate - return c >> (inbits - outbits); - } - else - { - // bitexpand - return (c << (outbits - inbits)) | convert(c, inbits, outbits - inbits); - } -} - void DirectDrawSurface::readLinearImage(Image * img) { - const unsigned int w = img->width(); - const unsigned int h = img->height(); - - unsigned int rshift, rsize; - maskShiftAndSize(header.pf.rmask, &rshift, &rsize); - unsigned int gshift, gsize; - maskShiftAndSize(header.pf.gmask, &gshift, &gsize); + const uint w = img->width(); + const uint h = img->height(); + + uint rshift, rsize; + PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize); - unsigned int bshift, bsize; - maskShiftAndSize(header.pf.bmask, &bshift, &bsize); + uint gshift, gsize; + PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize); - unsigned int ashift, asize; - maskShiftAndSize(header.pf.amask, &ashift, &asize); + 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; - unsigned int 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 (file corrupt?)"); + printf("DDS: bitcount too large"); return; } - if (header.pf.amask != 0) + // set image format: RGB or ARGB + // alpha channel exists if and only if the alpha mask is non-zero + if (header.pf.amask == 0) + { + img->setFormat(Image::Format_RGB); + } + else { img->setFormat(Image::Format_ARGB); } // Read linear RGB images. - for (unsigned int y = 0; y < h; y++) + for (uint y = 0; y < h; y++) { - for (unsigned int x = 0; x < w; x++) + for (uint x = 0; x < w; x++) { - unsigned int c = 0; + uint c = 0; mem_read(stream, (unsigned char *)(&c), byteCount); Color32 pixel(0, 0, 0, 0xFF); - pixel.r = convert(c >> rshift, rsize, 8); - pixel.g = convert(c >> gshift, gsize, 8); - pixel.b = convert(c >> bshift, bsize, 8); - pixel.a = convert(c >> ashift, asize, 8); + 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; } @@ -646,15 +933,29 @@ void DirectDrawSurface::readLinearImage(Image * img) void DirectDrawSurface::readBlockImage(Image * img) { - const unsigned int w = img->width(); - const unsigned int h = img->height(); + + // set image format: RGB or ARGB + if (header.pf.fourcc == FOURCC_RXGB || + header.pf.fourcc == FOURCC_ATI1 || + header.pf.fourcc == FOURCC_ATI2 || + header.pf.flags & DDPF_NORMAL) + { + img->setFormat(Image::Format_RGB); + } + else + { + img->setFormat(Image::Format_ARGB); + } + + const uint w = img->width(); + const uint h = img->height(); - const unsigned int bw = (w + 3) / 4; - const unsigned int bh = (h + 3) / 4; + const uint bw = (w + 3) / 4; + const uint bh = (h + 3) / 4; - for (unsigned int by = 0; by < bh; by++) + for (uint by = 0; by < bh; by++) { - for (unsigned int bx = 0; bx < bw; bx++) + for (uint bx = 0; bx < bw; bx++) { ColorBlock block; @@ -662,9 +963,9 @@ void DirectDrawSurface::readBlockImage(Image * img) readBlock(&block); // Write color block. - for (unsigned int y = 0; y < min(4U, h-4*by); y++) + for (uint y = 0; y < min(4U, h-4*by); y++) { - for (unsigned int x = 0; x < min(4U, w-4*bx); x++) + for (uint x = 0; x < min(4U, w-4*bx); x++) { img->pixel(4*bx+x, 4*by+y) = block.color(x, y); } @@ -673,12 +974,13 @@ void DirectDrawSurface::readBlockImage(Image * img) } } -static Color32 buildNormal(unsigned char x, unsigned char y) +static Color32 buildNormal(uint8 x, uint8 y) { - float nx = 2 * (x / 255) - 1; - float ny = 2 * (x / 255) - 1; - float nz = sqrt(1 - nx*nx - ny*ny); - unsigned char z = clamp(int(255 * (nz + 1) / 2), 0, 255); + 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); } @@ -713,7 +1015,7 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba) for (int i = 0; i < 16; i++) { Color32 & c = rgba->color(i); - unsigned int tmp = c.r; + uint tmp = c.r; c.r = c.a; c.a = tmp; } @@ -748,14 +1050,14 @@ void DirectDrawSurface::readBlock(ColorBlock * rgba) for (int i = 0; i < 16; i++) { Color32 & c = rgba->color(i); - c = buildNormal(c.g, c.a); + c = buildNormal(c.a, c.g); } } } } -unsigned int DirectDrawSurface::blockSize() const +uint DirectDrawSurface::blockSize() const { switch(header.pf.fourcc) { @@ -775,13 +1077,13 @@ unsigned int DirectDrawSurface::blockSize() const return 0; } -unsigned int DirectDrawSurface::mipmapSize(unsigned int mipmap) const +uint DirectDrawSurface::mipmapSize(uint mipmap) const { - unsigned int w = width(); - unsigned int h = height(); - unsigned int d = depth(); + uint w = width(); + uint h = height(); + uint d = depth(); - for (unsigned int m = 0; m < mipmap; m++) + for (uint m = 0; m < mipmap; m++) { w = max(1U, w / 2); h = max(1U, h / 2); @@ -798,10 +1100,10 @@ unsigned int DirectDrawSurface::mipmapSize(unsigned int mipmap) const else if (header.pf.flags & DDPF_RGB) { // Align pixels to bytes. - unsigned int byteCount = (header.pf.bitcount + 7) / 8; + uint byteCount = (header.pf.bitcount + 7) / 8; // Align pitch to 4 bytes. - unsigned int pitch = 4 * ((w * byteCount + 3) / 4); + uint pitch = 4 * ((w * byteCount + 3) / 4); return pitch * h * d; } @@ -811,12 +1113,12 @@ unsigned int DirectDrawSurface::mipmapSize(unsigned int mipmap) const }; } -unsigned int DirectDrawSurface::faceSize() const +uint DirectDrawSurface::faceSize() const { - const unsigned int count = mipmapCount(); - unsigned int size = 0; + const uint count = mipmapCount(); + uint size = 0; - for (unsigned int m = 0; m < count; m++) + for (uint m = 0; m < count; m++) { size += mipmapSize(m); } @@ -824,16 +1126,21 @@ unsigned int DirectDrawSurface::faceSize() const return size; } -unsigned int DirectDrawSurface::offset(const unsigned int face, const unsigned int mipmap) +uint DirectDrawSurface::offset(const uint face, const uint mipmap) { - unsigned int size = sizeof(DDSHeader); + uint size = 128; //sizeof(DDSHeader); + if (header.hasDX10Header()) + { + size += 20; // sizeof(DDSHeader10); + } + if (face != 0) { size += face * faceSize(); } - for (unsigned int m = 0; m < mipmap; m++) + for (uint m = 0; m < mipmap; m++) { size += mipmapSize(m); } @@ -876,8 +1183,23 @@ void DirectDrawSurface::printInfo() const 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("\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)); + if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0)) + { + printf("\tSwizzle: '%c%c%c%c'\n", + (header.pf.bitcount >> 0) & 0xFF, + (header.pf.bitcount >> 8) & 0xFF, + (header.pf.bitcount >> 16) & 0xFF, + (header.pf.bitcount >> 24) & 0xFF); + } + else + { + 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); @@ -908,6 +1230,15 @@ void DirectDrawSurface::printInfo() const printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); + if (header.hasDX10Header()) + { + printf("DX10 Header:\n"); + printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); + printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)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; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index 76272717332..28fcc95fe83 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -55,92 +55,114 @@ #ifndef _DDS_DIRECTDRAWSURFACE_H #define _DDS_DIRECTDRAWSURFACE_H +#include <Common.h> #include <Stream.h> #include <ColorBlock.h> #include <Image.h> -struct DDSPixelFormat { - unsigned int size; - unsigned int flags; - unsigned int fourcc; - unsigned int bitcount; - unsigned int rmask; - unsigned int gmask; - unsigned int bmask; - unsigned int amask; +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; }; -struct DDSCaps { - unsigned int caps1; - unsigned int caps2; - unsigned int caps3; - unsigned int caps4; +/// DDS file header for DX10. +struct DDSHeader10 +{ + uint dxgiFormat; + uint resourceDimension; + uint miscFlag; + uint arraySize; + uint reserved; }; /// DDS file header. -struct DDSHeader { - unsigned int fourcc; - unsigned int size; - unsigned int flags; - unsigned int height; - unsigned int width; - unsigned int pitch; - unsigned int depth; - unsigned int mipmapcount; - unsigned int reserved[11]; +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; - unsigned int notused; - + uint notused; + DDSHeader10 header10; + + // Helper methods. DDSHeader(); - void setWidth(unsigned int w); - void setHeight(unsigned int h); - void setDepth(unsigned int d); - void setMipmapCount(unsigned int count); + void setWidth(uint w); + void setHeight(uint h); + void setDepth(uint d); + void setMipmapCount(uint count); void setTexture2D(); void setTexture3D(); void setTextureCube(); - void setLinearSize(unsigned int size); - void setPitch(unsigned int pitch); - void setFourCC(unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3); - void setPixelFormat(unsigned int bitcount, unsigned int rmask, unsigned int gmask, unsigned int bmask, unsigned int amask); + 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); - /* void swapBytes(); */ + bool hasDX10Header() const; }; /// DirectDraw Surface. (DDS) class DirectDrawSurface { public: - DirectDrawSurface(unsigned char *mem, unsigned int size); + DirectDrawSurface(unsigned char *mem, uint size); ~DirectDrawSurface(); bool isValid() const; bool isSupported() const; - unsigned int mipmapCount() const; - unsigned int width() const; - unsigned int height() const; - unsigned int depth() const; + uint mipmapCount() const; + uint width() const; + uint height() const; + uint depth() const; + bool isTexture1D() const; bool isTexture2D() const; bool isTexture3D() const; bool isTextureCube() const; - bool hasAlpha() const; /* false for DXT1, true for all others */ + + void setNormalFlag(bool b); + + bool hasAlpha() const; /* false for DXT1, true for all other DXTs */ - void mipmap(Image * img, unsigned int f, unsigned int m); + void mipmap(Image * img, uint f, uint m); + // void mipmap(FloatImage * img, uint f, uint m); void printInfo() const; private: - unsigned int blockSize() const; - unsigned int faceSize() const; - unsigned int mipmapSize(unsigned int m) const; + uint blockSize() const; + uint faceSize() const; + uint mipmapSize(uint m) const; - unsigned int offset(unsigned int f, unsigned int m); + uint offset(uint f, uint m); void readLinearImage(Image * img); void readBlockImage(Image * img); @@ -155,5 +177,6 @@ private: 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 index 6a751591f3e..8f6ac8658ba 100644 --- a/source/blender/imbuf/intern/dds/Image.cpp +++ b/source/blender/imbuf/intern/dds/Image.cpp @@ -45,7 +45,7 @@ Image::~Image() free(); } -void Image::allocate(unsigned int w, unsigned int h) +void Image::allocate(uint w, uint h) { free(); m_width = w; @@ -60,17 +60,17 @@ void Image::free() } -unsigned int Image::width() const +uint Image::width() const { return m_width; } -unsigned int Image::height() const +uint Image::height() const { return m_height; } -const Color32 * Image::scanline(unsigned int h) const +const Color32 * Image::scanline(uint h) const { if (h >= m_height) { printf("DDS: scanline beyond dimensions of image"); @@ -79,7 +79,7 @@ const Color32 * Image::scanline(unsigned int h) const return m_data + h * m_width; } -Color32 * Image::scanline(unsigned int h) +Color32 * Image::scanline(uint h) { if (h >= m_height) { printf("DDS: scanline beyond dimensions of image"); @@ -98,7 +98,7 @@ Color32 * Image::pixels() return m_data; } -const Color32 & Image::pixel(unsigned int idx) const +const Color32 & Image::pixel(uint idx) const { if (idx >= m_width * m_height) { printf("DDS: pixel beyond dimensions of image"); @@ -107,7 +107,7 @@ const Color32 & Image::pixel(unsigned int idx) const return m_data[idx]; } -Color32 & Image::pixel(unsigned int idx) +Color32 & Image::pixel(uint idx) { if (idx >= m_width * m_height) { printf("DDS: pixel beyond dimensions of image"); diff --git a/source/blender/imbuf/intern/dds/Image.h b/source/blender/imbuf/intern/dds/Image.h index 3a656995857..f2ff9e4fbf3 100644 --- a/source/blender/imbuf/intern/dds/Image.h +++ b/source/blender/imbuf/intern/dds/Image.h @@ -34,6 +34,7 @@ #ifndef _DDS_IMAGE_H #define _DDS_IMAGE_H +#include <Common.h> #include <Color.h> /// 32 bit RGBA image. @@ -50,28 +51,28 @@ public: Image(); ~Image(); - void allocate(unsigned int w, unsigned int h); + void allocate(uint w, uint h); /* bool load(const char * name); - void wrap(void * data, unsigned int w, unsigned int h); + void wrap(void * data, uint w, uint h); void unwrap(); */ - unsigned int width() const; - unsigned int height() const; + uint width() const; + uint height() const; - const Color32 * scanline(unsigned int h) const; - Color32 * scanline(unsigned int h); + const Color32 * scanline(uint h) const; + Color32 * scanline(uint h); const Color32 * pixels() const; Color32 * pixels(); - const Color32 & pixel(unsigned int idx) const; - Color32 & pixel(unsigned int idx); + const Color32 & pixel(uint idx) const; + Color32 & pixel(uint idx); - const Color32 & pixel(unsigned int x, unsigned int y) const; - Color32 & pixel(unsigned int x, unsigned int y); + const Color32 & pixel(uint x, uint y) const; + Color32 & pixel(uint x, uint y); Format format() const; void setFormat(Format f); @@ -80,19 +81,19 @@ private: void free(); private: - unsigned int m_width; - unsigned int m_height; + uint m_width; + uint m_height; Format m_format; Color32 * m_data; }; -inline const Color32 & Image::pixel(unsigned int x, unsigned int y) const +inline const Color32 & Image::pixel(uint x, uint y) const { return pixel(y * width() + x); } -inline Color32 & Image::pixel(unsigned int x, unsigned int y) +inline Color32 & Image::pixel(uint x, uint y) { return pixel(y * width() + x); } diff --git a/source/blender/imbuf/intern/dds/PixelFormat.h b/source/blender/imbuf/intern/dds/PixelFormat.h new file mode 100644 index 00000000000..2004d689a3e --- /dev/null +++ b/source/blender/imbuf/intern/dds/PixelFormat.h @@ -0,0 +1,107 @@ +/** + * $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. + * + * Contributors: Amorilia (amorilia@gamebox.net) + * + * ***** END GPL 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/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index b41b940dca7..cf2f6c16d08 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -94,6 +94,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags) } /* convert DDS into ImBuf */ + // TODO use the image RGB or RGBA tag to determine the bits per pixel if (dds.hasAlpha()) bits_per_pixel = 32; else bits_per_pixel = 24; ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0, 0); diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 84588b52573..8043e594454 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -38,6 +38,7 @@ #include "IMB_imbuf.h" #include "IMB_allocimbuf.h" #include "IMB_divers.h" +#include "BKE_utildefines.h" void imb_checkncols(struct ImBuf *ibuf) { @@ -171,7 +172,6 @@ void IMB_gamwarp(struct ImBuf *ibuf, double gamma) } } -#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 d2ca19e8282..b9186e482c5 100644 --- a/source/blender/imbuf/intern/dynlibtiff.c +++ b/source/blender/imbuf/intern/dynlibtiff.c @@ -80,13 +80,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 */ @@ -100,8 +106,11 @@ void *libtiff_findsymbol(char *name) assert(libtiff != NULL); symbol = PIL_dynlib_find_symbol(libtiff, name); if (symbol == NULL) { - printf("libtiff_findsymbol: error %s\n", - PIL_dynlib_get_error_as_string(libtiff)); + char *err = PIL_dynlib_get_error_as_string(libtiff); + + if (err) printf("libtiff_findsymbol: error %s\n",err); + else printf("libtiff_findsymbol: error Unknown.\n"); + libtiff = NULL; G.have_libtiff = (0); return NULL; diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index fda79315268..9802405fd8d 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -203,29 +203,46 @@ void imb_filterx(struct ImBuf *ibuf) void IMB_filterN(ImBuf *out, ImBuf *in) { register char *row1, *row2, *row3; - register char *cp; + register char *cp, *r11, *r13, *r21, *r23, *r31, *r33; int rowlen, x, y; rowlen= in->x; - for(y=2; y<in->y; y++) { + for(y=0; y<in->y; y++) { /* setup rows */ - row1= (char *)(in->rect + (y-2)*rowlen); - row2= row1 + 4*rowlen; - row3= row2 + 4*rowlen; + row2= (char*)(in->rect + y*rowlen); + row1= (y == 0)? row2: row2 - 4*rowlen; + row3= (y == in->y-1)? row2: row2 + 4*rowlen; - cp= (char *)(out->rect + (y-1)*rowlen); - cp[0]= row2[0]; - cp[1]= row2[1]; - cp[2]= row2[2]; - cp[3]= row2[3]; - cp+= 4; + cp= (char *)(out->rect + y*rowlen); - for(x=2; x<rowlen; x++) { - cp[0]= (row1[0] + 2*row1[4] + row1[8] + 2*row2[0] + 4*row2[4] + 2*row2[8] + row3[0] + 2*row3[4] + row3[8])>>4; - cp[1]= (row1[1] + 2*row1[5] + row1[9] + 2*row2[1] + 4*row2[5] + 2*row2[9] + row3[1] + 2*row3[5] + row3[9])>>4; - cp[2]= (row1[2] + 2*row1[6] + row1[10] + 2*row2[2] + 4*row2[6] + 2*row2[10] + row3[2] + 2*row3[6] + row3[10])>>4; - cp[3]= (row1[3] + 2*row1[7] + row1[11] + 2*row2[3] + 4*row2[7] + 2*row2[11] + row3[3] + 2*row3[7] + row3[11])>>4; + for(x=0; x<rowlen; x++) { + if(x == 0) { + r11 = row1; + r21 = row1; + r31 = row1; + } + else { + r11 = row1-4; + r21 = row1-4; + r31 = row1-4; + } + + if(x == rowlen-1) { + r13 = row1; + r23 = row1; + r33 = row1; + } + else { + r13 = row1+4; + r23 = row1+4; + r33 = row1+4; + } + + cp[0]= (r11[0] + 2*row1[0] + r13[0] + 2*r21[0] + 4*row2[0] + 2*r23[0] + r31[0] + 2*row3[0] + r33[0])>>4; + cp[1]= (r11[1] + 2*row1[1] + r13[1] + 2*r21[1] + 4*row2[1] + 2*r23[1] + r31[1] + 2*row3[1] + r33[1])>>4; + cp[2]= (r11[2] + 2*row1[2] + r13[2] + 2*r21[2] + 4*row2[2] + 2*r23[2] + r31[2] + 2*row3[2] + r33[2])>>4; + cp[3]= (r11[3] + 2*row1[3] + r13[3] + 2*r21[3] + 4*row2[3] + 2*r23[3] + r31[3] + 2*row3[3] + r33[3])>>4; cp+=4; row1+=4; row2+=4; row3+=4; } } @@ -237,18 +254,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 */ @@ -267,8 +338,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); @@ -284,10 +356,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 9cd6b638658..4dba5b13aa0 100755 --- a/source/blender/imbuf/intern/gen_dynlibtiff.py +++ b/source/blender/imbuf/intern/gen_dynlibtiff.py @@ -119,13 +119,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/hamx.c b/source/blender/imbuf/intern/hamx.c index 8db21fc64f1..2f32d155407 100644 --- a/source/blender/imbuf/intern/hamx.c +++ b/source/blender/imbuf/intern/hamx.c @@ -53,7 +53,7 @@ #define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff)) /* more endianness... should move to a separate file... */ -#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__hppa__) || defined (__BIG_ENDIAN__) #define GET_ID GET_BIG_LONG #define LITTLE_LONG SWAP_LONG #else diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 4890e240c6b..d7f1ab4419d 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -48,22 +48,28 @@ I stole it from util.h in the plugins api */ /* 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; @@ -87,16 +93,14 @@ void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf) */ /* 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 ; + return (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)); } 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; + float a,b,w,wx,wy[4], outR,outG,outB,outA,*dataF,*outF; int do_rect, do_float; if (in == NULL) return; @@ -114,24 +118,39 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, in outG= 0.0f; outB= 0.0f; outA= 0.0f; + + /* avoid calling multiple times */ + wy[0] = P(b-(-1)); + wy[1] = P(b- 0); + wy[2] = P(b- 1); + wy[3] = P(b- 2); + 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); + x1= i+n; + if (x1>0 && x1 < in->x) { + wx = P(n-a); + for(m= -1; m<= 2; m++){ + y1= j+m; + if (y1>0 && y1<in->y) { + /* normally we could do this */ + /* w = P(n-a) * P(b-m); */ + /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ + w = wx * wy[m+1]; + + if (do_float) { + dataF= in->rect_float + in->x * y1 * 4 + 4*x1; + outR+= dataF[0] * w; + outG+= dataF[1] * w; + outB+= dataF[2] * w; + outA+= dataF[3] * w; + } + if (do_rect) { + dataI= (unsigned char*)in->rect + in->x * y1 * 4 + 4*x1; + outR+= dataI[0] * w; + outG+= dataI[1] * w; + outB+= dataI[2] * w; + outA+= dataI[3] * w; + } } } } diff --git a/source/blender/imbuf/intern/imbuf.h b/source/blender/imbuf/intern/imbuf.h index 9bdcd278f66..bd2a0d3082f 100644 --- a/source/blender/imbuf/intern/imbuf.h +++ b/source/blender/imbuf/intern/imbuf.h @@ -60,7 +60,7 @@ #define ENDIAN_NOP(x) (x) -#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined (__PPC__) || (defined (__APPLE__) && !defined(__LITTLE_ENDIAN__)) +#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__hppa__) || (defined (__APPLE__) && !defined(__LITTLE_ENDIAN__)) #define LITTLE_SHORT SWAP_SHORT #define LITTLE_LONG SWAP_LONG #define BIG_SHORT ENDIAN_NOP diff --git a/source/blender/imbuf/intern/imbuf_patch.h b/source/blender/imbuf/intern/imbuf_patch.h index 0405ce7bc05..cdd6048f1ad 100644 --- a/source/blender/imbuf/intern/imbuf_patch.h +++ b/source/blender/imbuf/intern/imbuf_patch.h @@ -50,7 +50,7 @@ typedef unsigned char uchar; /* Endianness: flip the byte order. It's strange that this is needed.. * After all, there is an internal endian.{c,h}... */ -#if defined(__sgi) || defined (__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +#if defined(__sgi) || defined (__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__hppa__) || defined (__BIG_ENDIAN__) #define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) #else #define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 3cbada812b9..3e618a483e3 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -180,7 +180,7 @@ static void openexr_header_compression(Header *header, int compression) static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) { - + int channels = ibuf->channels; int width = ibuf->x; int height = ibuf->y; int write_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; // summarize @@ -194,7 +194,7 @@ static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) header.channels().insert ("R", Channel (HALF)); header.channels().insert ("G", Channel (HALF)); header.channels().insert ("B", Channel (HALF)); - if (ibuf->depth==32) + if (ibuf->depth==32 && channels >= 4) header.channels().insert ("A", Channel (HALF)); if (write_zbuf) // z we do as float always header.channels().insert ("Z", Channel (FLOAT)); @@ -207,29 +207,29 @@ static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) RGBAZ *to = pixels; int xstride= sizeof (RGBAZ); int ystride= xstride*width; - + /* indicate used buffers */ frameBuffer.insert ("R", Slice (HALF, (char *) &pixels[0].r, xstride, ystride)); frameBuffer.insert ("G", Slice (HALF, (char *) &pixels[0].g, xstride, ystride)); frameBuffer.insert ("B", Slice (HALF, (char *) &pixels[0].b, xstride, ystride)); - if (ibuf->depth==32) + if (ibuf->depth==32 && channels >= 4) frameBuffer.insert ("A", Slice (HALF, (char *) &pixels[0].a, xstride, ystride)); if (write_zbuf) - frameBuffer.insert ("Z", Slice (FLOAT, (char *) ibuf->zbuf_float + 4*(height-1)*width, + frameBuffer.insert ("Z", Slice (FLOAT, (char *)(ibuf->zbuf_float + (height-1)*width), sizeof(float), sizeof(float) * -width)); if(ibuf->rect_float) { float *from; for (int i = ibuf->y-1; i >= 0; i--) { - from= ibuf->rect_float + 4*i*width; + from= ibuf->rect_float + channels*i*width; for (int j = ibuf->x; j > 0; j--) { to->r = from[0]; - to->g = from[1]; - to->b = from[2]; - to->a = from[3]; + to->g = (channels >= 2)? from[1]: from[0]; + to->b = (channels >= 3)? from[2]: from[0]; + to->a = (channels >= 4)? from[3]: from[0]; to++; from += 4; } } @@ -239,14 +239,14 @@ static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) for (int i = ibuf->y-1; i >= 0; i--) { - from= (unsigned char *)(ibuf->rect + i*width); + from= (unsigned char *)ibuf->rect + channels*i*width; for (int j = ibuf->x; j > 0; j--) { to->r = (float)(from[0])/255.0; - to->g = (float)(from[1])/255.0; - to->b = (float)(from[2])/255.0; - to->a = (float)(from[3])/255.0; + to->g = (float)((channels >= 2)? from[1]: from[0])/255.0; + to->b = (float)((channels >= 3)? from[2]: from[0])/255.0; + to->a = (float)((channels >= 4)? from[3]: from[0])/255.0; to++; from += 4; } } @@ -272,7 +272,7 @@ static short imb_save_openexr_half(struct ImBuf *ibuf, char *name, int flags) static short imb_save_openexr_float(struct ImBuf *ibuf, char *name, int flags) { - + int channels = ibuf->channels; int width = ibuf->x; int height = ibuf->y; int write_zbuf = (flags & IB_zbuffloat) && ibuf->zbuf_float != NULL; // summarize @@ -286,24 +286,29 @@ static short imb_save_openexr_float(struct ImBuf *ibuf, char *name, int flags) header.channels().insert ("R", Channel (FLOAT)); header.channels().insert ("G", Channel (FLOAT)); header.channels().insert ("B", Channel (FLOAT)); - if (ibuf->depth==32) + if (ibuf->depth==32 && channels >= 4) header.channels().insert ("A", Channel (FLOAT)); if (write_zbuf) header.channels().insert ("Z", Channel (FLOAT)); FrameBuffer frameBuffer; OutputFile *file = new OutputFile(name, header); - float *first= ibuf->rect_float + 4*(height-1)*width; - int xstride = sizeof(float) * 4; + int xstride = sizeof(float) * channels; int ystride = - xstride*width; - - frameBuffer.insert ("R", Slice (FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert ("G", Slice (FLOAT, (char *) (first+1), xstride, ystride)); - frameBuffer.insert ("B", Slice (FLOAT, (char *) (first+2), xstride, ystride)); - if (ibuf->depth==32) - frameBuffer.insert ("A", Slice (FLOAT, (char *) (first+3), xstride, ystride)); + float *rect[4] = {NULL, NULL, NULL, NULL}; + + rect[0]= ibuf->rect_float + channels*(height-1)*width; + rect[1]= (channels >= 2)? rect[0]+1: rect[0]; + rect[2]= (channels >= 3)? rect[0]+2: rect[0]; + rect[3]= (channels >= 4)? rect[0]+3: rect[0]; + + frameBuffer.insert ("R", Slice (FLOAT, (char *)rect[0], xstride, ystride)); + frameBuffer.insert ("G", Slice (FLOAT, (char *)rect[1], xstride, ystride)); + frameBuffer.insert ("B", Slice (FLOAT, (char *)rect[2], xstride, ystride)); + if (ibuf->depth==32 && channels >= 4) + frameBuffer.insert ("A", Slice (FLOAT, (char *)rect[3], xstride, ystride)); if (write_zbuf) - frameBuffer.insert ("Z", Slice (FLOAT, (char *) ibuf->zbuf_float + 4*(height-1)*width, + frameBuffer.insert ("Z", Slice (FLOAT, (char *) (ibuf->zbuf_float + (height-1)*width), sizeof(float), sizeof(float) * -width)); file->setFrameBuffer (frameBuffer); file->writePixels (height); @@ -362,6 +367,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 */ @@ -445,12 +451,12 @@ void IMB_exr_begin_write(void *handle, char *filename, int width, int height, in openexr_header_compression(&header, compress); /* header.lineOrder() = DECREASING_Y; this crashes in windows for file read! */ - header.insert ("BlenderMultiChannel", StringAttribute ("Blender V2.43")); + header.insert ("BlenderMultiChannel", StringAttribute ("Blender V2.43 and newer")); 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 +466,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 +485,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 +540,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 +554,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 +627,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 +789,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 +842,7 @@ typedef struct RGBA } RGBA; +/* debug only */ static void exr_print_filecontents(InputFile *file) { const ChannelList &channels = file->header().channels(); @@ -842,13 +854,33 @@ static void exr_print_filecontents(InputFile *file) } } -static int exr_has_zbuffer(InputFile *file) +/* for non-multilayer, map R G B A channel names to something that's in this file */ +static const char *exr_rgba_channelname(InputFile *file, const char *chan) { const ChannelList &channels = file->header().channels(); for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { const Channel &channel = i.channel(); + const char *str= i.name(); + int len= strlen(str); + if(len) { + if(BLI_strcasecmp(chan, str+len-1)==0) { + return str; + } + } + } + return chan; +} + + + +static int exr_has_zbuffer(InputFile *file) +{ + const ChannelList &channels = file->header().channels(); + + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) + { if(strcmp("Z", i.name())==0) return 1; } @@ -884,7 +916,8 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags) //printf("OpenEXR-load: image data window %d %d %d %d\n", // dw.min.x, dw.min.y, dw.max.x, dw.max.y); - // exr_print_filecontents(file); + if(0) // debug + exr_print_filecontents(file); is_multi= exr_is_renderresult(file); @@ -923,11 +956,15 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, int size, int flags) /* but, since we read y-flipped (negative y stride) we move to last scanline */ first+= 4*(height-1)*width; - frameBuffer.insert ("R", Slice (FLOAT, (char *) first, xstride, ystride)); - frameBuffer.insert ("G", Slice (FLOAT, (char *) (first+1), xstride, ystride)); - frameBuffer.insert ("B", Slice (FLOAT, (char *) (first+2), xstride, ystride)); - /* 1.0 is fill value */ - frameBuffer.insert ("A", Slice (FLOAT, (char *) (first+3), xstride, ystride, 1, 1, 1.0f)); + frameBuffer.insert ( exr_rgba_channelname(file, "R"), + Slice (FLOAT, (char *) first, xstride, ystride)); + frameBuffer.insert ( exr_rgba_channelname(file, "G"), + Slice (FLOAT, (char *) (first+1), xstride, ystride)); + frameBuffer.insert ( exr_rgba_channelname(file, "B"), + Slice (FLOAT, (char *) (first+2), xstride, ystride)); + + frameBuffer.insert ( exr_rgba_channelname(file, "A"), + Slice (FLOAT, (char *) (first+3), xstride, ystride, 1, 1, 1.0f)); /* 1.0 is fill value */ if(exr_has_zbuffer(file)) { 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/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 3cb9ca79ffc..b4e384ada72 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -61,6 +61,7 @@ #define BLU 2 #define EXP 3 #define COLXS 128 +#define STR_MAX 540 typedef unsigned char RGBE[4]; typedef float fCOLOR[3]; /* copy source -> dest */ @@ -192,7 +193,8 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) } } if (found) { - sscanf((char*)&mem[x+1], "%s %d %s %d", (char*)&oriY, &height, (char*)&oriX, &width); + if (sscanf((char *)&mem[x+1], "%79s %d %79s %d", (char*)&oriY, &height, + (char*)&oriX, &width) != 4) return NULL; /* find end of this line, data right behind it */ ptr = (unsigned char *)strchr((char*)&mem[x+1], '\n'); @@ -249,7 +251,7 @@ struct ImBuf *imb_loadhdr(unsigned char *mem, int size, int flags) } /* ImBuf write */ -static int fwritecolrs(FILE* file, int width, unsigned char* ibufscan, float* fpscan) +static int fwritecolrs(FILE* file, int width, int channels, unsigned char* ibufscan, float* fpscan) { int x, i, j, beg, c2, cnt=0; fCOLOR fcol; @@ -264,16 +266,16 @@ static int fwritecolrs(FILE* file, int width, unsigned char* ibufscan, float* fp for (i=0;i<width;i++) { if (fpscan) { fcol[RED] = fpscan[j]; - fcol[GRN] = fpscan[j+1]; - fcol[BLU] = fpscan[j+2]; + fcol[GRN] = (channels >= 2)? fpscan[j+1]: fpscan[j]; + fcol[BLU] = (channels >= 3)? fpscan[j+2]: fpscan[j]; } else { fcol[RED] = (float)ibufscan[j] / 255.f; - fcol[GRN] = (float)ibufscan[j+1] / 255.f; - fcol[BLU] = (float)ibufscan[j+2] /255.f; + fcol[GRN] = (float)((channels >= 2)? ibufscan[j+1]: ibufscan[j]) / 255.f; + fcol[BLU] = (float)((channels >= 3)? ibufscan[j+2]: ibufscan[j]) / 255.f; } FLOAT2RGBE(fcol, rgbe); copy_rgbe(rgbe, rgbe_scan[i]); - j+=4; + j+=channels; } if ((width < MINELEN) | (width > MAXELEN)) { /* OOBs, write out flat */ @@ -346,18 +348,18 @@ short imb_savehdr(struct ImBuf *ibuf, char *name, int flags) writeHeader(file, width, height); if(ibuf->rect) - cp= (unsigned char *)(ibuf->rect + (height-1)*width); + cp= (unsigned char *)ibuf->rect + ibuf->channels*(height-1)*width; if(ibuf->rect_float) - fp= ibuf->rect_float + 4*(height-1)*width; + fp= ibuf->rect_float + ibuf->channels*(height-1)*width; for (y=height-1;y>=0;y--) { - if (fwritecolrs(file, width, cp, fp) < 0) { + if (fwritecolrs(file, width, ibuf->channels, cp, fp) < 0) { fclose(file); printf("HDR write error\n"); return 0; } - if(cp) cp-= 4*width; - if(fp) fp-= 4*width; + if(cp) cp-= ibuf->channels*width; + if(fp) fp-= ibuf->channels*width; } fclose(file); diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index b9c04e621ed..05e7921665b 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -29,8 +29,14 @@ * $Id$ */ -#ifdef WIN32 +#ifdef _WIN32 #include <io.h> +#include <stddef.h> +#include <sys/types.h> +#include "mmap_win.h" +#define open _open +#define read _read +#define close _close #endif #include "BLI_blenlib.h" @@ -73,7 +79,7 @@ #define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff)) /* more endianness... should move to a separate file... */ -#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) +#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined(__hppa__) || defined (__BIG_ENDIAN__) #define GET_ID GET_BIG_LONG #define LITTLE_LONG SWAP_LONG #else @@ -229,7 +235,7 @@ struct ImBuf *IMB_loadifffile(int file, int flags) { size = BLI_filesize(file); -#if defined(AMIGA) || defined(__BeOS) || defined(WIN32) +#if defined(AMIGA) || defined(__BeOS) mem= (int *)malloc(size); if (mem==0) { printf("Out of mem\n"); diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 8b3902f77bf..56714c3b481 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -37,6 +37,7 @@ #include "IMB_imbuf.h" #include "IMB_allocimbuf.h" +#include "BKE_utildefines.h" /* blend modes */ @@ -514,15 +515,13 @@ 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, ai; + 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; @@ -538,7 +537,7 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, a = col[3]; ai = 1-a; - + aich = ai/255.0f; if (rect) { unsigned char *pixel; @@ -563,9 +562,9 @@ void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, pixel[1] = chg; pixel[2] = chb; } else { - pixel[0] = (char)(fr + ((float)pixel[0]*ai)); - pixel[1] = (char)(fg + ((float)pixel[1]*ai)); - pixel[2] = (char)(fb + ((float)pixel[2]*ai)); + 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); } } } diff --git a/source/blender/imbuf/intern/rotate.c b/source/blender/imbuf/intern/rotate.c index ca7ea01eaa6..c04987b3e71 100644 --- a/source/blender/imbuf/intern/rotate.c +++ b/source/blender/imbuf/intern/rotate.c @@ -40,48 +40,55 @@ 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); } - - MEM_freeN(line); - if(linef) MEM_freeN(linef); } void IMB_flipx(struct ImBuf * ibuf) diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index c46a4bf1e93..8257eb4643e 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -39,6 +39,8 @@ #include "IMB_allocimbuf.h" #include "IMB_filter.h" +#include "BLO_sys_types.h" // for intptr_t support + /************************************************************************/ /* SCALING */ /************************************************************************/ @@ -480,6 +482,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); + uintptr_t x_src, dx_src, x_dst; + uintptr_t 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; + uintptr_t weight1y = 65536 - (y_src & 0xffff); + uintptr_t 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++) { + uintptr_t weight1x = 65536 - (x_src & 0xffff); + uintptr_t 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 { + uintptr_t r; + uintptr_t g; + uintptr_t b; + uintptr_t a; + + uintptr_t 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); + uintptr_t x_src, dx_dst, x_dst; + uintptr_t y_src, dy_dst, y_dst; + intptr_t 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; + uintptr_t weight1y = 65536 - (y_dst & 0xffff); + uintptr_t weight2y = 65536 - weight1y; + x_dst = 0; + for (x_src = 0; x_src < src_width; x_src++) { + uintptr_t weight1x = 65536 - (x_dst & 0xffff); + uintptr_t weight2x = 65536 - weight1x; + + uintptr_t x = x_dst >> 16; + + uintptr_t 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) { + uintptr_t x; + struct scale_outpix_byte * temp; + + y_counter += 65536; + + for (x=0; x < dst_width; x++) { + uintptr_t 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) { + uintptr_t x; + for (x = 0; x < dst_width; x++) { + uintptr_t 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); + uintptr_t x_dst; + uintptr_t 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; + + uintptr_t 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); + uintptr_t x_src; + uintptr_t 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; + uintptr_t weight1y = 1.0 - (y_dst - (int) y_dst); + uintptr_t weight2y = 1.0 - weight1y; + x_dst = 0; + for (x_src = 0; x_src < src_width; x_src++) { + uintptr_t weight1x = 1.0 - (x_dst - (int) x_dst); + uintptr_t weight2x = 1.0 - weight1x; + + uintptr_t 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) { + uintptr_t 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) { + uintptr_t 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) { @@ -1110,11 +1574,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 index 9097fb84dcd..14d6cb2d54b 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -78,18 +78,17 @@ static int get_thumb_dir( char* dir , ThumbSize size) #endif switch(size) { case THB_NORMAL: - strcat(dir, "/.thumbnails/normal"); + strcat(dir, "/.thumbnails/normal/"); break; case THB_LARGE: - strcat(dir, "/.thumbnails/large"); + strcat(dir, "/.thumbnails/large/"); break; case THB_FAIL: - strcat(dir, "/.thumbnails/fail/blender"); + strcat(dir, "/.thumbnails/fail/blender/"); break; default: return 0; /* unknown size */ } - BLI_cleanup_dir(G.sce, dir); return 1; } diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index 34d486fff11..194082d3e19 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -309,7 +309,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; @@ -321,7 +321,7 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags) memFile.size = size; /* check whether or not we have a TIFF file */ - if (size < IMB_TIFF_NCB) { + if (size < IMB_TIFF_NCB) { fprintf(stderr, "imb_loadtiff: size < IMB_TIFF_NCB\n"); return NULL; } @@ -343,6 +343,7 @@ 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; @@ -415,8 +416,6 @@ struct ImBuf *imb_loadtiff(unsigned char *mem, int size, int flags) return (ibuf); } - - /** * Saves a TIFF file. * @@ -432,14 +431,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, @@ -453,6 +457,11 @@ short imb_savetiff(struct ImBuf *ibuf, char *name, int flags) 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 */ @@ -472,67 +481,67 @@ short imb_savetiff(struct ImBuf *ibuf, char *name, int flags) /* allocate array for pixel data */ npixels = ibuf->x * ibuf->y; - pixels = (unsigned char*)libtiff__TIFFmalloc(npixels * - samplesperpixel * sizeof(unsigned char)); - if (pixels == NULL) { + if(bitspersample == 16) + 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(bitspersample == 16) { + 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 */ @@ -545,18 +554,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) { + 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 4620797518a..c86f9b017bf 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -29,6 +29,13 @@ * $Id$ */ +#ifdef _WIN32 +#include <io.h> +#define open _open +#define read _read +#define close _close +#endif + #include "BLI_blenlib.h" #include "DNA_userdef_types.h" @@ -64,6 +71,8 @@ #ifdef WITH_FFMPEG #include <ffmpeg/avcodec.h> #include <ffmpeg/avformat.h> +//#include <ffmpeg/avdevice.h> +#include <ffmpeg/log.h> #if LIBAVFORMAT_VERSION_INT < (49 << 16) #define FFMPEG_OLD_FRAME_RATE 1 @@ -229,12 +238,32 @@ static int isqtime (char *name) { #endif #ifdef WITH_FFMPEG + +void silence_log_ffmpeg(int quiet) +{ + if (quiet) + { + av_log_set_level(AV_LOG_QUIET); + } + else + { + av_log_set_level(AV_LOG_INFO); + } +} + +extern void do_init_ffmpeg(); void do_init_ffmpeg() { static int ffmpeg_init = 0; if (!ffmpeg_init) { ffmpeg_init = 1; av_register_all(); + //avdevice_register_all(); + + if ((G.f & G_DEBUG) == 0) + { + silence_log_ffmpeg(1); + } } } @@ -253,7 +282,8 @@ static AVCodecContext* get_codec_from_stream(AVStream* stream) static int isffmpeg (char *filename) { AVFormatContext *pFormatCtx; - int i, videoStream; + unsigned int i; + int videoStream; AVCodec *pCodec; AVCodecContext *pCodecCtx; @@ -286,8 +316,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; @@ -303,13 +334,11 @@ static int isffmpeg (char *filename) { /* Find the decoder for the video stream */ pCodec=avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec==NULL) { - avcodec_close(pCodecCtx); av_close_input_file(pFormatCtx); return 0; } if(avcodec_open(pCodecCtx, pCodec)<0) { - avcodec_close(pCodecCtx); av_close_input_file(pFormatCtx); return 0; } @@ -321,6 +350,19 @@ static int isffmpeg (char *filename) { } #endif +#ifdef WITH_REDCODE +static int isredcode(char * filename) +{ + struct redcode_handle * h = redcode_open(filename); + if (!h) { + return 0; + } + redcode_close(h); + return 1; +} + +#endif + int imb_get_anim_type(char * name) { int type; struct stat st; @@ -355,6 +397,9 @@ int imb_get_anim_type(char * name) { if (isffmpeg(name)) return (ANIM_FFMPEG); # endif #endif +#ifdef WITH_REDCODE + if (isredcode(name)) return (ANIM_REDCODE); +#endif type = IMB_ispic(name); if (type == ANIM) return (ANIM_ANIM5); if (type) return(ANIM_SEQUENCE); @@ -369,6 +414,7 @@ int IMB_isanim(char *filename) { if( BLI_testextensie(filename, ".avi") || BLI_testextensie(filename, ".flc") || BLI_testextensie(filename, ".dv") + || BLI_testextensie(filename, ".r3d") || BLI_testextensie(filename, ".mov") || BLI_testextensie(filename, ".movie") || BLI_testextensie(filename, ".mv")) { @@ -379,6 +425,7 @@ int IMB_isanim(char *filename) { } else { // no quicktime if( BLI_testextensie(filename, ".avi") || BLI_testextensie(filename, ".dv") + || BLI_testextensie(filename, ".r3d") || BLI_testextensie(filename, ".mv")) { type = imb_get_anim_type(filename); } |