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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_bad_level_calls.h2
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c2
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c75
-rw-r--r--source/blender/blenkernel/intern/writeframeserver.c8
-rw-r--r--source/blender/blenloader/intern/readfile.c8
-rw-r--r--source/blender/imbuf/IMB_imbuf.h2
-rw-r--r--source/blender/imbuf/intern/IMB_anim.h1
-rw-r--r--source/blender/imbuf/intern/anim.c160
-rw-r--r--source/blender/imbuf/intern/divers.c33
-rw-r--r--source/blender/imbuf/intern/scaling.c16
-rw-r--r--source/blender/imbuf/intern/util.c28
-rw-r--r--source/blender/include/BSE_seqeffects.h83
-rw-r--r--source/blender/include/BSE_seqscopes.h38
-rw-r--r--source/blender/include/BSE_sequence.h64
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h3
-rw-r--r--source/blender/src/drawseq.c13
-rw-r--r--source/blender/src/editseq.c125
-rw-r--r--source/blender/src/hddaudio.c360
-rw-r--r--source/blender/src/seqeffects.c2515
-rw-r--r--source/blender/src/seqscopes.c340
-rw-r--r--source/blender/src/sequence.c1723
21 files changed, 3679 insertions, 1920 deletions
diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h
index 1bc02a02ea6..f261f786dd4 100644
--- a/source/blender/blenkernel/BKE_bad_level_calls.h
+++ b/source/blender/blenkernel/BKE_bad_level_calls.h
@@ -43,8 +43,6 @@ void free_editText(void);
void free_vertexpaint(void);
/* readfile.c */
-struct PluginSeq;
-void open_plugin_seq(struct PluginSeq *pis, char *seqname);
struct SpaceButs;
void set_rects_butspace(struct SpaceButs *buts);
struct SpaceImaSel;
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index e200c6a88ad..81b6130c021 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -63,8 +63,6 @@ void fluidsimSettingsFree(struct FluidsimSettings* sb);
/* readfile.c */
- /* struct PluginSeq; */
-void open_plugin_seq(struct PluginSeq *pis, char *seqname){}
/* struct SpaceButs; */
void set_rects_butspace(struct SpaceButs *buts){}
/* struct SpaceImaSel; */
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index b5e318f7279..5d67760f54a 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <ffmpeg/rational.h>
#include <ffmpeg/avformat.h>
#include <ffmpeg/avcodec.h>
@@ -28,6 +29,7 @@
#define FFMPEG_OLD_FRAME_RATE 1
#else
#define FFMPEG_CODEC_IS_POINTER 1
+#define FFMPEG_CODEC_TIME_BASE 1
#endif
#include "BKE_writeffmpeg.h"
@@ -77,8 +79,6 @@ static uint8_t* audio_output_buffer = 0;
static int audio_outbuf_size = 0;
static RenderData *ffmpeg_renderdata;
-static int ffmpeg_rectx;
-static int ffmpeg_recty;
#define FFMPEG_AUTOSPLIT_SIZE 2000000000
@@ -92,11 +92,23 @@ void delete_picture(AVFrame* f)
}
}
+#ifdef FFMPEG_CODEC_IS_POINTER
+static AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+ return stream->codec;
+}
+#else
+static AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+ return &stream->codec;
+}
+#endif
+
int write_audio_frame(void) {
AVCodecContext* c = NULL;
AVPacket pkt;
- c = audio_stream->codec;
+ c = get_codec_from_stream(audio_stream);
audiostream_fill(audio_input_buffer,
audio_input_frame_size
@@ -108,8 +120,12 @@ int write_audio_frame(void) {
audio_outbuf_size,
(short*) audio_input_buffer);
pkt.data = audio_output_buffer;
+#ifdef FFMPEG_CODEC_TIME_BASE
pkt.pts = av_rescale_q(c->coded_frame->pts,
c->time_base, audio_stream->time_base);
+#else
+ pkt.pts = c->coded_frame->pts;
+#endif
pkt.stream_index = audio_stream->index;
pkt.flags |= PKT_FLAG_KEY;
if (av_write_frame(outfile, &pkt) != 0) {
@@ -150,9 +166,11 @@ AVOutputFormat* ffmpeg_get_format(int format)
f = guess_format("dv", NULL, NULL);
break;
case FFMPEG_MPEG1:
- case FFMPEG_MPEG2:
f = guess_format("mpeg", NULL, NULL);
break;
+ case FFMPEG_MPEG2:
+ f = guess_format("dvd", NULL, NULL);
+ break;
case FFMPEG_MPEG4:
f = guess_format("mp4", NULL, NULL);
break;
@@ -218,11 +236,7 @@ void makeffmpegstring(char* string) {
static void write_video_frame(AVFrame* frame) {
int outsize = 0;
int ret;
-#ifdef FFMPEG_CODEC_IS_POINTER
- AVCodecContext* c = video_stream->codec;
-#else
- AVCodecContext* c = &video_stream->codec;
-#endif
+ AVCodecContext* c = get_codec_from_stream(video_stream);
frame->pts = G.scene->r.cfra - G.scene->r.sfra;
outsize = avcodec_encode_video(c, video_buffer, video_buffersize,
@@ -231,9 +245,13 @@ static void write_video_frame(AVFrame* frame) {
AVPacket packet;
av_init_packet(&packet);
+#ifdef FFMPEG_CODEC_TIME_BASE
packet.pts = av_rescale_q(c->coded_frame->pts,
c->time_base,
video_stream->time_base);
+#else
+ packet.pts = c->coded_frame->pts;
+#endif
if (c->coded_frame->key_frame)
packet.flags |= PKT_FLAG_KEY;
packet.stream_index = video_stream->index;
@@ -252,11 +270,7 @@ static AVFrame* generate_video_frame(uint8_t* pixels)
{
uint8_t* rendered_frame;
-#ifdef FFMPEG_CODEC_IS_POINTER
- AVCodecContext* c = video_stream->codec;
-#else
- AVCodecContext* c = &video_stream->codec;
-#endif
+ AVCodecContext* c = get_codec_from_stream(video_stream);
int width = c->width;
int height = c->height;
AVFrame* rgb_frame;
@@ -334,11 +348,7 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of,
/* Set up the codec context */
-#ifdef FFMPEG_CODEC_IS_POINTER
- c = st->codec;
-#else
- c = &st->codec;
-#endif
+ c = get_codec_from_stream(st);
c->codec_id = codec_id;
c->codec_type = CODEC_TYPE_VIDEO;
@@ -348,6 +358,7 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of,
c->width = rectx;
c->height = recty;
+#ifdef FFMPEG_CODEC_TIME_BASE
/* FIXME: Really bad hack (tm) for NTSC support */
if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) {
c->time_base.den = 2997;
@@ -356,6 +367,16 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of,
c->time_base.den = G.scene->r.frs_sec;
c->time_base.num = 1;
}
+#else
+ /* FIXME: Really bad hack (tm) for NTSC support */
+ if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) {
+ c->frame_rate = 2997;
+ c->frame_rate_base = 100;
+ } else {
+ c->frame_rate = G.scene->r.frs_sec;
+ c->frame_rate_base = 1;
+ }
+#endif
c->gop_size = ffmpeg_gop_size;
c->bit_rate = ffmpeg_video_bitrate*1000;
@@ -419,7 +440,7 @@ AVStream* alloc_audio_stream(int codec_id, AVFormatContext* of)
st = av_new_stream(of, 1);
if (!st) return NULL;
- c = st->codec;
+ c = get_codec_from_stream(st);
c->codec_id = codec_id;
c->codec_type = CODEC_TYPE_AUDIO;
@@ -445,7 +466,7 @@ AVStream* alloc_audio_stream(int codec_id, AVFormatContext* of)
if (c->frame_size <= 1) {
audio_input_frame_size = audio_outbuf_size / c->channels;
- switch(st->codec->codec_id) {
+ switch(c->codec_id) {
case CODEC_ID_PCM_S16LE:
case CODEC_ID_PCM_S16BE:
case CODEC_ID_PCM_U16LE:
@@ -600,14 +621,14 @@ void append_ffmpeg(int frame, int *pixels, int rectx, int recty)
)) {
write_audio_frame();
}
- write_video_frame(generate_video_frame(pixels));
+ write_video_frame(generate_video_frame((unsigned char*) pixels));
if (ffmpeg_autosplit) {
- if (url_fsize(&outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
+ if (url_ftell(&outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) {
end_ffmpeg();
ffmpeg_autosplit_count++;
- start_ffmpeg_impl(rectx, recty,
- ffmpeg_renderdata);
+ start_ffmpeg_impl(ffmpeg_renderdata,
+ rectx, recty);
}
}
}
@@ -625,8 +646,8 @@ void end_ffmpeg(void)
/* Close the video codec */
- if (video_stream && video_stream->codec) {
- avcodec_close(video_stream->codec);
+ if (video_stream && get_codec_from_stream(video_stream)) {
+ avcodec_close(get_codec_from_stream(video_stream));
}
diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c
index b82f9581cf3..58d8f82d454 100644
--- a/source/blender/blenkernel/intern/writeframeserver.c
+++ b/source/blender/blenkernel/intern/writeframeserver.c
@@ -165,10 +165,7 @@ static int handle_request(char * req)
{
char * p;
char * path;
-
- if (strlen(req) < 20) {
- return -1;
- }
+ int pathlen;
if (memcmp(req, "GET ", 4) != 0) {
return -1;
@@ -188,8 +185,9 @@ static int handle_request(char * req)
}
write_ppm = 0;
+ pathlen = strlen(path);
- if (memcmp(path, "/images/ppm/", 12) == 0) {
+ if (pathlen > 12 && memcmp(path, "/images/ppm/", 12) == 0) {
write_ppm = 1;
return atoi(path + 12);
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 31dfa93d4c5..7e452ddd64c 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -104,7 +104,7 @@
#include "BLI_arithb.h"
#include "BLI_storage_types.h" // for relname flags
-#include "BKE_bad_level_calls.h" // for reopen_text build_seqar (from WHILE_SEQ) open_plugin_seq set_rects_butspace check_imasel_copy
+#include "BKE_bad_level_calls.h" // for reopen_text build_seqar (from WHILE_SEQ) set_rects_butspace check_imasel_copy
#include "BKE_action.h"
#include "BKE_armature.h"
@@ -2718,9 +2718,11 @@ static void direct_link_scene(FileData *fd, Scene *sce)
seq->curelem= 0;
seq->plugin= newdataadr(fd, seq->plugin);
- if(seq->plugin) open_plugin_seq(seq->plugin, seq->name+2);
-
seq->effectdata= newdataadr(fd, seq->effectdata);
+
+ if (seq->type & SEQ_EFFECT) {
+ seq->flag |= SEQ_EFFECT_NOT_LOADED;
+ }
seq->strip= newdataadr(fd, seq->strip);
if(seq->strip && seq->strip->done==0) {
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 39243ec50d1..c4141b0a868 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -240,6 +240,8 @@ void IMB_close_anim(struct anim * anim);
*/
int ismovie(char *name);
+void IMB_anim_set_preseek(struct anim * anim, int preseek);
+int IMB_anim_get_preseek(struct anim * anim);
/**
*
diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h
index 5d597aa5463..602b13df4ca 100644
--- a/source/blender/imbuf/intern/IMB_anim.h
+++ b/source/blender/imbuf/intern/IMB_anim.h
@@ -153,6 +153,7 @@ struct anim {
int orientation;
size_t framesize;
int interlacing;
+ int preseek;
/* data */
struct ImBuf * ibuf1, * ibuf2;
diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c
index bd4b268f685..cd238f5013e 100644
--- a/source/blender/imbuf/intern/anim.c
+++ b/source/blender/imbuf/intern/anim.c
@@ -88,12 +88,19 @@
#ifdef WITH_FFMPEG
#include <ffmpeg/avformat.h>
#include <ffmpeg/avcodec.h>
+#include <ffmpeg/rational.h>
+
+/* #define FFMPEG_SEEK_DEBUG 1 */
#if LIBAVFORMAT_VERSION_INT < (49 << 16)
#define FFMPEG_OLD_FRAME_RATE 1
#else
#define FFMPEG_CODEC_IS_POINTER 1
-#define FFMPEG_HAVE_SKIP_FRAME 1
+#define FFMPEG_HAVE_SKIP_OPTS 1
+#endif
+
+#ifndef FF_ER_CAREFUL
+#define FF_ER_CAREFUL FF_ER_CAREFULL
#endif
#endif
@@ -136,6 +143,7 @@ static int startmovie(struct anim * anim) {
anim->framesize = dmImageFrameSize(anim->params);
anim->curposition = 0;
+ anim->preseek = 0;
/*printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/
return (0);
@@ -439,6 +447,7 @@ static int startavi (struct anim *anim) {
anim->framesize = anim->x * anim->y * 4;
anim->curposition = 0;
+ anim->preseek = 0;
/* printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/
@@ -493,6 +502,18 @@ static ImBuf * avi_fetchibuf (struct anim *anim, int position) {
extern void do_init_ffmpeg();
+#ifdef FFMPEG_CODEC_IS_POINTER
+static AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+ return stream->codec;
+}
+#else
+static AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+ return &stream->codec;
+}
+#endif
+
static int startffmpeg(struct anim * anim) {
int i, videoStream;
@@ -519,12 +540,8 @@ static int startffmpeg(struct anim * anim) {
/* Find the first video stream */
videoStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
-#ifdef FFMPEG_CODEC_IS_POINTER
- if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
-#else
- if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO)
-#endif
- {
+ if(get_codec_from_stream(pFormatCtx->streams[i])->codec_type
+ == CODEC_TYPE_VIDEO) {
videoStream=i;
break;
}
@@ -534,11 +551,7 @@ static int startffmpeg(struct anim * anim) {
return -1;
}
-#ifdef FFMPEG_CODEC_IS_POINTER
- pCodecCtx=pFormatCtx->streams[videoStream]->codec;
-#else
- pCodecCtx=&pFormatCtx->streams[videoStream]->codec;
-#endif
+ pCodecCtx = get_codec_from_stream(pFormatCtx->streams[videoStream]);
/* Find the decoder for the video stream */
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
@@ -551,11 +564,11 @@ static int startffmpeg(struct anim * anim) {
pCodecCtx->workaround_bugs = 1;
pCodecCtx->lowres = 0;
pCodecCtx->idct_algo= FF_IDCT_AUTO;
-#ifdef FFMPEG_HAVE_SKIP_FRAME
+#ifdef FFMPEG_HAVE_SKIP_OPTS
pCodecCtx->skip_frame= AVDISCARD_DEFAULT;
-#endif
pCodecCtx->skip_idct= AVDISCARD_DEFAULT;
pCodecCtx->skip_loop_filter= AVDISCARD_DEFAULT;
+#endif
pCodecCtx->error_resilience= FF_ER_CAREFUL;
pCodecCtx->error_concealment= 3;
@@ -573,7 +586,9 @@ static int startffmpeg(struct anim * anim) {
anim->duration = pFormatCtx->duration * pCodecCtx->frame_rate
/ pCodecCtx->frame_rate_base / AV_TIME_BASE;
#else
- anim->duration = pFormatCtx->duration * av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate) / AV_TIME_BASE;
+ anim->duration = pFormatCtx->duration
+ * av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate)
+ / AV_TIME_BASE;
#endif
anim->params = 0;
@@ -605,7 +620,12 @@ static int startffmpeg(struct anim * anim) {
return -1;
}
- /*printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/
+ if (pCodecCtx->has_b_frames) {
+ anim->preseek = 18; /* FIXME: detect gopsize ... */
+ } else {
+ anim->preseek = 0;
+ }
+
return (0);
}
@@ -625,22 +645,49 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
PIX_FMT_RGBA32, anim->x, anim->y);
if (position != anim->curposition + 1) {
+ if (position > anim->curposition + 1
+ && anim->preseek
+ && position - (anim->curposition + 1) < anim->preseek) {
+ while(av_read_frame(anim->pFormatCtx, &packet)>=0) {
+ if (packet.stream_index == anim->videoStream) {
+ avcodec_decode_video(
+ anim->pCodecCtx,
+ anim->pFrame, &frameFinished,
+ packet.data, packet.size);
+
+ if (frameFinished) {
+ anim->curposition++;
+ }
+ }
+ av_free_packet(&packet);
+ if (position == anim->curposition+1) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (position != anim->curposition + 1) {
int keyframe_found = 0;
- int scan_pos = position;
- int max_scan = 18; /* max mpeg 1/2 gop size */
#ifdef FFMPEG_OLD_FRAME_RATE
- long long pos = (long long) anim->pCodecCtx->frame_rate_base
- * position * AV_TIME_BASE
- / anim->pCodecCtx->frame_rate;
+ double frame_rate =
+ (double) anim->pCodecCtx->frame_rate
+ / (double) anim->pCodecCtx->frame_rate_base;
#else
- long long pos = (long long) position * AV_TIME_BASE
- / av_q2d(anim->pFormatCtx->streams[anim->videoStream]
- ->r_frame_rate);
+ double frame_rate =
+ av_q2d(anim->pFormatCtx->streams[anim->videoStream]
+ ->r_frame_rate);
#endif
+ double time_base =
+ av_q2d(anim->pFormatCtx->streams[anim->videoStream]
+ ->time_base);
+ long long pos = (long long) position * AV_TIME_BASE
+ / frame_rate;
long long st_time = anim->pFormatCtx
->streams[anim->videoStream]->start_time;
+
if (st_time != AV_NOPTS_VALUE) {
- pos += st_time;
+ pos += st_time * AV_TIME_BASE * time_base;
}
av_seek_frame(anim->pFormatCtx, -1,
@@ -653,49 +700,23 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
if ((packet.flags & PKT_FLAG_KEY) != 0) {
keyframe_found = 1;
}
+
av_free_packet(&packet);
break;
}
av_free_packet(&packet);
}
- /* if all ffmpeg seek bugs are fixed, the following
- loop is obsolete ... (but does not hurt very much...)
- */
-
- while (!keyframe_found && max_scan--) {
- scan_pos--;
-#ifdef FFMPEG_OLD_FRAME_RATE
- pos = (long long)
- anim->pCodecCtx->frame_rate_base
- * scan_pos * AV_TIME_BASE
- / anim->pCodecCtx->frame_rate;
-#else
- pos = (long long) scan_pos * AV_TIME_BASE
- / av_q2d(anim->pFormatCtx
- ->streams[anim->videoStream]
- ->r_frame_rate);
-#endif
- av_seek_frame(anim->pFormatCtx, -1,
- pos,
- AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
- while(av_read_frame(anim->pFormatCtx, &packet)>=0) {
- if(packet.stream_index == anim->videoStream) {
- if ((packet.flags & PKT_FLAG_KEY)
- != 0) {
- keyframe_found = 1;
- }
- av_free_packet(&packet);
- break;
- }
- av_free_packet(&packet);
+ if (!keyframe_found) {
+ int scan_pos = position - anim->preseek;
+ if (scan_pos < 0) {
+ scan_pos = 0;
}
- }
- if (max_scan <= 0) {
- fprintf(stderr,
- "Warning: Key frame not found, "
- "doesn't hurt, but _slow_...!\n");
+ pos = (long long) scan_pos * AV_TIME_BASE / frame_rate;
+ if (st_time != AV_NOPTS_VALUE) {
+ pos += st_time * AV_TIME_BASE * time_base;
+ }
}
av_seek_frame(anim->pFormatCtx, -1,
@@ -710,6 +731,11 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
&& !pos_found) {
if (url_ftell(&anim->pFormatCtx->pb) == pos_to_match) {
pos_found = 1;
+ if (anim->pCodecCtx->has_b_frames) {
+ pos_found++;
+ /* account for delay caused by
+ decoding pipeline */
+ }
}
}
if(packet.stream_index == anim->videoStream) {
@@ -717,7 +743,9 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
anim->pFrame, &frameFinished,
packet.data, packet.size);
- if(frameFinished && pos_found) {
+ if (frameFinished && pos_found == 2) {
+ pos_found = 1;
+ } else if(frameFinished && pos_found == 1) {
unsigned char * p =(unsigned char*) ibuf->rect;
unsigned char * e = p + anim->x * anim->y * 4;
@@ -924,3 +952,13 @@ struct ImBuf * IMB_anim_nextpic(struct anim * anim) {
int IMB_anim_get_duration(struct anim *anim) {
return anim->duration;
}
+
+void IMB_anim_set_preseek(struct anim * anim, int preseek)
+{
+ anim->preseek = preseek;
+}
+
+int IMB_anim_get_preseek(struct anim * anim)
+{
+ return anim->preseek;
+}
diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c
index 2fc80f6ddcb..c0018d0b336 100644
--- a/source/blender/imbuf/intern/divers.c
+++ b/source/blender/imbuf/intern/divers.c
@@ -141,25 +141,32 @@ void IMB_interlace(struct ImBuf *ibuf)
void IMB_gamwarp(struct ImBuf *ibuf, double gamma)
{
uchar gam[256];
- int i, do_float=0;
- uchar *rect = (uchar *) ibuf->rect;
- float *rectf = ibuf->rect_float;
+ int i;
+ uchar *rect;
+ float *rectf;
if (ibuf == 0) return;
- if (ibuf->rect == 0) return;
- if (ibuf->rect != NULL) do_float = 1;
if (gamma == 1.0) return;
+ rect = (uchar *) ibuf->rect;
+ rectf = ibuf->rect_float;
+
gamma = 1.0 / gamma;
- for (i = 255 ; i >= 0 ; i--) gam[i] = (255.0 * pow(i / 255.0 ,
- gamma)) + 0.5;
- rect = (uchar *) ibuf->rect;
- for (i = ibuf->x * ibuf->y ; i>0 ; i--, rect+=4){
- rect[0] = gam[rect[0]];
- rect[1] = gam[rect[1]];
- rect[2] = gam[rect[2]];
- if (do_float) {
+ if (rect) {
+ for (i = 255 ; i >= 0 ; i--)
+ gam[i] = (255.0 * pow(i / 255.0 ,
+ gamma)) + 0.5;
+
+ for (i = ibuf->x * ibuf->y ; i>0 ; i--, rect+=4){
+ rect[0] = gam[rect[0]];
+ rect[1] = gam[rect[1]];
+ rect[2] = gam[rect[2]];
+ }
+ }
+
+ if (rectf) {
+ for (i = ibuf->x * ibuf->y ; i>0 ; i--, rectf+=4){
rectf[0] = pow(rectf[0] / 255.0, gamma);
rectf[1] = pow(rectf[1] / 255.0, gamma);
rectf[2] = pow(rectf[2] / 255.0, gamma);
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index c962f1fbde5..8db51f50ee0 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -964,10 +964,18 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, short newx, short newy)
ofsy += stepy;
ofsx = 32768;
- for (x = newx ; x>0 ; x--){
- if (do_rect) *newrect++ = rect[ofsx >> 16];
- if (do_float) *newrectf++ = rectf[ofsx >> 16];
- ofsx += stepx;
+ if (do_rect) {
+ for (x = newx ; x>0 ; x--){
+ *newrect++ = rect[ofsx >> 16];
+ ofsx += stepx;
+ }
+ }
+
+ if (do_float) {
+ for (x = newx ; x>0 ; x--){
+ *newrectf++ = rectf[ofsx >> 16];
+ ofsx += stepx;
+ }
}
}
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index fdb1bed3870..56a03f56ce2 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -217,6 +217,18 @@ void do_init_ffmpeg()
}
}
+#ifdef FFMPEG_CODEC_IS_POINTER
+static AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+ return stream->codec;
+}
+#else
+static AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+ return &stream->codec;
+}
+#endif
+
static int isffmpeg (char *filename) {
AVFormatContext *pFormatCtx;
@@ -243,21 +255,14 @@ static int isffmpeg (char *filename) {
/* Find the first video stream */
videoStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
-#ifdef FFMPEG_CODEC_IS_POINTER
- if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
-#else
- if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO)
-#endif
+ if(get_codec_from_stream(pFormatCtx->streams[i])
+ ->codec_type==CODEC_TYPE_VIDEO)
{
videoStream=i;
break;
}
-#ifdef FFMPEG_CODEC_IS_POINTER
- pCodecCtx=pFormatCtx->streams[videoStream]->codec;
-#else
- pCodecCtx=&pFormatCtx->streams[videoStream]->codec;
-#endif
+ pCodecCtx = get_codec_from_stream(pFormatCtx->streams[videoStream]);
if(videoStream==-1) {
avcodec_close(pCodecCtx);
@@ -274,9 +279,6 @@ static int isffmpeg (char *filename) {
return 0;
}
- if(pCodec->capabilities & CODEC_CAP_TRUNCATED)
- pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
-
if(avcodec_open(pCodecCtx, pCodec)<0) {
avcodec_close(pCodecCtx);
av_close_input_file(pFormatCtx);
diff --git a/source/blender/include/BSE_seqeffects.h b/source/blender/include/BSE_seqeffects.h
new file mode 100644
index 00000000000..a7fd56593e0
--- /dev/null
+++ b/source/blender/include/BSE_seqeffects.h
@@ -0,0 +1,83 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Peter Schlaile < peter [at] schlaile [dot] de >
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef BSE_SEQUENCE_EFFECTS_H
+#define BSE_SEQUENCE_EFFECTS_H
+
+/* Wipe effect */
+enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE,
+ DO_IRIS_WIPE,DO_CLOCK_WIPE};
+
+struct Sequence;
+struct ImBuf;
+
+struct SeqEffectHandle {
+ /* constructors & destructor */
+ /* init & init_plugin are _only_ called on first creation */
+ void (*init)(struct Sequence *seq);
+ void (*init_plugin)(struct Sequence * seq, const char * fname);
+
+ /* load is called first time after readblenfile in
+ get_sequence_effect automatically */
+ void (*load)(struct Sequence *seq);
+
+ /* duplicate */
+ void (*copy)(struct Sequence *dst, struct Sequence * src);
+
+ /* destruct */
+ void (*free)(struct Sequence *seq);
+
+ /* returns: 0: no early out, 1: out = ibuf1, 2: out = ibuf2 */
+ int (*early_out)(struct Sequence *seq,
+ float facf0, float facf1);
+
+ /* stores the default facf0 and facf1 if no IPO is present */
+ void (*get_default_fac)(struct Sequence * seq, int cfra,
+ float * facf0, float * facf1);
+
+ /* execute the effect
+ sequence effects are only required to either support
+ float-rects or byte-rects
+ (mixed cases are handled one layer up...) */
+
+ void (*execute)(struct Sequence *seq, int cfra,
+ float facf0, float facf1,
+ int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out);
+};
+
+struct SeqEffectHandle get_sequence_effect(struct Sequence * seq);
+
+#endif
+
diff --git a/source/blender/include/BSE_seqscopes.h b/source/blender/include/BSE_seqscopes.h
new file mode 100644
index 00000000000..3dd5e495928
--- /dev/null
+++ b/source/blender/include/BSE_seqscopes.h
@@ -0,0 +1,38 @@
+/**
+ * $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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Peter Schlaile < peter [at] schlaile [dot] de >
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef BSE_SEQUENCE_SCOPES_H
+#define BSE_SEQUENCE_SCOPES_H
+
+struct ImBuf;
+
+struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf);
+struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf);
+
+#endif
+
diff --git a/source/blender/include/BSE_sequence.h b/source/blender/include/BSE_sequence.h
index 686749b303d..65c55d95045 100644
--- a/source/blender/include/BSE_sequence.h
+++ b/source/blender/include/BSE_sequence.h
@@ -44,9 +44,6 @@ struct Editing;
struct ImBuf;
struct Scene;
-void open_plugin_seq(struct PluginSeq *pis, char *seqname);
-struct PluginSeq *add_plugin_seq(char *str, char *seqname);
-void free_plugin_seq(struct PluginSeq *pis);
void free_stripdata(int len, struct StripElem *se);
void free_strip(struct Strip *strip);
void new_stripdata(struct Sequence *seq);
@@ -58,64 +55,6 @@ void free_editing(struct Editing *ed);
void calc_sequence(struct Sequence *seq);
void sort_seq(void);
void clear_scene_in_allseqs(struct Scene *sce);
-void do_alphaover_effect(float facf0,
- float facf1,
- int x, int y,
- unsigned int *rect1,
- unsigned int *rect2,
- unsigned int *out);
-void do_alphaunder_effect(float facf0, float facf1,
- int x, int y,
- unsigned int *rect1, unsigned int *rect2,
- unsigned int *out);
-void do_cross_effect(float facf0, float facf1,
- int x, int y,
- unsigned int *rect1, unsigned int *rect2,
- unsigned int *out);
-void do_gammacross_effect(float facf0, float facf1,
- int x, int y,
- unsigned int *rect1, unsigned int *rect2,
- unsigned int *out);
-void do_add_effect(float facf0, float facf1,
- int x, int y,
- unsigned int *rect1, unsigned int *rect2,
- unsigned int *out);
-void do_sub_effect(float facf0, float facf1,
- int x, int y,
- unsigned int *rect1, unsigned int *rect2,
- unsigned int *out);
-void do_drop_effect(float facf0, float facf1,
- int x, int y,
- unsigned int *rect2i, unsigned int *rect1i,
- unsigned int *outi);
-void do_drop_effect2(float facf0, float facf1,
- int x, int y,
- unsigned int *rect2, unsigned int *rect1,
- unsigned int *out);
-void do_mul_effect(float facf0, float facf1,
- int x, int y,
- unsigned int *rect1, unsigned int *rect2,
- unsigned int *out);
-/* Wipe effect */
-enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE,
- DO_IRIS_WIPE,DO_CLOCK_WIPE};
-float in_band(float width,float dist, float perc,int side,int dir);
-float check_zone(int x, int y, int xo, int yo, struct Sequence *seq, float facf0);
-void init_wipe_effect(struct Sequence *seq);
-void do_wipe_effect(struct Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out);
-
-/* Glow effect */
-enum {
- GlowR=0,
- GlowG=1,
- GlowB=2,
- GlowA=3
-};
-void RVBlurBitmap2( unsigned char* map, int width, int height, float blur, int quality);
-void RVIsolateHighlights (unsigned char* in, unsigned char* out, int width, int height, int threshold, float boost, float clamp);
-void RVAddBitmaps (unsigned char* a,unsigned char* b, unsigned char* c, int width, int height);
-void init_glow_effect(struct Sequence *seq);
-void do_glow_effect(struct Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out);
void make_black_ibuf(struct ImBuf *ibuf);
void multibuf(struct ImBuf *ibuf, float fmul);
@@ -126,9 +65,6 @@ void set_meta_stripdata(struct Sequence *seqm);
struct ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chansel);
/* chansel: render this channel. Default=0 (renders end result)*/
-struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf);
-struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf);
-
void free_imbuf_effect_spec(int cfra);
void free_imbuf_seq_except(int cfra);
void free_imbuf_seq(void);
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 6115a82457f..2505c5c6838 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -126,6 +126,8 @@ typedef struct Sequence {
void *effectdata; /* Struct pointer for effect settings */
+ int anim_preseek;
+ int pad;
} Sequence;
typedef struct MetaStack {
@@ -170,6 +172,7 @@ typedef struct GlowVars {
#define SEQ_MAKE_PREMUL 64
#define SEQ_REVERSE_FRAMES 128
#define SEQ_IPO_FRAME_LOCKED 256
+#define SEQ_EFFECT_NOT_LOADED 512
/* seq->type WATCH IT: SEQ_EFFECT BIT is used to determine if this is an effect strip!!! */
#define SEQ_IMAGE 0
diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c
index 1712be12368..a0d3232cf2f 100644
--- a/source/blender/src/drawseq.c
+++ b/source/blender/src/drawseq.c
@@ -70,6 +70,8 @@
#include "BSE_view.h"
#include "BSE_drawipo.h"
#include "BSE_sequence.h"
+#include "BSE_seqeffects.h"
+#include "BSE_seqscopes.h"
#include "BSE_seqaudio.h"
#include "IMB_imbuf_types.h"
@@ -596,8 +598,14 @@ static void draw_image_seq(ScrArea *sa)
free_ibuf = 1;
}
- if (sseq->zoom > 0) zoom = sseq->zoom;
- else zoom = -1.0/sseq->zoom;
+ if (sseq->zoom > 0) {
+ zoom = sseq->zoom;
+ } else if (sseq->zoom == 0) {
+ zoom = 1.0;
+ } else {
+ zoom = -1.0/sseq->zoom;
+ }
+
/* calc location */
x1= (sa->winx-zoom*ibuf->x)/2;
y1= (sa->winy-zoom*ibuf->y)/2;
@@ -809,6 +817,7 @@ static void seq_panel_properties(short cntrl) // SEQ_HANDLER_PROPERTIES
uiDefButS(block, TOG|BIT|7, SEQ_BUT_RELOAD, "Reverse Frames", 10,30,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Reverse frame order");
uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Strobe:", 10,10,150,19, &last_seq->strobe, 1.0, 30.0, 100, 0, "Only display every nth frame");
+ uiDefButI(block, NUM, SEQ_BUT_RELOAD, "Preseek:", 10,-10,150,19, &last_seq->anim_preseek, 0.0, 50.0, 100, 0, "On MPEG-seeking preseek this many frames");
}
else if(last_seq->type==SEQ_RAM_SOUND ||
diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c
index 15877c226c2..a1cbcf296d7 100644
--- a/source/blender/src/editseq.c
+++ b/source/blender/src/editseq.c
@@ -85,6 +85,7 @@
#include "BSE_edit.h"
#include "BSE_sequence.h"
+#include "BSE_seqeffects.h"
#include "BSE_filesel.h"
#include "BSE_drawipo.h"
#include "BSE_seqaudio.h"
@@ -111,15 +112,18 @@ static void shuffle_seq(Sequence *);
static void change_plugin_seq(char *str) /* called from fileselect */
{
-/* extern Sequence *last_seq; already done few lines before !!!*/
+ struct SeqEffectHandle sh;
- if(last_seq && last_seq->type!=SEQ_PLUGIN) return;
+ if(last_seq && last_seq->type != SEQ_PLUGIN) return;
- free_plugin_seq(last_seq->plugin);
+ sh = get_sequence_effect(last_seq);
+ sh.free(last_seq);
+ sh.init_plugin(last_seq, str);
- last_seq->plugin= (PluginSeq *)add_plugin_seq(str, last_seq->name+2);
+ last_seq->machine = MAX3(last_seq->seq1->machine,
+ last_seq->seq2->machine,
+ last_seq->seq3->machine);
- last_seq->machine= MAX3(last_seq->seq1->machine, last_seq->seq2->machine, last_seq->seq3->machine);
if( test_overlap_seq(last_seq) ) shuffle_seq(last_seq);
BIF_undo_push("Load/change Sequencer plugin");
@@ -404,11 +408,13 @@ void mouse_select_seq(void)
if(seq->flag & SELECT) {
if(hand==0) seq->flag &= SEQ_DESEL;
else if(hand==1) {
- if(seq->flag & SEQ_LEFTSEL) seq->flag &= ~SEQ_LEFTSEL;
+ if(seq->flag & SEQ_LEFTSEL)
+ seq->flag &= ~SEQ_LEFTSEL;
else seq->flag |= SEQ_LEFTSEL;
}
else if(hand==2) {
- if(seq->flag & SEQ_RIGHTSEL) seq->flag &= ~SEQ_RIGHTSEL;
+ if(seq->flag & SEQ_RIGHTSEL)
+ seq->flag &= ~SEQ_RIGHTSEL;
else seq->flag |= SEQ_RIGHTSEL;
}
}
@@ -553,6 +559,7 @@ static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine)
seq->len= totframe;
seq->type= SEQ_MOVIE;
seq->anim= anim;
+ seq->anim_preseek = IMB_anim_get_preseek(anim);
calc_sequence(seq);
@@ -981,6 +988,7 @@ static int add_seq_effect(int type)
float x, y;
int cfra, machine;
short mval[2];
+ struct SeqEffectHandle sh;
if(G.scene->ed==0) return 0;
ed= G.scene->ed;
@@ -1037,23 +1045,14 @@ static int add_seq_effect(int type)
seq->type= event_to_efftype(type);
- /* Allocate variable structs for effects with settings */
- if(seq->type==SEQ_WIPE){
- init_wipe_effect(seq);
- }
- else if(seq->type==SEQ_GLOW){
- init_glow_effect(seq);
- }
+ sh = get_sequence_effect(seq);
- if(seq->type==SEQ_ALPHAUNDER || seq->type==SEQ_ALPHAOVER) {
- seq->seq2= seq1;
- seq->seq1= seq2;
- }
- else {
- seq->seq1= seq1;
- seq->seq2= seq2;
- }
+ seq->seq1= seq1;
+ seq->seq2= seq2;
seq->seq3= seq3;
+
+ sh.init(seq);
+
calc_sequence(seq);
seq->strip= strip= MEM_callocN(sizeof(Strip), "strip");
@@ -1069,12 +1068,12 @@ static int add_seq_effect(int type)
static void load_plugin_seq(char *str) /* called from fileselect */
{
Editing *ed;
+ struct SeqEffectHandle sh;
add_seq_effect(10); /* this sets last_seq */
- free_plugin_seq(last_seq->plugin);
-
- last_seq->plugin= (PluginSeq *)add_plugin_seq(str, last_seq->name+2);
+ sh = get_sequence_effect(last_seq);
+ sh.init_plugin(last_seq, str);
if(last_seq->plugin==0) {
ed= G.scene->ed;
@@ -1261,33 +1260,46 @@ void change_sequence(void)
if(last_seq==0) return;
if(last_seq->type & SEQ_EFFECT) {
- event= pupmenu("Change Effect%t|Switch A <-> B %x1|Switch B <-> C %x10|Plugin%x11|Recalculate%x12|Cross%x2|Gamma Cross%x3|Add%x4|Sub%x5|Mul%x6|Alpha Over%x7|Alpha Under%x8|Alpha Over Drop%x9|Wipe%x13|Glow%x14");
- if(event>0) {
+ event = pupmenu("Change Effect%t"
+ "|Switch A <-> B %x1"
+ "|Switch B <-> C %x10"
+ "|Plugin%x11"
+ "|Recalculate%x12"
+ "|Cross%x2"
+ "|Gamma Cross%x3"
+ "|Add%x4"
+ "|Sub%x5"
+ "|Mul%x6"
+ "|Alpha Over%x7"
+ "|Alpha Under%x8"
+ "|Alpha Over Drop%x9"
+ "|Wipe%x13"
+ "|Glow%x14");
+ if(event > 0) {
if(event==1) {
- SWAP(Sequence *, last_seq->seq1, last_seq->seq2);
+ SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
}
else if(event==10) {
- SWAP(Sequence *, last_seq->seq2, last_seq->seq3);
+ SWAP(Sequence *,last_seq->seq2,last_seq->seq3);
}
else if(event==11) {
- activate_fileselect(FILE_SPECIAL, "Select Plugin", U.plugseqdir, change_plugin_seq);
+ activate_fileselect(
+ FILE_SPECIAL, "Select Plugin",
+ U.plugseqdir, change_plugin_seq);
}
- else if(event==12); /* recalculate: only new_stripdata */
+ else if(event==12);
+ /* recalculate: only new_stripdata */
else {
- /* to be sure, free plugin */
- free_plugin_seq(last_seq->plugin);
- last_seq->plugin= 0;
- last_seq->type= event_to_efftype(event);
-
- switch(last_seq->type){
- case SEQ_WIPE:
- init_wipe_effect(last_seq);
- break;
- case SEQ_GLOW:
- init_glow_effect(last_seq);
- break;
- }
+ /* free previous effect and init new effect */
+ struct SeqEffectHandle sh;
+ sh = get_sequence_effect(last_seq);
+ sh.free(last_seq);
+
+ last_seq->type = event_to_efftype(event);
+
+ sh = get_sequence_effect(last_seq);
+ sh.init(last_seq);
}
new_stripdata(last_seq);
allqueue(REDRAWSEQ, 0);
@@ -1296,7 +1308,10 @@ void change_sequence(void)
}
else if(last_seq->type == SEQ_IMAGE) {
if(okee("Change images")) {
- activate_fileselect(FILE_SPECIAL, "Select Images", last_imagename, reload_image_strip);
+ activate_fileselect(FILE_SPECIAL,
+ "Select Images",
+ last_imagename,
+ reload_image_strip);
}
}
else if(last_seq->type == SEQ_MOVIE) {
@@ -1379,7 +1394,9 @@ void del_seq(void)
while(seq) {
seqn= seq->next;
if(seq->type & SEQ_EFFECT) {
- if( is_a_sequence(seq->seq1)==0 || is_a_sequence(seq->seq2)==0 || is_a_sequence(seq->seq3)==0 ) {
+ if( is_a_sequence(seq->seq1)==0
+ || is_a_sequence(seq->seq2)==0
+ || is_a_sequence(seq->seq3)==0 ) {
BLI_remlink(ed->seqbasep, seq);
if(seq==last_seq) last_seq= 0;
free_sequence(seq);
@@ -1436,7 +1453,7 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new)
seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
seqn->seqbase.first= seqn->seqbase.last= 0;
- recurs_dupli_seq(&seq->seqbase, &seqn->seqbase);
+ recurs_dupli_seq(&seq->seqbase,&seqn->seqbase);
}
else if(seq->type == SEQ_SCENE) {
@@ -1446,7 +1463,7 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new)
seqn->strip= MEM_dupallocN(seq->strip);
- if(seq->len>0) seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
+ if(seq->len>0) seqn->strip->stripdata = MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
seq->flag &= SEQ_DESEL;
seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
@@ -1548,10 +1565,12 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new)
if(seqn->ipo) seqn->ipo->id.us++;
- if(seq->plugin) {
- seqn->plugin= MEM_dupallocN(seq->plugin);
- open_plugin_seq(seqn->plugin, seqn->name+2);
+ if (seq->type & SEQ_EFFECT) {
+ struct SeqEffectHandle sh;
+ sh = get_sequence_effect(seq);
+ sh.copy(seq, seqn);
}
+
seqn->strip= MEM_dupallocN(seq->strip);
if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem");
@@ -1795,7 +1814,9 @@ void un_meta(void)
while(seq) {
seqn= seq->next;
if(seq->type & SEQ_EFFECT) {
- if( is_a_sequence(seq->seq1)==0 || is_a_sequence(seq->seq2)==0 || is_a_sequence(seq->seq3)==0 ) {
+ if( is_a_sequence(seq->seq1)==0
+ || is_a_sequence(seq->seq2)==0
+ || is_a_sequence(seq->seq3)==0 ) {
BLI_remlink(ed->seqbasep, seq);
if(seq==last_seq) last_seq= 0;
free_sequence(seq);
diff --git a/source/blender/src/hddaudio.c b/source/blender/src/hddaudio.c
index a06ff0c6901..4221bd440b5 100644
--- a/source/blender/src/hddaudio.c
+++ b/source/blender/src/hddaudio.c
@@ -20,7 +20,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * Contributor(s): Peter Schlaile <peter@schlaile.de> 2005
+ * Contributor(s): Peter Schlaile <peter [at] schlaile [dot] de> 2005
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -38,6 +38,7 @@
#ifdef WITH_FFMPEG
#include <ffmpeg/avformat.h>
#include <ffmpeg/avcodec.h>
+#include <ffmpeg/rational.h>
#if LIBAVFORMAT_VERSION_INT < (49 << 16)
#define FFMPEG_OLD_FRAME_RATE 1
#else
@@ -65,8 +66,12 @@ struct hdaudio {
AVCodecContext *pCodecCtx;
int frame_position;
int frame_duration;
+ int frame_alloc_duration;
+ int decode_pos;
int frame_size;
short * decode_cache;
+ short * decode_cache_zero;
+ short * resample_cache;
int decode_cache_size;
int target_channels;
int target_rate;
@@ -77,6 +82,20 @@ struct hdaudio {
#endif
};
+#ifdef WITH_FFMPEG
+#ifdef FFMPEG_CODEC_IS_POINTER
+static AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+ return stream->codec;
+}
+#else
+static AVCodecContext* get_codec_from_stream(AVStream* stream)
+{
+ return &stream->codec;
+}
+#endif
+#endif
+
struct hdaudio * sound_open_hdaudio(char * filename)
{
#ifdef WITH_FFMPEG
@@ -104,11 +123,8 @@ struct hdaudio * sound_open_hdaudio(char * filename)
/* Find the first audio stream */
audioStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
-#ifdef FFMPEG_CODEC_IS_POINTER
- if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO)
-#else
- if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_AUDIO)
-#endif
+ if(get_codec_from_stream(pFormatCtx->streams[i])
+ ->codec_type == CODEC_TYPE_AUDIO)
{
audioStream=i;
break;
@@ -119,11 +135,7 @@ struct hdaudio * sound_open_hdaudio(char * filename)
return 0;
}
-#ifdef FFMPEG_CODEC_IS_POINTER
- pCodecCtx=pFormatCtx->streams[audioStream]->codec;
-#else
- pCodecCtx=&pFormatCtx->streams[audioStream]->codec;
-#endif
+ pCodecCtx = get_codec_from_stream(pFormatCtx->streams[audioStream]);
/* Find the decoder for the audio stream */
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
@@ -133,11 +145,6 @@ struct hdaudio * sound_open_hdaudio(char * filename)
return 0;
}
-#if 0
- if(pCodec->capabilities & CODEC_CAP_TRUNCATED)
- pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
-#endif
-
if(avcodec_open(pCodecCtx, pCodec)<0) {
avcodec_close(pCodecCtx);
av_close_input_file(pFormatCtx);
@@ -155,22 +162,23 @@ struct hdaudio * sound_open_hdaudio(char * filename)
rval->pCodecCtx = pCodecCtx;
rval->pCodec = pCodec;
rval->audioStream = audioStream;
- rval->frame_position = -1;
+ rval->frame_position = -10;
- /* FIXME: This only works with integer frame rates ... */
- rval->frame_duration = AV_TIME_BASE;
+ rval->frame_duration = AV_TIME_BASE / 10;
+ rval->frame_alloc_duration = AV_TIME_BASE;
rval->decode_cache_size =
(long long) rval->sample_rate * rval->channels
- * rval->frame_duration / AV_TIME_BASE
+ * rval->frame_alloc_duration / AV_TIME_BASE
* 2;
rval->decode_cache = (short*) MEM_mallocN(
rval->decode_cache_size * sizeof(short),
"hdaudio decode cache");
-
+ rval->decode_pos = 0;
rval->target_channels = -1;
rval->target_rate = -1;
rval->resampler = 0;
+ rval->resample_cache = 0;
return rval;
#else
return 0;
@@ -195,21 +203,27 @@ long sound_hdaudio_get_duration(struct hdaudio * hdaudio, int frame_rate)
#endif
}
-void sound_hdaudio_extract(struct hdaudio * hdaudio,
- short * target_buffer,
- int sample_position /* units of target_rate */,
- int target_rate,
- int target_channels,
- int nb_samples /* in target */)
-{
#ifdef WITH_FFMPEG
+static void sound_hdaudio_extract_small_block(
+ struct hdaudio * hdaudio,
+ short * target_buffer,
+ int sample_position /* units of target_rate */,
+ int target_rate,
+ int target_channels,
+ int nb_samples /* in target */)
+{
AVPacket packet;
int frame_position;
int frame_size = (long long) target_rate
* hdaudio->frame_duration / AV_TIME_BASE;
+ int in_frame_size = (long long) hdaudio->sample_rate
+ * hdaudio->frame_duration / AV_TIME_BASE;
int rate_conversion =
(target_rate != hdaudio->sample_rate)
|| (target_channels != hdaudio->channels);
+ int sample_ofs = target_channels * (sample_position % frame_size);
+
+ frame_position = sample_position / frame_size;
if (hdaudio == 0) return;
@@ -226,94 +240,261 @@ void sound_hdaudio_extract(struct hdaudio * hdaudio,
target_rate, hdaudio->sample_rate);
hdaudio->target_rate = target_rate;
hdaudio->target_channels = target_channels;
+ if (hdaudio->resample_cache) {
+ MEM_freeN(hdaudio->resample_cache);
+ }
+
+
+ hdaudio->resample_cache = (short*) MEM_mallocN(
+ (long long)
+ hdaudio->target_channels
+ * frame_size * 2
+ * sizeof(short),
+ "hdaudio resample cache");
+
+ if (frame_position == hdaudio->frame_position) {
+ audio_resample(hdaudio->resampler,
+ hdaudio->resample_cache,
+ hdaudio->decode_cache_zero,
+ in_frame_size * 7 / 4);
+ }
}
}
- frame_position = sample_position / frame_size;
+ if (frame_position == hdaudio->frame_position + 1
+ && in_frame_size * hdaudio->channels <= hdaudio->decode_pos) {
+ int bl_size = in_frame_size * hdaudio->channels;
+ int decode_pos = hdaudio->decode_pos;
+
+ hdaudio->frame_position = frame_position;
+
+ memcpy(hdaudio->decode_cache,
+ hdaudio->decode_cache + bl_size,
+ (decode_pos - bl_size) * sizeof(short));
+
+ decode_pos -= bl_size;
+
+ while(av_read_frame(hdaudio->pFormatCtx, &packet) >= 0) {
+ int data_size;
+ int len;
+ uint8_t *audio_pkt_data;
+ int audio_pkt_size;
+
+ if(packet.stream_index != hdaudio->audioStream) {
+ av_free_packet(&packet);
+ continue;
+ }
+
+ audio_pkt_data = packet.data;
+ audio_pkt_size = packet.size;
+
+ while (audio_pkt_size > 0) {
+ len = avcodec_decode_audio(
+ hdaudio->pCodecCtx,
+ hdaudio->decode_cache
+ + decode_pos,
+ &data_size,
+ audio_pkt_data,
+ audio_pkt_size);
+ if (data_size <= 0) {
+ continue;
+ }
+ if (len < 0) {
+ audio_pkt_size = 0;
+ break;
+ }
+
+ audio_pkt_size -= len;
+ audio_pkt_data += len;
+
+ decode_pos += data_size / sizeof(short);
+ if (decode_pos + data_size
+ / sizeof(short)
+ > hdaudio->decode_cache_size) {
+ break;
+ }
+ }
+ av_free_packet(&packet);
+
+ if (decode_pos + data_size / sizeof(short)
+ > hdaudio->decode_cache_size) {
+ break;
+ }
+ }
+
+ if (rate_conversion) {
+ audio_resample(hdaudio->resampler,
+ hdaudio->resample_cache,
+ hdaudio->decode_cache_zero,
+ in_frame_size * 7 / 4);
+ }
+
+ hdaudio->decode_pos = decode_pos;
+ }
if (frame_position != hdaudio->frame_position) {
long decode_pos = 0;
+ long long st_time = hdaudio->pFormatCtx
+ ->streams[hdaudio->audioStream]->start_time;
+ double time_base =
+ av_q2d(hdaudio->pFormatCtx
+ ->streams[hdaudio->audioStream]->time_base);
+ long long pos = frame_position * AV_TIME_BASE
+ * hdaudio->frame_duration / AV_TIME_BASE;
hdaudio->frame_position = frame_position;
+ if (st_time == AV_NOPTS_VALUE) {
+ st_time = 0;
+ }
+
+ pos += st_time * AV_TIME_BASE * time_base;
+
av_seek_frame(hdaudio->pFormatCtx, -1,
- (long long) frame_position * AV_TIME_BASE,
+ pos,
AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
+ avcodec_flush_buffers(hdaudio->pCodecCtx);
+
+ hdaudio->decode_cache_zero = 0;
while(av_read_frame(hdaudio->pFormatCtx, &packet) >= 0) {
- if(packet.stream_index == hdaudio->audioStream) {
- int data_size;
- int len;
- uint8_t *audio_pkt_data;
- int audio_pkt_size;
-
- audio_pkt_data = packet.data;
- audio_pkt_size = packet.size;
-
- while (audio_pkt_size > 0) {
- len = avcodec_decode_audio(
- hdaudio->pCodecCtx,
- hdaudio->decode_cache
- + decode_pos,
- &data_size,
- audio_pkt_data,
- audio_pkt_size);
- if (data_size <= 0) {
- continue;
- }
- if (len < 0) {
- audio_pkt_size = 0;
- break;
+ int data_size;
+ int len;
+ uint8_t *audio_pkt_data;
+ int audio_pkt_size;
+
+ if(packet.stream_index != hdaudio->audioStream) {
+ av_free_packet(&packet);
+ continue;
+ }
+
+ audio_pkt_data = packet.data;
+ audio_pkt_size = packet.size;
+
+ if (!hdaudio->decode_cache_zero
+ && audio_pkt_size > 0) {
+ long long diff;
+
+ if (packet.pts == AV_NOPTS_VALUE) {
+ fprintf(stderr,
+ "hdaudio: audio "
+ "pts=NULL audio "
+ "distortion!\n");
+ diff = 0;
+ } else {
+ long long pts = packet.pts;
+ long long spts = (long long) (
+ pos / time_base / AV_TIME_BASE
+ + 0.5);
+ diff = spts - pts;
+ if (diff < 0) {
+ fprintf(stderr,
+ "hdaudio: "
+ "negative seek: "
+ "%lld < %lld "
+ "audio distortion!!\n",
+ spts, pts);
+ diff = 0;
}
+ }
- audio_pkt_size -= len;
- audio_pkt_data += len;
- decode_pos +=
- data_size / sizeof(short);
- if (decode_pos + data_size
- / sizeof(short)
- > hdaudio->decode_cache_size) {
- av_free_packet(&packet);
- break;
- }
+ diff *= hdaudio->sample_rate * time_base;
+ diff *= hdaudio->channels;
+
+ if (diff > hdaudio->decode_cache_size / 2) {
+ fprintf(stderr,
+ "hdaudio: audio "
+ "diff too large!!\n");
+ diff = 0;
+ }
+
+ hdaudio->decode_cache_zero
+ = hdaudio->decode_cache + diff;
+ }
+
+ while (audio_pkt_size > 0) {
+ len = avcodec_decode_audio(
+ hdaudio->pCodecCtx,
+ hdaudio->decode_cache
+ + decode_pos,
+ &data_size,
+ audio_pkt_data,
+ audio_pkt_size);
+ if (data_size <= 0) {
+ continue;
}
- if (decode_pos + data_size / sizeof(short)
+ if (len < 0) {
+ audio_pkt_size = 0;
+ break;
+ }
+
+ audio_pkt_size -= len;
+ audio_pkt_data += len;
+
+ decode_pos += data_size / sizeof(short);
+ if (decode_pos + data_size
+ / sizeof(short)
> hdaudio->decode_cache_size) {
break;
}
}
+
av_free_packet(&packet);
+
+ if (decode_pos + data_size / sizeof(short)
+ > hdaudio->decode_cache_size) {
+ break;
+ }
+ }
+ if (rate_conversion) {
+ audio_resample(hdaudio->resampler,
+ hdaudio->resample_cache,
+ hdaudio->decode_cache_zero,
+ in_frame_size * 7 / 4);
}
+ hdaudio->decode_pos = decode_pos;
}
- if (!rate_conversion) {
- int ofs = target_channels * (sample_position % frame_size);
- memcpy(target_buffer,
- hdaudio->decode_cache + ofs,
- nb_samples * target_channels * sizeof(short));
- } else {
- double ratio = (double) hdaudio->sample_rate / target_rate;
- long in_samples = (long) ((nb_samples + 16) * ratio);
- short temp_buffer[target_channels * (nb_samples + 64)];
-
- int s = audio_resample(hdaudio->resampler,
- temp_buffer,
- hdaudio->decode_cache
- + target_channels *
- (long)
- (ratio*(sample_position % frame_size)),
- in_samples);
- if (s < nb_samples || s > nb_samples + 63) {
- fprintf(stderr, "resample ouch: %d != %d\n",
- s, nb_samples);
- }
- memcpy(target_buffer, temp_buffer,
- nb_samples * target_channels * sizeof(short));
+ memcpy(target_buffer, (rate_conversion
+ ? hdaudio->resample_cache
+ : hdaudio->decode_cache_zero) + sample_ofs,
+ nb_samples * target_channels * sizeof(short));
+}
+#endif
+
+
+void sound_hdaudio_extract(struct hdaudio * hdaudio,
+ short * target_buffer,
+ int sample_position /* units of target_rate */,
+ int target_rate,
+ int target_channels,
+ int nb_samples /* in target */)
+{
+#ifdef WITH_FFMPEG
+ long long max_samples = (long long) target_rate
+ * hdaudio->frame_duration / AV_TIME_BASE / 4;
+
+ while (nb_samples > max_samples) {
+ sound_hdaudio_extract_small_block(hdaudio, target_buffer,
+ sample_position,
+ target_rate,
+ target_channels,
+ max_samples);
+ target_buffer += max_samples * target_channels;
+ sample_position += max_samples;
+ nb_samples -= max_samples;
+ }
+ if (nb_samples > 0) {
+ sound_hdaudio_extract_small_block(hdaudio, target_buffer,
+ sample_position,
+ target_rate,
+ target_channels,
+ nb_samples);
}
#else
-#endif
+#endif
}
void sound_close_hdaudio(struct hdaudio * hdaudio)
@@ -324,6 +505,9 @@ void sound_close_hdaudio(struct hdaudio * hdaudio)
avcodec_close(hdaudio->pCodecCtx);
av_close_input_file(hdaudio->pFormatCtx);
MEM_freeN (hdaudio->decode_cache);
+ if (hdaudio->resample_cache) {
+ MEM_freeN(hdaudio->resample_cache);
+ }
free(hdaudio->filename);
MEM_freeN (hdaudio);
}
diff --git a/source/blender/src/seqeffects.c b/source/blender/src/seqeffects.c
new file mode 100644
index 00000000000..d1d04a7eb96
--- /dev/null
+++ b/source/blender/src/seqeffects.c
@@ -0,0 +1,2515 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+#include "PIL_dynlib.h"
+#include "BKE_plugin_types.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "DNA_sequence_types.h"
+#include "BSE_seqeffects.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "DNA_sequence_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_global.h"
+#include "BKE_ipo.h"
+#include "BKE_texture.h"
+#include "BIF_toolbox.h"
+#include "BIF_interface.h"
+
+#include "BSE_sequence.h"
+
+#include "RE_pipeline.h" // talks to entire render API
+
+#include "blendef.h"
+
+/* Glow effect */
+enum {
+ GlowR=0,
+ GlowG=1,
+ GlowB=2,
+ GlowA=3
+};
+
+
+/* **********************************************************************
+ PLUGINS
+ ********************************************************************** */
+
+static void open_plugin_seq(PluginSeq *pis, const char *seqname)
+{
+ int (*version)();
+ void* (*alloc_private)();
+ char *cp;
+
+ /* to be sure: (is tested for) */
+ pis->doit= 0;
+ pis->pname= 0;
+ pis->varstr= 0;
+ pis->cfra= 0;
+ pis->version= 0;
+ pis->instance_private_data = 0;
+
+ /* clear the error list */
+ PIL_dynlib_get_error_as_string(NULL);
+
+ /* if(pis->handle) PIL_dynlib_close(pis->handle); */
+ /* pis->handle= 0; */
+
+ /* open the needed object */
+ pis->handle= PIL_dynlib_open(pis->name);
+ if(test_dlerr(pis->name, pis->name)) return;
+
+ if (pis->handle != 0) {
+ /* find the address of the version function */
+ version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
+ if (test_dlerr(pis->name, "plugin_seq_getversion")) return;
+
+ if (version != 0) {
+ pis->version= version();
+ if (pis->version==2 || pis->version==3) {
+ int (*info_func)(PluginInfo *);
+ PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");;
+
+ info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo");
+
+ if(info_func == NULL) error("No info func");
+ else {
+ info_func(info);
+
+ pis->pname= info->name;
+ pis->vars= info->nvars;
+ pis->cfra= info->cfra;
+
+ pis->varstr= info->varstr;
+
+ pis->doit= (void(*)(void))info->seq_doit;
+ if (info->init)
+ info->init();
+ }
+ MEM_freeN(info);
+
+ cp= PIL_dynlib_find_symbol(pis->handle, "seqname");
+ if(cp) strncpy(cp, seqname, 21);
+ } else {
+ printf ("Plugin returned unrecognized version number\n");
+ return;
+ }
+ }
+ alloc_private = (void* (*)())PIL_dynlib_find_symbol(
+ pis->handle, "plugin_seq_alloc_private_data");
+ if (alloc_private) {
+ pis->instance_private_data = alloc_private();
+ }
+
+ pis->current_private_data = (void**)
+ PIL_dynlib_find_symbol(
+ pis->handle, "plugin_private_data");
+ }
+}
+
+static PluginSeq *add_plugin_seq(const char *str, const char *seqname)
+{
+ PluginSeq *pis;
+ VarStruct *varstr;
+ int a;
+
+ pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq");
+
+ strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE);
+ open_plugin_seq(pis, seqname);
+
+ if(pis->doit==0) {
+ if(pis->handle==0) error("no plugin: %s", str);
+ else error("in plugin: %s", str);
+ MEM_freeN(pis);
+ return 0;
+ }
+
+ /* default values */
+ varstr= pis->varstr;
+ for(a=0; a<pis->vars; a++, varstr++) {
+ if( (varstr->type & FLO)==FLO)
+ pis->data[a]= varstr->def;
+ else if( (varstr->type & INT)==INT)
+ *((int *)(pis->data+a))= (int) varstr->def;
+ }
+
+ return pis;
+}
+
+static void free_plugin_seq(PluginSeq *pis)
+{
+ if(pis==0) return;
+
+ /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */
+
+ if (pis->instance_private_data) {
+ void (*free_private)(void *);
+
+ free_private = (void (*)(void *))PIL_dynlib_find_symbol(
+ pis->handle, "plugin_seq_free_private_data");
+ if (free_private) {
+ free_private(pis->instance_private_data);
+ }
+ }
+
+ MEM_freeN(pis);
+}
+
+static void init_plugin(Sequence * seq, const char * fname)
+{
+ seq->plugin= (PluginSeq *)add_plugin_seq(fname, seq->name+2);
+}
+
+static void load_plugin(Sequence * seq)
+{
+ if (seq) {
+ open_plugin_seq(seq->plugin, seq->name+2);
+ }
+}
+
+static void copy_plugin(Sequence * dst, Sequence * src)
+{
+ if(src->plugin) {
+ dst->plugin= MEM_dupallocN(src->plugin);
+ open_plugin_seq(dst->plugin, dst->name+2);
+ }
+}
+
+static void do_plugin_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ char *cp;
+
+ if(seq->plugin && seq->plugin->doit) {
+ if(seq->plugin->cfra)
+ *(seq->plugin->cfra)= frame_to_float(cfra);
+
+ cp = PIL_dynlib_find_symbol(
+ seq->plugin->handle, "seqname");
+
+ if(cp) strncpy(cp, seq->name+2, 22);
+
+ if (seq->plugin->current_private_data) {
+ *seq->plugin->current_private_data
+ = seq->plugin->instance_private_data;
+ }
+
+ if (seq->plugin->version<=2) {
+ if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
+ if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
+ if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
+ }
+
+ ((SeqDoit)seq->plugin->doit)(
+ seq->plugin->data, facf0, facf1, x, y,
+ ibuf1, ibuf2, out, ibuf3);
+
+ if (seq->plugin->version<=2) {
+ if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1);
+ if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2);
+ if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3);
+ IMB_convert_rgba_to_abgr(out);
+ }
+ }
+}
+
+static int do_plugin_early_out(struct Sequence *seq,
+ float facf0, float facf1)
+{
+ return 0;
+}
+
+static void free_plugin(struct Sequence * seq)
+{
+ free_plugin_seq(seq->plugin);
+ seq->plugin = 0;
+}
+
+/* **********************************************************************
+ ALPHA OVER
+ ********************************************************************** */
+
+static void init_alpha_over_or_under(Sequence * seq)
+{
+ Sequence * seq1 = seq->seq1;
+ Sequence * seq2 = seq->seq2;
+
+ seq->seq2= seq1;
+ seq->seq1= seq2;
+}
+
+static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y,
+ char * rect1, char *rect2, char *out)
+{
+ int fac2, mfac, fac, fac4;
+ int xo, tempc;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac2= (int)(256.0*facf0);
+ fac4= (int)(256.0*facf1);
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ /* rt = rt1 over rt2 (alpha from rt1) */
+
+ fac= fac2;
+ mfac= 256 - ( (fac2*rt1[3])>>8 );
+
+ if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ else {
+ tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
+ if(tempc>255) rt[0]= 255; else rt[0]= tempc;
+ tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
+ if(tempc>255) rt[1]= 255; else rt[1]= tempc;
+ tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
+ if(tempc>255) rt[2]= 255; else rt[2]= tempc;
+ tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
+ if(tempc>255) rt[3]= 255; else rt[3]= tempc;
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ fac= fac4;
+ mfac= 256 - ( (fac4*rt1[3])>>8 );
+
+ if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ else {
+ tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
+ if(tempc>255) rt[0]= 255; else rt[0]= tempc;
+ tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
+ if(tempc>255) rt[1]= 255; else rt[1]= tempc;
+ tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
+ if(tempc>255) rt[2]= 255; else rt[2]= tempc;
+ tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
+ if(tempc>255) rt[3]= 255; else rt[3]= tempc;
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+static void do_alphaover_effect_float(float facf0, float facf1, int x, int y,
+ float * rect1, float *rect2, float *out)
+{
+ float fac2, mfac, fac, fac4;
+ int xo;
+ float *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= rect1;
+ rt2= rect2;
+ rt= out;
+
+ fac2= facf0;
+ fac4= facf1;
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ /* rt = rt1 over rt2 (alpha from rt1) */
+
+ fac= fac2;
+ mfac= 1.0 - (fac2*rt1[3]) ;
+
+ if(fac <= 0.0) {
+ memcpy(rt, rt2, 4 * sizeof(float));
+ } else if(mfac <=0) {
+ memcpy(rt, rt1, 4 * sizeof(float));
+ } else {
+ rt[0] = fac*rt1[0] + mfac*rt2[0];
+ rt[1] = fac*rt1[1] + mfac*rt2[1];
+ rt[2] = fac*rt1[2] + mfac*rt2[2];
+ rt[3] = fac*rt1[3] + mfac*rt2[3];
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ fac= fac4;
+ mfac= 1.0 - (fac4*rt1[3]);
+
+ if(fac <= 0.0) {
+ memcpy(rt, rt2, 4 * sizeof(float));
+ } else if(mfac <= 0.0) {
+ memcpy(rt, rt1, 4 * sizeof(float));
+ } else {
+ rt[0] = fac*rt1[0] + mfac*rt2[0];
+ rt[1] = fac*rt1[1] + mfac*rt2[1];
+ rt[2] = fac*rt1[2] + mfac*rt2[2];
+ rt[3] = fac*rt1[3] + mfac*rt2[3];
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+static void do_alphaover_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_alphaover_effect_float(
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_alphaover_effect_byte(
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+
+/* **********************************************************************
+ ALPHA UNDER
+ ********************************************************************** */
+
+void do_alphaunder_effect_byte(
+ float facf0, float facf1, int x, int y, char *rect1,
+ char *rect2, char *out)
+{
+ int fac2, mfac, fac, fac4;
+ int xo;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= rect1;
+ rt2= rect2;
+ rt= out;
+
+ fac2= (int)(256.0*facf0);
+ fac4= (int)(256.0*facf1);
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ /* rt = rt1 under rt2 (alpha from rt2) */
+
+ /* this complex optimalisation is because the
+ * 'skybuf' can be crossed in
+ */
+ if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else {
+ mfac= rt2[3];
+ fac= (fac2*(256-mfac))>>8;
+
+ if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else {
+ rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
+ rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
+ rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
+ rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
+ }
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
+ else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else {
+ mfac= rt2[3];
+ fac= (fac4*(256-mfac))>>8;
+
+ if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
+ else {
+ rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
+ rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
+ rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
+ rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
+ }
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+
+static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y,
+ float *rect1, float *rect2,
+ float *out)
+{
+ float fac2, mfac, fac, fac4;
+ int xo;
+ float *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= rect1;
+ rt2= rect2;
+ rt= out;
+
+ fac2= facf0;
+ fac4= facf1;
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ /* rt = rt1 under rt2 (alpha from rt2) */
+
+ /* this complex optimalisation is because the
+ * 'skybuf' can be crossed in
+ */
+ if( rt2[3]<=0 && fac2>=1.0) {
+ memcpy(rt, rt1, 4 * sizeof(float));
+ } else if(rt2[3]>=1.0) {
+ memcpy(rt, rt2, 4 * sizeof(float));
+ } else {
+ mfac = rt2[3];
+ fac = fac2 * (1.0 - mfac);
+
+ if(fac == 0) {
+ memcpy(rt, rt2, 4 * sizeof(float));
+ } else {
+ rt[0]= fac*rt1[0] + mfac*rt2[0];
+ rt[1]= fac*rt1[1] + mfac*rt2[1];
+ rt[2]= fac*rt1[2] + mfac*rt2[2];
+ rt[3]= fac*rt1[3] + mfac*rt2[3];
+ }
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ if(rt2[3]<=0 && fac4 >= 1.0) {
+ memcpy(rt, rt1, 4 * sizeof(float));
+
+ } else if(rt2[3]>=1.0) {
+ memcpy(rt, rt2, 4 * sizeof(float));
+ } else {
+ mfac= rt2[3];
+ fac= fac4*(1.0-mfac);
+
+ if(fac == 0) {
+ memcpy(rt, rt2, 4 * sizeof(float));
+ } else {
+ rt[0]= fac * rt1[0] + mfac * rt2[0];
+ rt[1]= fac * rt1[1] + mfac * rt2[1];
+ rt[2]= fac * rt1[2] + mfac * rt2[2];
+ rt[3]= fac * rt1[3] + mfac * rt2[3];
+ }
+ }
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+static void do_alphaunder_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_alphaunder_effect_float(
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_alphaunder_effect_byte(
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+
+/* **********************************************************************
+ CROSS
+ ********************************************************************** */
+
+void do_cross_effect_byte(float facf0, float facf1, int x, int y,
+ char *rect1, char *rect2,
+ char *out)
+{
+ int fac1, fac2, fac3, fac4;
+ int xo;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= rect1;
+ rt2= rect2;
+ rt= out;
+
+ fac2= (int)(256.0*facf0);
+ fac1= 256-fac2;
+ fac4= (int)(256.0*facf1);
+ fac3= 256-fac4;
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8;
+ rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8;
+ rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8;
+ rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8;
+ rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8;
+ rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8;
+ rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ }
+}
+
+void do_cross_effect_float(float facf0, float facf1, int x, int y,
+ float*rect1, float *rect2, float *out)
+{
+ int fac1, fac2, fac3, fac4;
+ int xo;
+ float *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= rect1;
+ rt2= rect2;
+ rt= out;
+
+ fac2= facf0;
+ fac1= 1.0 - fac2;
+ fac4= facf1;
+ fac3= 1.0 - fac4;
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= fac1*rt1[0] + fac2*rt2[0];
+ rt[1]= fac1*rt1[1] + fac2*rt2[1];
+ rt[2]= fac1*rt1[2] + fac2*rt2[2];
+ rt[3]= fac1*rt1[3] + fac2*rt2[3];
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= fac3*rt1[0] + fac4*rt2[0];
+ rt[1]= fac3*rt1[1] + fac4*rt2[1];
+ rt[2]= fac3*rt1[2] + fac4*rt2[2];
+ rt[3]= fac3*rt1[3] + fac4*rt2[3];
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ }
+}
+
+static void do_cross_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_cross_effect_float(
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_cross_effect_byte(
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+
+/* **********************************************************************
+ GAMMA CROSS
+ ********************************************************************** */
+
+/* copied code from initrender.c */
+static unsigned short *gamtab = 0;
+static unsigned short *igamtab1 = 0;
+static int gamma_tabs_refcount = 0;
+
+#define RE_GAMMA_TABLE_SIZE 400
+
+static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
+static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
+static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
+static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
+static float colour_domain_table[RE_GAMMA_TABLE_SIZE + 1];
+static float colour_step;
+static float inv_colour_step;
+static float valid_gamma;
+static float valid_inv_gamma;
+
+static void makeGammaTables(float gamma)
+{
+ /* we need two tables: one forward, one backward */
+ int i;
+
+ valid_gamma = gamma;
+ valid_inv_gamma = 1.0 / gamma;
+ colour_step = 1.0 / RE_GAMMA_TABLE_SIZE;
+ inv_colour_step = (float) RE_GAMMA_TABLE_SIZE;
+
+ /* We could squeeze out the two range tables to gain some memory. */
+ for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
+ colour_domain_table[i] = i * colour_step;
+ gamma_range_table[i] = pow(colour_domain_table[i],
+ valid_gamma);
+ inv_gamma_range_table[i] = pow(colour_domain_table[i],
+ valid_inv_gamma);
+ }
+
+ /* The end of the table should match 1.0 carefully. In order to avoid */
+ /* rounding errors, we just set this explicitly. The last segment may */
+ /* have a different lenght than the other segments, but our */
+ /* interpolation is insensitive to that. */
+ colour_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+ gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+ inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
+
+ /* To speed up calculations, we make these calc factor tables. They are */
+ /* multiplication factors used in scaling the interpolation. */
+ for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) {
+ gamfactor_table[i] = inv_colour_step
+ * (gamma_range_table[i + 1] - gamma_range_table[i]) ;
+ inv_gamfactor_table[i] = inv_colour_step
+ * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ;
+ }
+
+} /* end of void makeGammaTables(float gamma) */
+
+
+static float gammaCorrect(float c)
+{
+ int i;
+ float res = 0.0;
+
+ i = floor(c * inv_colour_step);
+ /* Clip to range [0,1]: outside, just do the complete calculation. */
+ /* We may have some performance problems here. Stretching up the LUT */
+ /* may help solve that, by exchanging LUT size for the interpolation. */
+ /* Negative colours are explicitly handled. */
+ if (i < 0) res = -pow(abs(c), valid_gamma);
+ else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma);
+ else res = gamma_range_table[i] +
+ ( (c - colour_domain_table[i]) * gamfactor_table[i]);
+
+ return res;
+} /* end of float gammaCorrect(float col) */
+
+/* ------------------------------------------------------------------------- */
+
+static float invGammaCorrect(float col)
+{
+ int i;
+ float res = 0.0;
+
+ i = floor(col*inv_colour_step);
+ /* Negative colours are explicitly handled. */
+ if (i < 0) res = -pow(abs(col), valid_inv_gamma);
+ else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma);
+ else res = inv_gamma_range_table[i] +
+ ( (col - colour_domain_table[i]) * inv_gamfactor_table[i]);
+
+ return res;
+} /* end of float invGammaCorrect(float col) */
+
+
+static void gamtabs(float gamma)
+{
+ float val, igamma= 1.0f/gamma;
+ int a;
+
+ gamtab= MEM_mallocN(65536*sizeof(short), "initGaus2");
+ igamtab1= MEM_mallocN(256*sizeof(short), "initGaus2");
+
+ /* gamtab: in short, out short */
+ for(a=0; a<65536; a++) {
+ val= a;
+ val/= 65535.0;
+
+ if(gamma==2.0) val= sqrt(val);
+ else if(gamma!=1.0) val= pow(val, igamma);
+
+ gamtab[a]= (65535.99*val);
+ }
+ /* inverse gamtab1 : in byte, out short */
+ for(a=1; a<=256; a++) {
+ if(gamma==2.0) igamtab1[a-1]= a*a-1;
+ else if(gamma==1.0) igamtab1[a-1]= 256*a-1;
+ else {
+ val= a/256.0;
+ igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ;
+ }
+ }
+
+}
+
+static void alloc_or_ref_gammatabs()
+{
+ if (gamma_tabs_refcount == 0) {
+ gamtabs(2.0f);
+ makeGammaTables(2.0f);
+ }
+ gamma_tabs_refcount++;
+}
+
+static void init_gammacross(Sequence * seq)
+{
+ alloc_or_ref_gammatabs();
+}
+
+static void load_gammacross(Sequence * seq)
+{
+ alloc_or_ref_gammatabs();
+}
+
+static void free_gammacross(Sequence * seq)
+{
+ if (--gamma_tabs_refcount == 0) {
+ MEM_freeN(gamtab);
+ MEM_freeN(igamtab1);
+ gamtab = 0;
+ igamtab1 = 0;
+ }
+ if (gamma_tabs_refcount < 0) {
+ fprintf(stderr, "seqeffects: free_gammacross double free!\n");
+ }
+}
+
+static void do_gammacross_effect_byte(float facf0, float facf1,
+ int x, int y,
+ char *rect1,
+ char *rect2,
+ char *out)
+{
+ int fac1, fac2, col;
+ int xo;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac2= (int)(256.0*facf0);
+ fac1= 256-fac2;
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
+ if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
+ if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
+ if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
+ if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
+ if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
+ if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
+ if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+ col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
+ if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+
+}
+
+static void do_gammacross_effect_float(float facf0, float facf1,
+ int x, int y,
+ float *rect1, float *rect2,
+ float *out)
+{
+ float fac1, fac2, col;
+ int xo;
+ float *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= rect1;
+ rt2= rect2;
+ rt= out;
+
+ fac2= facf0;
+ fac1= 1.0 - fac2;
+
+ while(y--) {
+
+ x= xo * 4;
+ while(x--) {
+
+ *rt= gammaCorrect(
+ fac1 * invGammaCorrect(*rt1)
+ + fac2 * invGammaCorrect(*rt2));
+ rt1++; rt2++; rt++;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo * 4;
+ while(x--) {
+
+ col= gammaCorrect(
+ fac1*invGammaCorrect(*rt1)
+ + fac2*invGammaCorrect(*rt2));
+
+ rt1++; rt2++; rt++;
+ }
+ }
+}
+
+static void do_gammacross_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_gammacross_effect_float(
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_gammacross_effect_byte(
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+
+/* **********************************************************************
+ ADD
+ ********************************************************************** */
+
+static void do_add_effect_byte(float facf0, float facf1, int x, int y,
+ unsigned char *rect1, unsigned char *rect2,
+ unsigned char *out)
+{
+ int col, xo, fac1, fac3;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac1= (int)(256.0*facf0);
+ fac3= (int)(256.0*facf1);
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ col= rt1[0]+ ((fac1*rt2[0])>>8);
+ if(col>255) rt[0]= 255; else rt[0]= col;
+ col= rt1[1]+ ((fac1*rt2[1])>>8);
+ if(col>255) rt[1]= 255; else rt[1]= col;
+ col= rt1[2]+ ((fac1*rt2[2])>>8);
+ if(col>255) rt[2]= 255; else rt[2]= col;
+ col= rt1[3]+ ((fac1*rt2[3])>>8);
+ if(col>255) rt[3]= 255; else rt[3]= col;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ col= rt1[0]+ ((fac3*rt2[0])>>8);
+ if(col>255) rt[0]= 255; else rt[0]= col;
+ col= rt1[1]+ ((fac3*rt2[1])>>8);
+ if(col>255) rt[1]= 255; else rt[1]= col;
+ col= rt1[2]+ ((fac3*rt2[2])>>8);
+ if(col>255) rt[2]= 255; else rt[2]= col;
+ col= rt1[3]+ ((fac3*rt2[3])>>8);
+ if(col>255) rt[3]= 255; else rt[3]= col;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+static void do_add_effect_float(float facf0, float facf1, int x, int y,
+ float *rect1, float *rect2,
+ float *out)
+{
+ int xo;
+ float fac1, fac3;
+ float *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= rect1;
+ rt2= rect2;
+ rt= out;
+
+ fac1= facf0;
+ fac3= facf1;
+
+ while(y--) {
+
+ x= xo * 4;
+ while(x--) {
+ *rt = *rt1 + fac1 * (*rt2);
+
+ rt1++; rt2++; rt++;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo * 4;
+ while(x--) {
+ *rt = *rt1 + fac3 * (*rt2);
+
+ rt1++; rt2++; rt++;
+ }
+ }
+}
+
+static void do_add_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_add_effect_float(
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_add_effect_byte(
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+
+/* **********************************************************************
+ SUB
+ ********************************************************************** */
+
+static void do_sub_effect_byte(float facf0, float facf1,
+ int x, int y,
+ char *rect1, char *rect2, char *out)
+{
+ int col, xo, fac1, fac3;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac1= (int)(256.0*facf0);
+ fac3= (int)(256.0*facf1);
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ col= rt1[0]- ((fac1*rt2[0])>>8);
+ if(col<0) rt[0]= 0; else rt[0]= col;
+ col= rt1[1]- ((fac1*rt2[1])>>8);
+ if(col<0) rt[1]= 0; else rt[1]= col;
+ col= rt1[2]- ((fac1*rt2[2])>>8);
+ if(col<0) rt[2]= 0; else rt[2]= col;
+ col= rt1[3]- ((fac1*rt2[3])>>8);
+ if(col<0) rt[3]= 0; else rt[3]= col;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ col= rt1[0]- ((fac3*rt2[0])>>8);
+ if(col<0) rt[0]= 0; else rt[0]= col;
+ col= rt1[1]- ((fac3*rt2[1])>>8);
+ if(col<0) rt[1]= 0; else rt[1]= col;
+ col= rt1[2]- ((fac3*rt2[2])>>8);
+ if(col<0) rt[2]= 0; else rt[2]= col;
+ col= rt1[3]- ((fac3*rt2[3])>>8);
+ if(col<0) rt[3]= 0; else rt[3]= col;
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+static void do_sub_effect_float(float facf0, float facf1, int x, int y,
+ float *rect1, float *rect2,
+ float *out)
+{
+ int xo;
+ float fac1, fac3;
+ float *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= rect1;
+ rt2= rect2;
+ rt= out;
+
+ fac1= facf0;
+ fac3= facf1;
+
+ while(y--) {
+
+ x= xo * 4;
+ while(x--) {
+ *rt = *rt1 - fac1 * (*rt2);
+
+ rt1++; rt2++; rt++;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo * 4;
+ while(x--) {
+ *rt = *rt1 - fac3 * (*rt2);
+
+ rt1++; rt2++; rt++;
+ }
+ }
+}
+
+static void do_sub_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_sub_effect_float(
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_sub_effect_byte(
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+/* **********************************************************************
+ DROP
+ ********************************************************************** */
+
+/* Must be > 0 or add precopy, etc to the function */
+#define XOFF 8
+#define YOFF 8
+
+static void do_drop_effect_byte(float facf0, float facf1, int x, int y,
+ unsigned char *rect2i, unsigned char *rect1i,
+ unsigned char *outi)
+{
+ int height, width, temp, fac, fac1, fac2;
+ char *rt1, *rt2, *out;
+ int field= 1;
+
+ width= x;
+ height= y;
+
+ fac1= (int)(70.0*facf0);
+ fac2= (int)(70.0*facf1);
+
+ rt2= (char*) (rect2i + YOFF*width);
+ rt1= (char*) rect1i;
+ out= (char*) outi;
+ for (y=0; y<height-YOFF; y++) {
+ if(field) fac= fac1;
+ else fac= fac2;
+ field= !field;
+
+ memcpy(out, rt1, sizeof(int)*XOFF);
+ rt1+= XOFF*4;
+ out+= XOFF*4;
+
+ for (x=XOFF; x<width; x++) {
+ temp= ((fac*rt2[3])>>8);
+
+ *(out++)= MAX2(0, *rt1 - temp); rt1++;
+ *(out++)= MAX2(0, *rt1 - temp); rt1++;
+ *(out++)= MAX2(0, *rt1 - temp); rt1++;
+ *(out++)= MAX2(0, *rt1 - temp); rt1++;
+ rt2+=4;
+ }
+ rt2+=XOFF*4;
+ }
+ memcpy(out, rt1, sizeof(int)*YOFF*width);
+}
+
+static void do_drop_effect_float(float facf0, float facf1, int x, int y,
+ float *rect2i, float *rect1i,
+ float *outi)
+{
+ int height, width;
+ float temp, fac, fac1, fac2;
+ float *rt1, *rt2, *out;
+ int field= 1;
+
+ width= x;
+ height= y;
+
+ fac1= 70.0*facf0;
+ fac2= 70.0*facf1;
+
+ rt2= (rect2i + YOFF*width);
+ rt1= rect1i;
+ out= outi;
+ for (y=0; y<height-YOFF; y++) {
+ if(field) fac= fac1;
+ else fac= fac2;
+ field= !field;
+
+ memcpy(out, rt1, 4 * sizeof(float)*XOFF);
+ rt1+= XOFF*4;
+ out+= XOFF*4;
+
+ for (x=XOFF; x<width; x++) {
+ temp= fac * rt2[3];
+
+ *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
+ *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
+ *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
+ *(out++)= MAX2(0.0, *rt1 - temp); rt1++;
+ rt2+=4;
+ }
+ rt2+=XOFF*4;
+ }
+ memcpy(out, rt1, 4 * sizeof(float)*YOFF*width);
+}
+
+
+static void do_drop_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf * ibuf3,
+ struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_drop_effect_float(
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_drop_effect_byte(
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+/* **********************************************************************
+ MUL
+ ********************************************************************** */
+
+static void do_mul_effect_byte(float facf0, float facf1, int x, int y,
+ unsigned char *rect1, unsigned char *rect2,
+ unsigned char *out)
+{
+ int xo, fac1, fac3;
+ char *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= (char *)rect1;
+ rt2= (char *)rect2;
+ rt= (char *)out;
+
+ fac1= (int)(256.0*facf0);
+ fac3= (int)(256.0*facf1);
+
+ /* formula:
+ * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a
+ */
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16);
+ rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16);
+ rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16);
+ rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16);
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16);
+ rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16);
+ rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16);
+ rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16);
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+static void do_mul_effect_float(float facf0, float facf1, int x, int y,
+ float *rect1, float *rect2,
+ float *out)
+{
+ int xo;
+ float fac1, fac3;
+ float *rt1, *rt2, *rt;
+
+ xo= x;
+ rt1= rect1;
+ rt2= rect2;
+ rt= out;
+
+ fac1= facf0;
+ fac3= facf1;
+
+ /* formula:
+ * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a
+ */
+
+ while(y--) {
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= rt1[0] + fac1*rt1[0]*(rt2[0]-1.0);
+ rt[1]= rt1[1] + fac1*rt1[1]*(rt2[1]-1.0);
+ rt[2]= rt1[2] + fac1*rt1[2]*(rt2[2]-1.0);
+ rt[3]= rt1[3] + fac1*rt1[3]*(rt2[3]-1.0);
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+
+ if(y==0) break;
+ y--;
+
+ x= xo;
+ while(x--) {
+
+ rt[0]= rt1[0] + fac3*rt1[0]*(rt2[0]-1.0);
+ rt[1]= rt1[1] + fac3*rt1[1]*(rt2[1]-1.0);
+ rt[2]= rt1[2] + fac3*rt1[2]*(rt2[2]-1.0);
+ rt[3]= rt1[3] + fac3*rt1[3]*(rt2[3]-1.0);
+
+ rt1+= 4; rt2+= 4; rt+= 4;
+ }
+ }
+}
+
+static void do_mul_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_mul_effect_float(
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_mul_effect_byte(
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+/* **********************************************************************
+ WIPE
+ ********************************************************************** */
+
+// This function calculates the blur band for the wipe effects
+static float in_band(float width,float dist, float perc,int side,int dir){
+
+ float t1,t2,alpha,percwidth;
+ if(width == 0)
+ return (float)side;
+ if(side == 1)
+ percwidth = width * perc;
+ else
+ percwidth = width * (1 - perc);
+
+ if(width < dist)
+ return side;
+
+ t1 = dist / width; //percentange of width that is
+ t2 = 1 / width; //amount of alpha per % point
+
+ if(side == 1)
+ alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe
+ else
+ alpha = (1-perc) - (t1*t2*100);
+
+ if(dir == 0)
+ alpha = 1-alpha;
+ return alpha;
+}
+
+static float check_zone(int x, int y, int xo, int yo,
+ Sequence *seq, float facf0)
+{
+ float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist;
+ /*some future stuff
+ float hyp3,hyp4,b4,b5
+ */
+ float temp1,temp2,temp3,temp4; //some placeholder variables
+ float halfx = xo/2;
+ float halfy = yo/2;
+ float widthf,output=0;
+ WipeVars *wipe = (WipeVars *)seq->effectdata;
+ int width;
+
+ angle = wipe->angle;
+ if(angle < 0){
+ x = xo-x;
+ //y = yo-y
+ }
+ angle = pow(fabs(angle)/45,log(xo)/log(2));
+
+ posy = facf0 * yo;
+ if(wipe->forward){
+ posx = facf0 * xo;
+ posy = facf0 * yo;
+ } else{
+ posx = xo - facf0 * xo;
+ posy = yo - facf0 * yo;
+ }
+ switch (wipe->wipetype) {
+ case DO_SINGLE_WIPE:
+ width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
+ hwidth = (float)width/2.0;
+
+ if (angle == 0.0)angle = 0.000001;
+ b1 = posy - (-angle)*posx;
+ b2 = y - (-angle)*x;
+ hyp = fabs(angle*x+y+(-posy-angle*posx))/sqrt(angle*angle+1);
+ if(angle < 0){
+ temp1 = b1;
+ b1 = b2;
+ b2 = temp1;
+ }
+ if(wipe->forward){
+ if(b1 < b2)
+ output = in_band(width,hyp,facf0,1,1);
+ else
+ output = in_band(width,hyp,facf0,0,1);
+ }
+ else{
+ if(b1 < b2)
+ output = in_band(width,hyp,facf0,0,1);
+ else
+ output = in_band(width,hyp,facf0,1,1);
+ }
+ break;
+
+
+ case DO_DOUBLE_WIPE:
+ if(!wipe->forward)facf0 = 1-facf0; // Go the other direction
+
+ width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); // calculate the blur width
+ hwidth = (float)width/2.0;
+ if (angle == 0)angle = 0.000001;
+ b1 = posy/2 - (-angle)*posx/2;
+ b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
+ b2 = y - (-angle)*x;
+
+ hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
+ hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
+
+ temp1 = xo*(1-facf0/2)-xo*facf0/2;
+ temp2 = yo*(1-facf0/2)-yo*facf0/2;
+ pointdist = sqrt(temp1*temp1 + temp2*temp2);
+
+ if(b2 < b1 && b2 < b3 ){
+ if(hwidth < pointdist)
+ output = in_band(hwidth,hyp,facf0,0,1);
+ }
+ else if(b2 > b1 && b2 > b3 ){
+ if(hwidth < pointdist)
+ output = in_band(hwidth,hyp2,facf0,0,1);
+ }
+ else{
+ if( hyp < hwidth && hyp2 > hwidth )
+ output = in_band(hwidth,hyp,facf0,1,1);
+ else if( hyp > hwidth && hyp2 < hwidth )
+ output = in_band(hwidth,hyp2,facf0,1,1);
+ else
+ output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
+ }
+ if(!wipe->forward)output = 1-output;
+ break;
+ case DO_CLOCK_WIPE:
+ /*
+ temp1: angle of effect center in rads
+ temp2: angle of line through (halfx,halfy) and (x,y) in rads
+ temp3: angle of low side of blur
+ temp4: angle of high side of blur
+ */
+ output = 1-facf0;
+ widthf = wipe->edgeWidth*2*3.14159;
+ temp1 = 2 * 3.14159 * facf0;
+
+ if(wipe->forward){
+ temp1 = 2*3.14159-temp1;
+ }
+
+ x = x - halfx;
+ y = y - halfy;
+
+ temp2 = asin(abs(y)/sqrt(x*x + y*y));
+ if(x <= 0 && y >= 0)
+ temp2 = 3.14159 - temp2;
+ else if(x<=0 && y <= 0)
+ temp2 += 3.14159;
+ else if(x >= 0 && y <= 0)
+ temp2 = 2*3.14159 - temp2;
+
+ if(wipe->forward){
+ temp3 = temp1-(widthf/2)*facf0;
+ temp4 = temp1+(widthf/2)*(1-facf0);
+ }
+ else{
+ temp3 = temp1-(widthf/2)*(1-facf0);
+ temp4 = temp1+(widthf/2)*facf0;
+ }
+ if (temp3 < 0) temp3 = 0;
+ if (temp4 > 2*3.14159) temp4 = 2*3.14159;
+
+
+ if(temp2 < temp3)
+ output = 0;
+ else if (temp2 > temp4)
+ output = 1;
+ else
+ output = (temp2-temp3)/(temp4-temp3);
+ if(x == 0 && y == 0){
+ output = 1;
+ }
+ if(output != output)
+ output = 1;
+ if(wipe->forward)
+ output = 1 - output;
+ break;
+ /* BOX WIPE IS NOT WORKING YET */
+ /* case DO_CROSS_WIPE: */
+ /* BOX WIPE IS NOT WORKING YET */
+ /* case DO_BOX_WIPE:
+ if(invert)facf0 = 1-facf0;
+
+ width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
+ hwidth = (float)width/2.0;
+ if (angle == 0)angle = 0.000001;
+ b1 = posy/2 - (-angle)*posx/2;
+ b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
+ b2 = y - (-angle)*x;
+
+ hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
+ hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
+
+ temp1 = xo*(1-facf0/2)-xo*facf0/2;
+ temp2 = yo*(1-facf0/2)-yo*facf0/2;
+ pointdist = sqrt(temp1*temp1 + temp2*temp2);
+
+ if(b2 < b1 && b2 < b3 ){
+ if(hwidth < pointdist)
+ output = in_band(hwidth,hyp,facf0,0,1);
+ }
+ else if(b2 > b1 && b2 > b3 ){
+ if(hwidth < pointdist)
+ output = in_band(hwidth,hyp2,facf0,0,1);
+ }
+ else{
+ if( hyp < hwidth && hyp2 > hwidth )
+ output = in_band(hwidth,hyp,facf0,1,1);
+ else if( hyp > hwidth && hyp2 < hwidth )
+ output = in_band(hwidth,hyp2,facf0,1,1);
+ else
+ output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
+ }
+ if(invert)facf0 = 1-facf0;
+ angle = -1/angle;
+ b1 = posy/2 - (-angle)*posx/2;
+ b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
+ b2 = y - (-angle)*x;
+
+ hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
+ hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
+
+ if(b2 < b1 && b2 < b3 ){
+ if(hwidth < pointdist)
+ output *= in_band(hwidth,hyp,facf0,0,1);
+ }
+ else if(b2 > b1 && b2 > b3 ){
+ if(hwidth < pointdist)
+ output *= in_band(hwidth,hyp2,facf0,0,1);
+ }
+ else{
+ if( hyp < hwidth && hyp2 > hwidth )
+ output *= in_band(hwidth,hyp,facf0,1,1);
+ else if( hyp > hwidth && hyp2 < hwidth )
+ output *= in_band(hwidth,hyp2,facf0,1,1);
+ else
+ output *= in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
+ }
+
+ break;*/
+ case DO_IRIS_WIPE:
+ if(xo > yo) yo = xo;
+ else xo = yo;
+
+ if(!wipe->forward)
+ facf0 = 1-facf0;
+
+ width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
+ hwidth = (float)width/2.0;
+
+ temp1 = (halfx-(halfx)*facf0);
+ pointdist = sqrt(temp1*temp1 + temp1*temp1);
+
+ temp2 = sqrt((halfx-x)*(halfx-x) + (halfy-y)*(halfy-y));
+ if(temp2 > pointdist)
+ output = in_band(hwidth,fabs(temp2-pointdist),facf0,0,1);
+ else
+ output = in_band(hwidth,fabs(temp2-pointdist),facf0,1,1);
+
+ if(!wipe->forward)
+ output = 1-output;
+
+ break;
+ }
+ if (output < 0) output = 0;
+ else if(output > 1) output = 1;
+ return output;
+}
+
+static void init_wipe_effect(Sequence *seq)
+{
+ if(seq->effectdata)MEM_freeN(seq->effectdata);
+ seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars");
+}
+
+static void free_wipe_effect(Sequence *seq)
+{
+ if(seq->effectdata)MEM_freeN(seq->effectdata);
+ seq->effectdata = 0;
+}
+
+static void copy_wipe_effect(Sequence *dst, Sequence *src)
+{
+ dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1,
+ int x, int y,
+ unsigned char *rect1,
+ unsigned char *rect2, unsigned char *out)
+{
+ int xo, yo;
+ char *rt1, *rt2, *rt;
+ rt1 = (char *)rect1;
+ rt2 = (char *)rect2;
+ rt = (char *)out;
+
+ xo = x;
+ yo = y;
+ for(y=0;y<yo;y++) {
+ for(x=0;x<xo;x++) {
+ float check = check_zone(x,y,xo,yo,seq,facf0);
+ if (check) {
+ if (rt1) {
+ rt[0] = (int)(rt1[0]*check)+ (int)(rt2[0]*(1-check));
+ rt[1] = (int)(rt1[1]*check)+ (int)(rt2[1]*(1-check));
+ rt[2] = (int)(rt1[2]*check)+ (int)(rt2[2]*(1-check));
+ rt[3] = (int)(rt1[3]*check)+ (int)(rt2[3]*(1-check));
+ } else {
+ rt[0] = 0;
+ rt[1] = 0;
+ rt[2] = 0;
+ rt[3] = 255;
+ }
+ } else {
+ if (rt2) {
+ rt[0] = rt2[0];
+ rt[1] = rt2[1];
+ rt[2] = rt2[2];
+ rt[3] = rt2[3];
+ } else {
+ rt[0] = 0;
+ rt[1] = 0;
+ rt[2] = 0;
+ rt[3] = 255;
+ }
+ }
+
+ rt+=4;
+ if(rt1 !=NULL){
+ rt1+=4;
+ }
+ if(rt2 !=NULL){
+ rt2+=4;
+ }
+ }
+ }
+}
+
+static void do_wipe_effect_float(Sequence *seq, float facf0, float facf1,
+ int x, int y,
+ float *rect1,
+ float *rect2, float *out)
+{
+ int xo, yo;
+ float *rt1, *rt2, *rt;
+ rt1 = rect1;
+ rt2 = rect2;
+ rt = out;
+
+ xo = x;
+ yo = y;
+ for(y=0;y<yo;y++) {
+ for(x=0;x<xo;x++) {
+ float check = check_zone(x,y,xo,yo,seq,facf0);
+ if (check) {
+ if (rt1) {
+ rt[0] = rt1[0]*check+ rt2[0]*(1-check);
+ rt[1] = rt1[1]*check+ rt2[1]*(1-check);
+ rt[2] = rt1[2]*check+ rt2[2]*(1-check);
+ rt[3] = rt1[3]*check+ rt2[3]*(1-check);
+ } else {
+ rt[0] = 0;
+ rt[1] = 0;
+ rt[2] = 0;
+ rt[3] = 1.0;
+ }
+ } else {
+ if (rt2) {
+ rt[0] = rt2[0];
+ rt[1] = rt2[1];
+ rt[2] = rt2[2];
+ rt[3] = rt2[3];
+ } else {
+ rt[0] = 0;
+ rt[1] = 0;
+ rt[2] = 0;
+ rt[3] = 1.0;
+ }
+ }
+
+ rt+=4;
+ if(rt1 !=NULL){
+ rt1+=4;
+ }
+ if(rt2 !=NULL){
+ rt2+=4;
+ }
+ }
+ }
+}
+
+static void do_wipe_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_wipe_effect_float(seq,
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_wipe_effect_byte(seq,
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+/* **********************************************************************
+ GLOW
+ ********************************************************************** */
+
+static void RVBlurBitmap2_byte ( unsigned char* map, int width,int height,
+ float blur,
+ int quality)
+/* MUUUCCH better than the previous blur. */
+/* We do the blurring in two passes which is a whole lot faster. */
+/* I changed the math arount to implement an actual Gaussian */
+/* distribution. */
+/* */
+/* Watch out though, it tends to misbehaven with large blur values on */
+/* a small bitmap. Avoid avoid avoid. */
+/*=============================== */
+{
+ unsigned char* temp=NULL,*swap;
+ float *filter=NULL;
+ int x,y,i,fx,fy;
+ int index, ix, halfWidth;
+ float fval, k, curColor[3], curColor2[3], weight=0;
+
+ /* If we're not really blurring, bail out */
+ if (blur<=0)
+ return;
+
+ /* Allocate memory for the tempmap and the blur filter matrix */
+ temp= MEM_mallocN( (width*height*4), "blurbitmaptemp");
+ if (!temp)
+ return;
+
+ /* Allocate memory for the filter elements */
+ halfWidth = ((quality+1)*blur);
+ filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
+ if (!filter){
+ MEM_freeN (temp);
+ return;
+ }
+
+ /* Apparently we're calculating a bell curve */
+ /* based on the standard deviation (or radius) */
+ /* This code is based on an example */
+ /* posted to comp.graphics.algorithms by */
+ /* Blancmange (bmange@airdmhor.gen.nz) */
+
+ k = -1.0/(2.0*3.14159*blur*blur);
+ fval=0;
+ for (ix = 0;ix< halfWidth;ix++){
+ weight = (float)exp(k*(ix*ix));
+ filter[halfWidth - ix] = weight;
+ filter[halfWidth + ix] = weight;
+ }
+ filter[0] = weight;
+
+ /* Normalize the array */
+ fval=0;
+ for (ix = 0;ix< halfWidth*2;ix++)
+ fval+=filter[ix];
+
+ for (ix = 0;ix< halfWidth*2;ix++)
+ filter[ix]/=fval;
+
+ /* Blur the rows */
+ for (y=0;y<height;y++){
+ /* Do the left & right strips */
+ for (x=0;x<halfWidth;x++){
+ index=(x+y*width)*4;
+ fx=0;
+ curColor[0]=curColor[1]=curColor[2]=0;
+ curColor2[0]=curColor2[1]=curColor2[2]=0;
+
+ for (i=x-halfWidth;i<x+halfWidth;i++){
+ if ((i>=0)&&(i<width)){
+ curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
+ curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
+ curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
+
+ curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
+ filter[fx];
+ curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
+ filter[fx];
+ curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
+ filter[fx];
+ }
+ fx++;
+ }
+ temp[index+GlowR]=curColor[0];
+ temp[index+GlowG]=curColor[1];
+ temp[index+GlowB]=curColor[2];
+
+ temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
+ temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
+ temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
+
+ }
+ /* Do the main body */
+ for (x=halfWidth;x<width-halfWidth;x++){
+ index=(x+y*width)*4;
+ fx=0;
+ curColor[0]=curColor[1]=curColor[2]=0;
+ for (i=x-halfWidth;i<x+halfWidth;i++){
+ curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
+ curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
+ curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
+ fx++;
+ }
+ temp[index+GlowR]=curColor[0];
+ temp[index+GlowG]=curColor[1];
+ temp[index+GlowB]=curColor[2];
+ }
+ }
+
+ /* Swap buffers */
+ swap=temp;temp=map;map=swap;
+
+
+ /* Blur the columns */
+ for (x=0;x<width;x++){
+ /* Do the top & bottom strips */
+ for (y=0;y<halfWidth;y++){
+ index=(x+y*width)*4;
+ fy=0;
+ curColor[0]=curColor[1]=curColor[2]=0;
+ curColor2[0]=curColor2[1]=curColor2[2]=0;
+ for (i=y-halfWidth;i<y+halfWidth;i++){
+ if ((i>=0)&&(i<height)){
+ /* Bottom */
+ curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
+ curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
+ curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
+
+ /* Top */
+ curColor2[0]+=map[(x+(height-1-i)*width) *
+ 4+GlowR]*filter[fy];
+ curColor2[1]+=map[(x+(height-1-i)*width) *
+ 4+GlowG]*filter[fy];
+ curColor2[2]+=map[(x+(height-1-i)*width) *
+ 4+GlowB]*filter[fy];
+ }
+ fy++;
+ }
+ temp[index+GlowR]=curColor[0];
+ temp[index+GlowG]=curColor[1];
+ temp[index+GlowB]=curColor[2];
+ temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
+ temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
+ temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
+ }
+ /* Do the main body */
+ for (y=halfWidth;y<height-halfWidth;y++){
+ index=(x+y*width)*4;
+ fy=0;
+ curColor[0]=curColor[1]=curColor[2]=0;
+ for (i=y-halfWidth;i<y+halfWidth;i++){
+ curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
+ curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
+ curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
+ fy++;
+ }
+ temp[index+GlowR]=curColor[0];
+ temp[index+GlowG]=curColor[1];
+ temp[index+GlowB]=curColor[2];
+ }
+ }
+
+
+ /* Swap buffers */
+ swap=temp;temp=map;map=swap;
+
+ /* Tidy up */
+ MEM_freeN (filter);
+ MEM_freeN (temp);
+}
+
+static void RVBlurBitmap2_float ( float* map, int width,int height,
+ float blur,
+ int quality)
+/* MUUUCCH better than the previous blur. */
+/* We do the blurring in two passes which is a whole lot faster. */
+/* I changed the math arount to implement an actual Gaussian */
+/* distribution. */
+/* */
+/* Watch out though, it tends to misbehaven with large blur values on */
+/* a small bitmap. Avoid avoid avoid. */
+/*=============================== */
+{
+ float* temp=NULL,*swap;
+ float *filter=NULL;
+ int x,y,i,fx,fy;
+ int index, ix, halfWidth;
+ float fval, k, curColor[3], curColor2[3], weight=0;
+
+ /* If we're not really blurring, bail out */
+ if (blur<=0)
+ return;
+
+ /* Allocate memory for the tempmap and the blur filter matrix */
+ temp= MEM_mallocN( (width*height*4*sizeof(float)), "blurbitmaptemp");
+ if (!temp)
+ return;
+
+ /* Allocate memory for the filter elements */
+ halfWidth = ((quality+1)*blur);
+ filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
+ if (!filter){
+ MEM_freeN (temp);
+ return;
+ }
+
+ /* Apparently we're calculating a bell curve */
+ /* based on the standard deviation (or radius) */
+ /* This code is based on an example */
+ /* posted to comp.graphics.algorithms by */
+ /* Blancmange (bmange@airdmhor.gen.nz) */
+
+ k = -1.0/(2.0*3.14159*blur*blur);
+ fval=0;
+ for (ix = 0;ix< halfWidth;ix++){
+ weight = (float)exp(k*(ix*ix));
+ filter[halfWidth - ix] = weight;
+ filter[halfWidth + ix] = weight;
+ }
+ filter[0] = weight;
+
+ /* Normalize the array */
+ fval=0;
+ for (ix = 0;ix< halfWidth*2;ix++)
+ fval+=filter[ix];
+
+ for (ix = 0;ix< halfWidth*2;ix++)
+ filter[ix]/=fval;
+
+ /* Blur the rows */
+ for (y=0;y<height;y++){
+ /* Do the left & right strips */
+ for (x=0;x<halfWidth;x++){
+ index=(x+y*width)*4;
+ fx=0;
+ curColor[0]=curColor[1]=curColor[2]=0;
+ curColor2[0]=curColor2[1]=curColor2[2]=0;
+
+ for (i=x-halfWidth;i<x+halfWidth;i++){
+ if ((i>=0)&&(i<width)){
+ curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
+ curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
+ curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
+
+ curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
+ filter[fx];
+ curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
+ filter[fx];
+ curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
+ filter[fx];
+ }
+ fx++;
+ }
+ temp[index+GlowR]=curColor[0];
+ temp[index+GlowG]=curColor[1];
+ temp[index+GlowB]=curColor[2];
+
+ temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
+ temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
+ temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
+
+ }
+ /* Do the main body */
+ for (x=halfWidth;x<width-halfWidth;x++){
+ index=(x+y*width)*4;
+ fx=0;
+ curColor[0]=curColor[1]=curColor[2]=0;
+ for (i=x-halfWidth;i<x+halfWidth;i++){
+ curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
+ curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
+ curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
+ fx++;
+ }
+ temp[index+GlowR]=curColor[0];
+ temp[index+GlowG]=curColor[1];
+ temp[index+GlowB]=curColor[2];
+ }
+ }
+
+ /* Swap buffers */
+ swap=temp;temp=map;map=swap;
+
+
+ /* Blur the columns */
+ for (x=0;x<width;x++){
+ /* Do the top & bottom strips */
+ for (y=0;y<halfWidth;y++){
+ index=(x+y*width)*4;
+ fy=0;
+ curColor[0]=curColor[1]=curColor[2]=0;
+ curColor2[0]=curColor2[1]=curColor2[2]=0;
+ for (i=y-halfWidth;i<y+halfWidth;i++){
+ if ((i>=0)&&(i<height)){
+ /* Bottom */
+ curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
+ curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
+ curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
+
+ /* Top */
+ curColor2[0]+=map[(x+(height-1-i)*width) *
+ 4+GlowR]*filter[fy];
+ curColor2[1]+=map[(x+(height-1-i)*width) *
+ 4+GlowG]*filter[fy];
+ curColor2[2]+=map[(x+(height-1-i)*width) *
+ 4+GlowB]*filter[fy];
+ }
+ fy++;
+ }
+ temp[index+GlowR]=curColor[0];
+ temp[index+GlowG]=curColor[1];
+ temp[index+GlowB]=curColor[2];
+ temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
+ temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
+ temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
+ }
+ /* Do the main body */
+ for (y=halfWidth;y<height-halfWidth;y++){
+ index=(x+y*width)*4;
+ fy=0;
+ curColor[0]=curColor[1]=curColor[2]=0;
+ for (i=y-halfWidth;i<y+halfWidth;i++){
+ curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
+ curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
+ curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
+ fy++;
+ }
+ temp[index+GlowR]=curColor[0];
+ temp[index+GlowG]=curColor[1];
+ temp[index+GlowB]=curColor[2];
+ }
+ }
+
+
+ /* Swap buffers */
+ swap=temp;temp=map;map=swap;
+
+ /* Tidy up */
+ MEM_freeN (filter);
+ MEM_freeN (temp);
+}
+
+
+/* Adds two bitmaps and puts the results into a third map. */
+/* C must have been previously allocated but it may be A or B. */
+/* We clamp values to 255 to prevent weirdness */
+/*=============================== */
+static void RVAddBitmaps_byte (unsigned char* a, unsigned char* b, unsigned char* c, int width, int height)
+{
+ int x,y,index;
+
+ for (y=0;y<height;y++){
+ for (x=0;x<width;x++){
+ index=(x+y*width)*4;
+ c[index+GlowR]=MIN2(255,a[index+GlowR]+b[index+GlowR]);
+ c[index+GlowG]=MIN2(255,a[index+GlowG]+b[index+GlowG]);
+ c[index+GlowB]=MIN2(255,a[index+GlowB]+b[index+GlowB]);
+ c[index+GlowA]=MIN2(255,a[index+GlowA]+b[index+GlowA]);
+ }
+ }
+}
+
+static void RVAddBitmaps_float (float* a, float* b, float* c,
+ int width, int height)
+{
+ int x,y,index;
+
+ for (y=0;y<height;y++){
+ for (x=0;x<width;x++){
+ index=(x+y*width)*4;
+ c[index+GlowR]=MIN2(1.0,a[index+GlowR]+b[index+GlowR]);
+ c[index+GlowG]=MIN2(1.0,a[index+GlowG]+b[index+GlowG]);
+ c[index+GlowB]=MIN2(1.0,a[index+GlowB]+b[index+GlowB]);
+ c[index+GlowA]=MIN2(1.0,a[index+GlowA]+b[index+GlowA]);
+ }
+ }
+}
+
+/* For each pixel whose total luminance exceeds the threshold, */
+/* Multiply it's value by BOOST and add it to the output map */
+static void RVIsolateHighlights_byte (unsigned char* in, unsigned char* out,
+ int width, int height, int threshold,
+ float boost, float clamp)
+{
+ int x,y,index;
+ int intensity;
+
+
+ for(y=0;y< height;y++) {
+ for (x=0;x< width;x++) {
+ index= (x+y*width)*4;
+
+ /* Isolate the intensity */
+ intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
+ if (intensity>0){
+ out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255);
+ out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255);
+ out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255);
+ out[index+GlowA]=MIN2(255*clamp, (in[index+GlowA]*boost*intensity)/255);
+ }
+ else{
+ out[index+GlowR]=0;
+ out[index+GlowG]=0;
+ out[index+GlowB]=0;
+ out[index+GlowA]=0;
+ }
+ }
+ }
+}
+
+static void RVIsolateHighlights_float (float* in, float* out,
+ int width, int height, int threshold,
+ float boost, float clamp)
+{
+ int x,y,index;
+ float intensity;
+
+
+ for(y=0;y< height;y++) {
+ for (x=0;x< width;x++) {
+ index= (x+y*width)*4;
+
+ /* Isolate the intensity */
+ intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
+ if (intensity>0){
+ out[index+GlowR]=MIN2(clamp, (in[index+GlowR]*boost*intensity));
+ out[index+GlowG]=MIN2(clamp, (in[index+GlowG]*boost*intensity));
+ out[index+GlowB]=MIN2(clamp, (in[index+GlowB]*boost*intensity));
+ out[index+GlowA]=MIN2(clamp, (in[index+GlowA]*boost*intensity));
+ }
+ else{
+ out[index+GlowR]=0;
+ out[index+GlowG]=0;
+ out[index+GlowB]=0;
+ out[index+GlowA]=0;
+ }
+ }
+ }
+}
+
+static void init_glow_effect(Sequence *seq)
+{
+ GlowVars *glow;
+
+ if(seq->effectdata)MEM_freeN(seq->effectdata);
+ seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars");
+
+ glow = (GlowVars *)seq->effectdata;
+ glow->fMini = 0.25;
+ glow->fClamp = 1.0;
+ glow->fBoost = 0.5;
+ glow->dDist = 3.0;
+ glow->dQuality = 3;
+ glow->bNoComp = 0;
+}
+
+static void free_glow_effect(Sequence *seq)
+{
+ if(seq->effectdata)MEM_freeN(seq->effectdata);
+ seq->effectdata = 0;
+}
+
+static void copy_glow_effect(Sequence *dst, Sequence *src)
+{
+ dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use)
+static void do_glow_effect_byte(Sequence *seq, float facf0, float facf1,
+ int x, int y, char *rect1,
+ char *rect2, char *out)
+{
+ unsigned char *outbuf=(unsigned char *)out;
+ unsigned char *inbuf=(unsigned char *)rect1;
+ GlowVars *glow = (GlowVars *)seq->effectdata;
+
+ RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp);
+ RVBlurBitmap2_byte (outbuf, x, y, glow->dDist,glow->dQuality);
+ if (!glow->bNoComp)
+ RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y);
+}
+
+static void do_glow_effect_float(Sequence *seq, float facf0, float facf1,
+ int x, int y,
+ float *rect1, float *rect2, float *out)
+{
+ float *outbuf = out;
+ float *inbuf = rect1;
+ GlowVars *glow = (GlowVars *)seq->effectdata;
+
+ RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp);
+ RVBlurBitmap2_float (outbuf, x, y, glow->dDist,glow->dQuality);
+ if (!glow->bNoComp)
+ RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y);
+}
+
+static void do_glow_effect(Sequence * seq,int cfra,
+ float facf0, float facf1, int x, int y,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3, struct ImBuf *out)
+{
+ if (out->rect_float) {
+ do_glow_effect_float(seq,
+ facf0, facf1, x, y,
+ ibuf1->rect_float, ibuf2->rect_float,
+ out->rect_float);
+ } else {
+ do_glow_effect_byte(seq,
+ facf0, facf1, x, y,
+ (char*) ibuf1->rect, (char*) ibuf2->rect,
+ (char*) out->rect);
+ }
+}
+
+
+/* **********************************************************************
+ sequence effect factory
+ ********************************************************************** */
+
+
+static void init_noop(struct Sequence *seq)
+{
+
+}
+
+static void load_noop(struct Sequence *seq)
+{
+
+}
+
+static void init_plugin_noop(struct Sequence *seq, const char * fname)
+{
+
+}
+
+static void free_noop(struct Sequence *seq)
+{
+
+}
+
+static int early_out_noop(struct Sequence *seq,
+ float facf0, float facf1)
+{
+ return 0;
+}
+
+static int early_out_fade(struct Sequence *seq,
+ float facf0, float facf1)
+{
+ if (facf0 == 0.0 && facf1 == 0.0) {
+ return 1;
+ } else if (facf0 == 1.0 && facf1 == 1.0) {
+ return 2;
+ }
+ return 0;
+}
+
+static void get_default_fac_noop(struct Sequence *seq, int cfra,
+ float * facf0, float * facf1)
+{
+ *facf0 = *facf1 = 1.0;
+}
+
+static void get_default_fac_fade(struct Sequence *seq, int cfra,
+ float * facf0, float * facf1)
+{
+ *facf0 = (float)(cfra - seq->startdisp);
+ *facf1 = (float)(*facf0 + 0.5);
+ *facf0 /= seq->len;
+ *facf1 /= seq->len;
+}
+
+static void do_overdrop_effect(struct Sequence * seq, int cfra,
+ float fac, float facf,
+ int x, int y, struct ImBuf * ibuf1,
+ struct ImBuf * ibuf2,
+ struct ImBuf * ibuf3,
+ struct ImBuf * out)
+{
+ do_drop_effect(seq, cfra, fac, facf, x, y,
+ ibuf1, ibuf2, ibuf3, out);
+ do_alphaover_effect(seq, cfra, fac, facf, x, y,
+ ibuf1, ibuf2, ibuf3, out);
+}
+
+struct SeqEffectHandle get_sequence_effect(Sequence * seq)
+{
+ struct SeqEffectHandle rval;
+ int sequence_type = seq->type;
+
+ rval.init = init_noop;
+ rval.init_plugin = init_plugin_noop;
+ rval.load = load_noop;
+ rval.free = free_noop;
+ rval.early_out = early_out_noop;
+ rval.get_default_fac = get_default_fac_noop;
+ rval.execute = 0;
+
+ switch (sequence_type) {
+ case SEQ_CROSS:
+ rval.execute = do_cross_effect;
+ rval.early_out = early_out_fade;
+ rval.get_default_fac = get_default_fac_fade;
+ break;
+ case SEQ_GAMCROSS:
+ rval.init = init_gammacross;
+ rval.load = load_gammacross;
+ rval.free = free_gammacross;
+ rval.early_out = early_out_fade;
+ rval.get_default_fac = get_default_fac_fade;
+ rval.execute = do_gammacross_effect;
+ break;
+ case SEQ_ADD:
+ rval.execute = do_add_effect;
+ break;
+ case SEQ_SUB:
+ rval.execute = do_sub_effect;
+ break;
+ case SEQ_MUL:
+ rval.execute = do_mul_effect;
+ break;
+ case SEQ_ALPHAOVER:
+ rval.init = init_alpha_over_or_under;
+ rval.execute = do_alphaover_effect;
+ break;
+ case SEQ_OVERDROP:
+ rval.execute = do_overdrop_effect;
+ break;
+ case SEQ_ALPHAUNDER:
+ rval.init = init_alpha_over_or_under;
+ rval.execute = do_alphaunder_effect;
+ break;
+ case SEQ_WIPE:
+ rval.init = init_wipe_effect;
+ rval.free = free_wipe_effect;
+ rval.copy = copy_wipe_effect;
+ rval.early_out = early_out_fade;
+ rval.get_default_fac = get_default_fac_fade;
+ rval.execute = do_wipe_effect;
+ break;
+ case SEQ_GLOW:
+ rval.init = init_glow_effect;
+ rval.free = free_glow_effect;
+ rval.copy = copy_glow_effect;
+ rval.execute = do_glow_effect;
+ break;
+ case SEQ_PLUGIN:
+ rval.init_plugin = init_plugin;
+ rval.load = load_plugin;
+ rval.free = free_plugin;
+ rval.copy = copy_plugin;
+ rval.execute = do_plugin_effect;
+ rval.early_out = do_plugin_early_out;
+ rval.get_default_fac = get_default_fac_fade;
+ break;
+ }
+
+ if (seq->flag & SEQ_EFFECT_NOT_LOADED) {
+ rval.load(seq);
+ seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
+ }
+
+ return rval;
+}
diff --git a/source/blender/src/seqscopes.c b/source/blender/src/seqscopes.c
new file mode 100644
index 00000000000..a44a5261782
--- /dev/null
+++ b/source/blender/src/seqscopes.c
@@ -0,0 +1,340 @@
+/**
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Peter Schlaile < peter [at] schlaile [dot] de >
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ *
+ */
+
+#include "BSE_seqscopes.h"
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+#include "BKE_utildefines.h"
+#include <math.h>
+#include <string.h>
+
+static void rgb_to_yuv(float rgb[3], float yuv[3]) {
+ yuv[0]= 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
+ yuv[1]= 0.492*(rgb[2] - yuv[0]);
+ yuv[2]= 0.877*(rgb[0] - yuv[0]);
+
+ /* Normalize */
+ yuv[1]*= 255.0/(122*2.0);
+ yuv[1]+= 0.5;
+
+ yuv[2]*= 255.0/(157*2.0);
+ yuv[2]+= 0.5;
+}
+
+static void scope_put_pixel(unsigned char* table, unsigned char * pos)
+{
+ char newval = table[*pos];
+ pos[0] = pos[1] = pos[2] = newval;
+ pos[3] = 255;
+}
+
+static void wform_put_line(int w,
+ unsigned char * last_pos, unsigned char * new_pos)
+{
+ if (last_pos > new_pos) {
+ unsigned char* temp = new_pos;
+ new_pos = last_pos;
+ last_pos = temp;
+ }
+
+ while (last_pos < new_pos) {
+ if (last_pos[0] == 0) {
+ last_pos[0] = last_pos[1] = last_pos[2] = 32;
+ last_pos[3] = 255;
+ }
+ last_pos += 4*w;
+ }
+}
+
+static struct ImBuf *make_waveform_view_from_ibuf_byte(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ unsigned char* src = (unsigned char*) ibuf->rect;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < h; y++) {
+ unsigned char * last_p = 0;
+
+ for (x = 0; x < w; x++) {
+ unsigned char * rgb = src + 4 * (ibuf->x * y + x);
+ float v = 1.0 *
+ ( 0.299*rgb[0]
+ + 0.587*rgb[1]
+ + 0.114*rgb[2]) / 255.0;
+ unsigned char * p = tgt;
+ p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
+
+ scope_put_pixel(wtable, p);
+ p += 4 * w;
+ scope_put_pixel(wtable, p);
+
+ if (last_p != 0) {
+ wform_put_line(w, last_p, p);
+ }
+ last_p = p;
+ }
+ }
+
+ for (x = 0; x < w; x++) {
+ unsigned char * p = tgt + 4 * x;
+ p[1] = p[3] = 255.0;
+ p[4 * w + 1] = p[4 * w + 3] = 255.0;
+ p = tgt + 4 * (w * (h - 1) + x);
+ p[1] = p[3] = 255.0;
+ p[-4 * w + 1] = p[-4 * w + 3] = 255.0;
+ }
+
+ for (y = 0; y < h; y++) {
+ unsigned char * p = tgt + 4 * w * y;
+ p[1] = p[3] = 255.0;
+ p[4 + 1] = p[4 + 3] = 255.0;
+ p = tgt + 4 * (w * y + w - 1);
+ p[1] = p[3] = 255.0;
+ p[-4 + 1] = p[-4 + 3] = 255.0;
+ }
+
+ return rval;
+}
+
+static struct ImBuf *make_waveform_view_from_ibuf_float(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0);
+ int x,y;
+ float* src = ibuf->rect_float;
+ unsigned char* tgt = (unsigned char*) rval->rect;
+ int w = ibuf->x + 3;
+ int h = 515;
+ float waveform_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ waveform_gamma)*255);
+ }
+
+ for (y = 0; y < h; y++) {
+ unsigned char * last_p = 0;
+
+ for (x = 0; x < w; x++) {
+ float * rgb = src + 4 * (ibuf->x * y + x);
+ float v = 1.0 *
+ ( 0.299*rgb[0]
+ + 0.587*rgb[1]
+ + 0.114*rgb[2]);
+ unsigned char * p = tgt;
+
+ CLAMP(v, 0.0, 1.0);
+
+ p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
+
+ scope_put_pixel(wtable, p);
+ p += 4 * w;
+ scope_put_pixel(wtable, p);
+
+ if (last_p != 0) {
+ wform_put_line(w, last_p, p);
+ }
+ last_p = p;
+ }
+ }
+
+ for (x = 0; x < w; x++) {
+ unsigned char * p = tgt + 4 * x;
+ p[1] = p[3] = 255.0;
+ p[4 * w + 1] = p[4 * w + 3] = 255.0;
+ p = tgt + 4 * (w * (h - 1) + x);
+ p[1] = p[3] = 255.0;
+ p[-4 * w + 1] = p[-4 * w + 3] = 255.0;
+ }
+
+ for (y = 0; y < h; y++) {
+ unsigned char * p = tgt + 4 * w * y;
+ p[1] = p[3] = 255.0;
+ p[4 + 1] = p[4 + 3] = 255.0;
+ p = tgt + 4 * (w * y + w - 1);
+ p[1] = p[3] = 255.0;
+ p[-4 + 1] = p[-4 + 3] = 255.0;
+ }
+
+ return rval;
+}
+
+struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_waveform_view_from_ibuf_float(ibuf);
+ } else {
+ return make_waveform_view_from_ibuf_byte(ibuf);
+ }
+}
+
+
+static void vectorscope_put_cross(unsigned char r, unsigned char g,
+ unsigned char b,
+ char * tgt, int w, int h, int size)
+{
+ float rgb[3], yuv[3];
+ char * p;
+ int x = 0;
+ int y = 0;
+
+ rgb[0]= (float)r/255.0;
+ rgb[1]= (float)g/255.0;
+ rgb[2]= (float)b/255.0;
+ rgb_to_yuv(rgb, yuv);
+
+ p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
+ + (int) ((yuv[1] * (w - 3) + 1)));
+
+ if (r == 0 && g == 0 && b == 0) {
+ r = 255;
+ }
+
+ for (y = -size; y <= size; y++) {
+ for (x = -size; x <= size; x++) {
+ char * q = p + 4 * (y * w + x);
+ q[0] = r; q[1] = g; q[2] = b; q[3] = 255;
+ }
+ }
+}
+
+static struct ImBuf *make_vectorscope_view_from_ibuf_byte(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0);
+ int x,y;
+ char* src = (char*) ibuf->rect;
+ char* tgt = (char*) rval->rect;
+ float rgb[3], yuv[3];
+ int w = 515;
+ int h = 515;
+ float scope_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ scope_gamma)*255);
+ }
+
+ for (x = 0; x <= 255; x++) {
+ vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255 , x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ }
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ char * src1 = src + 4 * (ibuf->x * y + x);
+ char * p;
+
+ rgb[0]= (float)src1[0]/255.0;
+ rgb[1]= (float)src1[1]/255.0;
+ rgb[2]= (float)src1[2]/255.0;
+ rgb_to_yuv(rgb, yuv);
+
+ p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
+ + (int) ((yuv[1] * (w - 3) + 1)));
+ scope_put_pixel(wtable, p);
+ }
+ }
+
+ vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
+
+ return rval;
+}
+
+static struct ImBuf *make_vectorscope_view_from_ibuf_float(struct ImBuf * ibuf)
+{
+ struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0);
+ int x,y;
+ float* src = ibuf->rect_float;
+ char* tgt = (char*) rval->rect;
+ float rgb[3], yuv[3];
+ int w = 515;
+ int h = 515;
+ float scope_gamma = 0.2;
+ unsigned char wtable[256];
+
+ for (x = 0; x < 256; x++) {
+ wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
+ scope_gamma)*255);
+ }
+
+ for (x = 0; x <= 255; x++) {
+ vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1);
+ vectorscope_put_cross(255 , x, 0, tgt, w, h, 1);
+ vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
+ vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
+ vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
+ }
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ float * src1 = src + 4 * (ibuf->x * y + x);
+ char * p;
+
+ memcpy(rgb, src1, 3 * sizeof(float));
+
+ CLAMP(rgb[0], 0.0, 1.0);
+ CLAMP(rgb[1], 0.0, 1.0);
+ CLAMP(rgb[2], 0.0, 1.0);
+
+ rgb_to_yuv(rgb, yuv);
+
+ p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
+ + (int) ((yuv[1] * (w - 3) + 1)));
+ scope_put_pixel(wtable, p);
+ }
+ }
+
+ vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
+
+ return rval;
+}
+
+struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf)
+{
+ if (ibuf->rect_float) {
+ return make_vectorscope_view_from_ibuf_float(ibuf);
+ } else {
+ return make_vectorscope_view_from_ibuf_byte(ibuf);
+ }
+}
diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c
index 3fbe9735626..71c258bf3f6 100644
--- a/source/blender/src/sequence.c
+++ b/source/blender/src/sequence.c
@@ -23,7 +23,7 @@
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
- * Contributor(s): Peter Schlaile <peter@schlaile.de> 2005/2006
+ * Contributor(s): Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -33,7 +33,6 @@
#include <stdlib.h>
#include "MEM_guardedalloc.h"
-#include "PIL_dynlib.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
@@ -47,7 +46,6 @@
#include "DNA_view3d_types.h"
#include "BKE_utildefines.h"
-#include "BKE_plugin_types.h"
#include "BKE_global.h"
#include "BKE_texture.h"
#include "BKE_image.h"
@@ -64,138 +62,14 @@
#include "BIF_editsound.h"
#include "BSE_sequence.h"
+#include "BSE_seqeffects.h"
#include "RE_pipeline.h" // talks to entire render API
#include "blendef.h"
-static void do_build_seq_depend(Sequence * seq, int cfra);
-
int seqrectx, seqrecty;
-/* support for plugin sequences: */
-
-void open_plugin_seq(PluginSeq *pis, char *seqname)
-{
- int (*version)();
- void* (*alloc_private)();
- char *cp;
-
- /* to be sure: (is tested for) */
- pis->doit= 0;
- pis->pname= 0;
- pis->varstr= 0;
- pis->cfra= 0;
- pis->version= 0;
- pis->instance_private_data = 0;
-
- /* clear the error list */
- PIL_dynlib_get_error_as_string(NULL);
-
- /* if(pis->handle) PIL_dynlib_close(pis->handle); */
- /* pis->handle= 0; */
-
- /* open the needed object */
- pis->handle= PIL_dynlib_open(pis->name);
- if(test_dlerr(pis->name, pis->name)) return;
-
- if (pis->handle != 0) {
- /* find the address of the version function */
- version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion");
- if (test_dlerr(pis->name, "plugin_seq_getversion")) return;
-
- if (version != 0) {
- pis->version= version();
- if (pis->version==2 || pis->version==3) {
- int (*info_func)(PluginInfo *);
- PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");;
-
- info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo");
-
- if(info_func == NULL) error("No info func");
- else {
- info_func(info);
-
- pis->pname= info->name;
- pis->vars= info->nvars;
- pis->cfra= info->cfra;
-
- pis->varstr= info->varstr;
-
- pis->doit= (void(*)(void))info->seq_doit;
- if (info->init)
- info->init();
- }
- MEM_freeN(info);
-
- cp= PIL_dynlib_find_symbol(pis->handle, "seqname");
- if(cp) strncpy(cp, seqname, 21);
- } else {
- printf ("Plugin returned unrecognized version number\n");
- return;
- }
- }
- alloc_private = (void* (*)())PIL_dynlib_find_symbol(
- pis->handle, "plugin_seq_alloc_private_data");
- if (alloc_private) {
- pis->instance_private_data = alloc_private();
- }
-
- pis->current_private_data = (void**)
- PIL_dynlib_find_symbol(
- pis->handle, "plugin_private_data");
- }
-}
-
-PluginSeq *add_plugin_seq(char *str, char *seqname)
-{
- PluginSeq *pis;
- VarStruct *varstr;
- int a;
-
- pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq");
-
- strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE);
- open_plugin_seq(pis, seqname);
-
- if(pis->doit==0) {
- if(pis->handle==0) error("no plugin: %s", str);
- else error("in plugin: %s", str);
- MEM_freeN(pis);
- return 0;
- }
-
- /* default values */
- varstr= pis->varstr;
- for(a=0; a<pis->vars; a++, varstr++) {
- if( (varstr->type & FLO)==FLO)
- pis->data[a]= varstr->def;
- else if( (varstr->type & INT)==INT)
- *((int *)(pis->data+a))= (int) varstr->def;
- }
-
- return pis;
-}
-
-void free_plugin_seq(PluginSeq *pis)
-{
- if(pis==0) return;
-
- /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */
-
- if (pis->instance_private_data) {
- void (*free_private)(void *);
-
- free_private = (void (*)(void *))PIL_dynlib_find_symbol(
- pis->handle, "plugin_seq_free_private_data");
- if (free_private) {
- free_private(pis->instance_private_data);
- }
- }
-
- MEM_freeN(pis);
-}
-
/* ***************** END PLUGIN ************************ */
void free_stripdata(int len, StripElem *se)
@@ -247,12 +121,15 @@ void free_sequence(Sequence *seq)
extern Sequence *last_seq;
if(seq->strip) free_strip(seq->strip);
- if(seq->effectdata) MEM_freeN(seq->effectdata);
if(seq->anim) IMB_free_anim(seq->anim);
if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio);
- free_plugin_seq(seq->plugin);
+ if (seq->type & SEQ_EFFECT) {
+ struct SeqEffectHandle sh = get_sequence_effect(seq);
+
+ sh.free(seq);
+ }
if(seq==last_seq) last_seq= 0;
@@ -467,1158 +344,65 @@ void clear_scene_in_allseqs(Scene *sce)
/* ***************** DO THE SEQUENCE ***************** */
-void do_alphaover_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
- int fac2, mfac, fac, fac4;
- int xo, tempc;
- char *rt1, *rt2, *rt;
-
- xo= x;
- rt1= (char *)rect1;
- rt2= (char *)rect2;
- rt= (char *)out;
-
- fac2= (int)(256.0*facf0);
- fac4= (int)(256.0*facf1);
-
- while(y--) {
-
- x= xo;
- while(x--) {
-
- /* rt = rt1 over rt2 (alpha from rt1) */
-
- fac= fac2;
- mfac= 256 - ( (fac2*rt1[3])>>8 );
-
- if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
- else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
- else {
- tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
- if(tempc>255) rt[0]= 255; else rt[0]= tempc;
- tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
- if(tempc>255) rt[1]= 255; else rt[1]= tempc;
- tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
- if(tempc>255) rt[2]= 255; else rt[2]= tempc;
- tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
- if(tempc>255) rt[3]= 255; else rt[3]= tempc;
- }
- rt1+= 4; rt2+= 4; rt+= 4;
- }
-
- if(y==0) break;
- y--;
-
- x= xo;
- while(x--) {
-
- fac= fac4;
- mfac= 256 - ( (fac4*rt1[3])>>8 );
-
- if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
- else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
- else {
- tempc= ( fac*rt1[0] + mfac*rt2[0])>>8;
- if(tempc>255) rt[0]= 255; else rt[0]= tempc;
- tempc= ( fac*rt1[1] + mfac*rt2[1])>>8;
- if(tempc>255) rt[1]= 255; else rt[1]= tempc;
- tempc= ( fac*rt1[2] + mfac*rt2[2])>>8;
- if(tempc>255) rt[2]= 255; else rt[2]= tempc;
- tempc= ( fac*rt1[3] + mfac*rt2[3])>>8;
- if(tempc>255) rt[3]= 255; else rt[3]= tempc;
- }
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
-}
-
-void do_alphaunder_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
- int fac2, mfac, fac, fac4;
- int xo;
- char *rt1, *rt2, *rt;
-
- xo= x;
- rt1= (char *)rect1;
- rt2= (char *)rect2;
- rt= (char *)out;
-
- fac2= (int)(256.0*facf0);
- fac4= (int)(256.0*facf1);
-
- while(y--) {
-
- x= xo;
- while(x--) {
-
- /* rt = rt1 under rt2 (alpha from rt2) */
-
- /* this complex optimalisation is because the
- * 'skybuf' can be crossed in
- */
- if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
- else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
- else {
- mfac= rt2[3];
- fac= (fac2*(256-mfac))>>8;
-
- if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
- else {
- rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
- rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
- rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
- rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
- }
- }
- rt1+= 4; rt2+= 4; rt+= 4;
- }
-
- if(y==0) break;
- y--;
-
- x= xo;
- while(x--) {
-
- if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1);
- else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
- else {
- mfac= rt2[3];
- fac= (fac4*(256-mfac))>>8;
-
- if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2);
- else {
- rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8;
- rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8;
- rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8;
- rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8;
- }
- }
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
-}
-
-
-void do_cross_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
- int fac1, fac2, fac3, fac4;
- int xo;
- char *rt1, *rt2, *rt;
-
- xo= x;
- rt1= (char *)rect1;
- rt2= (char *)rect2;
- rt= (char *)out;
-
- fac2= (int)(256.0*facf0);
- fac1= 256-fac2;
- fac4= (int)(256.0*facf1);
- fac3= 256-fac4;
-
- while(y--) {
-
- x= xo;
- while(x--) {
-
- rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8;
- rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8;
- rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8;
- rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8;
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
-
- if(y==0) break;
- y--;
-
- x= xo;
- while(x--) {
-
- rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8;
- rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8;
- rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8;
- rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8;
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
-
- }
-}
-
-/* copied code from initrender.c */
-static unsigned short *gamtab, *igamtab1;
-
-static void gamtabs(float gamma)
-{
- float val, igamma= 1.0f/gamma;
- int a;
-
- gamtab= MEM_mallocN(65536*sizeof(short), "initGaus2");
- igamtab1= MEM_mallocN(256*sizeof(short), "initGaus2");
-
- /* gamtab: in short, out short */
- for(a=0; a<65536; a++) {
- val= a;
- val/= 65535.0;
-
- if(gamma==2.0) val= sqrt(val);
- else if(gamma!=1.0) val= pow(val, igamma);
-
- gamtab[a]= (65535.99*val);
- }
- /* inverse gamtab1 : in byte, out short */
- for(a=1; a<=256; a++) {
- if(gamma==2.0) igamtab1[a-1]= a*a-1;
- else if(gamma==1.0) igamtab1[a-1]= 256*a-1;
- else {
- val= a/256.0;
- igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ;
- }
- }
-
-}
-
-void do_gammacross_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
- int fac1, fac2, col;
- int xo;
- char *rt1, *rt2, *rt;
-
- gamtabs(2.0f);
-
- xo= x;
- rt1= (char *)rect1;
- rt2= (char *)rect2;
- rt= (char *)out;
-
- fac2= (int)(256.0*facf0);
- fac1= 256-fac2;
-
- while(y--) {
-
- x= xo;
- while(x--) {
-
- col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
- if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
- col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
- if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
- col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
- if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
- col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
- if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
-
- if(y==0) break;
- y--;
-
- x= xo;
- while(x--) {
-
- col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8;
- if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
- col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8;
- if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
- col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8;
- if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
- col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8;
- if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE];
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
-
- MEM_freeN(gamtab);
- MEM_freeN(igamtab1);
-}
-
-void do_add_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
- int col, xo, fac1, fac3;
- char *rt1, *rt2, *rt;
-
- xo= x;
- rt1= (char *)rect1;
- rt2= (char *)rect2;
- rt= (char *)out;
-
- fac1= (int)(256.0*facf0);
- fac3= (int)(256.0*facf1);
-
- while(y--) {
-
- x= xo;
- while(x--) {
-
- col= rt1[0]+ ((fac1*rt2[0])>>8);
- if(col>255) rt[0]= 255; else rt[0]= col;
- col= rt1[1]+ ((fac1*rt2[1])>>8);
- if(col>255) rt[1]= 255; else rt[1]= col;
- col= rt1[2]+ ((fac1*rt2[2])>>8);
- if(col>255) rt[2]= 255; else rt[2]= col;
- col= rt1[3]+ ((fac1*rt2[3])>>8);
- if(col>255) rt[3]= 255; else rt[3]= col;
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
-
- if(y==0) break;
- y--;
-
- x= xo;
- while(x--) {
-
- col= rt1[0]+ ((fac3*rt2[0])>>8);
- if(col>255) rt[0]= 255; else rt[0]= col;
- col= rt1[1]+ ((fac3*rt2[1])>>8);
- if(col>255) rt[1]= 255; else rt[1]= col;
- col= rt1[2]+ ((fac3*rt2[2])>>8);
- if(col>255) rt[2]= 255; else rt[2]= col;
- col= rt1[3]+ ((fac3*rt2[3])>>8);
- if(col>255) rt[3]= 255; else rt[3]= col;
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
-}
-
-void do_sub_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
- int col, xo, fac1, fac3;
- char *rt1, *rt2, *rt;
-
- xo= x;
- rt1= (char *)rect1;
- rt2= (char *)rect2;
- rt= (char *)out;
-
- fac1= (int)(256.0*facf0);
- fac3= (int)(256.0*facf1);
-
- while(y--) {
-
- x= xo;
- while(x--) {
-
- col= rt1[0]- ((fac1*rt2[0])>>8);
- if(col<0) rt[0]= 0; else rt[0]= col;
- col= rt1[1]- ((fac1*rt2[1])>>8);
- if(col<0) rt[1]= 0; else rt[1]= col;
- col= rt1[2]- ((fac1*rt2[2])>>8);
- if(col<0) rt[2]= 0; else rt[2]= col;
- col= rt1[3]- ((fac1*rt2[3])>>8);
- if(col<0) rt[3]= 0; else rt[3]= col;
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
-
- if(y==0) break;
- y--;
-
- x= xo;
- while(x--) {
-
- col= rt1[0]- ((fac3*rt2[0])>>8);
- if(col<0) rt[0]= 0; else rt[0]= col;
- col= rt1[1]- ((fac3*rt2[1])>>8);
- if(col<0) rt[1]= 0; else rt[1]= col;
- col= rt1[2]- ((fac3*rt2[2])>>8);
- if(col<0) rt[2]= 0; else rt[2]= col;
- col= rt1[3]- ((fac3*rt2[3])>>8);
- if(col<0) rt[3]= 0; else rt[3]= col;
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
-}
-
-/* Must be > 0 or add precopy, etc to the function */
-#define XOFF 8
-#define YOFF 8
-
-void do_drop_effect(float facf0, float facf1, int x, int y, unsigned int *rect2i, unsigned int *rect1i, unsigned int *outi)
-{
- int height, width, temp, fac, fac1, fac2;
- char *rt1, *rt2, *out;
- int field= 1;
-
- width= x;
- height= y;
-
- fac1= (int)(70.0*facf0);
- fac2= (int)(70.0*facf1);
-
- rt2= (char*) (rect2i + YOFF*width);
- rt1= (char*) rect1i;
- out= (char*) outi;
- for (y=0; y<height-YOFF; y++) {
- if(field) fac= fac1;
- else fac= fac2;
- field= !field;
-
- memcpy(out, rt1, sizeof(int)*XOFF);
- rt1+= XOFF*4;
- out+= XOFF*4;
-
- for (x=XOFF; x<width; x++) {
- temp= ((fac*rt2[3])>>8);
-
- *(out++)= MAX2(0, *rt1 - temp); rt1++;
- *(out++)= MAX2(0, *rt1 - temp); rt1++;
- *(out++)= MAX2(0, *rt1 - temp); rt1++;
- *(out++)= MAX2(0, *rt1 - temp); rt1++;
- rt2+=4;
- }
- rt2+=XOFF*4;
- }
- memcpy(out, rt1, sizeof(int)*YOFF*width);
-}
-
- /* WATCH: rect2 and rect1 reversed */
-void do_drop_effect2(float facf0, float facf1, int x, int y, unsigned int *rect2, unsigned int *rect1, unsigned int *out)
-{
- int col, xo, yo, temp, fac1, fac3;
- int xofs= -8, yofs= 8;
- char *rt1, *rt2, *rt;
-
- xo= x;
- yo= y;
-
- rt2= (char *)(rect2 + yofs*x + xofs);
-
- rt1= (char *)rect1;
- rt= (char *)out;
-
- fac1= (int)(70.0*facf0);
- fac3= (int)(70.0*facf1);
-
- while(y-- > 0) {
-
- temp= y-yofs;
- if(temp > 0 && temp < yo) {
-
- x= xo;
- while(x--) {
-
- temp= x+xofs;
- if(temp > 0 && temp < xo) {
-
- temp= ((fac1*rt2[3])>>8);
-
- col= rt1[0]- temp;
- if(col<0) rt[0]= 0; else rt[0]= col;
- col= rt1[1]- temp;
- if(col<0) rt[1]= 0; else rt[1]= col;
- col= rt1[2]- temp;
- if(col<0) rt[2]= 0; else rt[2]= col;
- col= rt1[3]- temp;
- if(col<0) rt[3]= 0; else rt[3]= col;
- }
- else *( (unsigned int *)rt) = *( (unsigned int *)rt1);
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
- else {
- x= xo;
- while(x--) {
- *( (unsigned int *)rt) = *( (unsigned int *)rt1);
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
-
- if(y==0) break;
- y--;
-
- temp= y-yofs;
- if(temp > 0 && temp < yo) {
-
- x= xo;
- while(x--) {
-
- temp= x+xofs;
- if(temp > 0 && temp < xo) {
-
- temp= ((fac3*rt2[3])>>8);
-
- col= rt1[0]- temp;
- if(col<0) rt[0]= 0; else rt[0]= col;
- col= rt1[1]- temp;
- if(col<0) rt[1]= 0; else rt[1]= col;
- col= rt1[2]- temp;
- if(col<0) rt[2]= 0; else rt[2]= col;
- col= rt1[3]- temp;
- if(col<0) rt[3]= 0; else rt[3]= col;
- }
- else *( (unsigned int *)rt) = *( (unsigned int *)rt1);
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
- else {
- x= xo;
- while(x--) {
- *( (unsigned int *)rt) = *( (unsigned int *)rt1);
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
- }
-}
-
-
-void do_mul_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
- int xo, fac1, fac3;
- char *rt1, *rt2, *rt;
-
- xo= x;
- rt1= (char *)rect1;
- rt2= (char *)rect2;
- rt= (char *)out;
-
- fac1= (int)(256.0*facf0);
- fac3= (int)(256.0*facf1);
-
- /* formula:
- * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a
- */
-
- while(y--) {
-
- x= xo;
- while(x--) {
-
- rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16);
- rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16);
- rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16);
- rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16);
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
-
- if(y==0) break;
- y--;
-
- x= xo;
- while(x--) {
-
- rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16);
- rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16);
- rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16);
- rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16);
-
- rt1+= 4; rt2+= 4; rt+= 4;
- }
- }
-}
-
-// This function calculates the blur band for the wipe effects
-float in_band(float width,float dist, float perc,int side,int dir){
-
- float t1,t2,alpha,percwidth;
- if(width == 0)
- return (float)side;
- if(side == 1)
- percwidth = width * perc;
- else
- percwidth = width * (1 - perc);
-
- if(width < dist)
- return side;
-
- t1 = dist / width; //percentange of width that is
- t2 = 1 / width; //amount of alpha per % point
-
- if(side == 1)
- alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe
- else
- alpha = (1-perc) - (t1*t2*100);
-
- if(dir == 0)
- alpha = 1-alpha;
- return alpha;
-}
-
-float check_zone(int x, int y, int xo, int yo, Sequence *seq, float facf0) {
-
- float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist;
- /*some future stuff
- float hyp3,hyp4,b4,b5
- */
- float temp1,temp2,temp3,temp4; //some placeholder variables
- float halfx = xo/2;
- float halfy = yo/2;
- float widthf,output=0;
- WipeVars *wipe = (WipeVars *)seq->effectdata;
- int width;
-
- angle = wipe->angle;
- if(angle < 0){
- x = xo-x;
- //y = yo-y
- }
- angle = pow(fabs(angle)/45,log(xo)/log(2));
-
- posy = facf0 * yo;
- if(wipe->forward){
- posx = facf0 * xo;
- posy = facf0 * yo;
- } else{
- posx = xo - facf0 * xo;
- posy = yo - facf0 * yo;
- }
- switch (wipe->wipetype) {
- case DO_SINGLE_WIPE:
- width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
- hwidth = (float)width/2.0;
-
- if (angle == 0.0)angle = 0.000001;
- b1 = posy - (-angle)*posx;
- b2 = y - (-angle)*x;
- hyp = fabs(angle*x+y+(-posy-angle*posx))/sqrt(angle*angle+1);
- if(angle < 0){
- temp1 = b1;
- b1 = b2;
- b2 = temp1;
- }
- if(wipe->forward){
- if(b1 < b2)
- output = in_band(width,hyp,facf0,1,1);
- else
- output = in_band(width,hyp,facf0,0,1);
- }
- else{
- if(b1 < b2)
- output = in_band(width,hyp,facf0,0,1);
- else
- output = in_band(width,hyp,facf0,1,1);
- }
- break;
-
-
- case DO_DOUBLE_WIPE:
- if(!wipe->forward)facf0 = 1-facf0; // Go the other direction
-
- width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); // calculate the blur width
- hwidth = (float)width/2.0;
- if (angle == 0)angle = 0.000001;
- b1 = posy/2 - (-angle)*posx/2;
- b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
- b2 = y - (-angle)*x;
-
- hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
- hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
-
- temp1 = xo*(1-facf0/2)-xo*facf0/2;
- temp2 = yo*(1-facf0/2)-yo*facf0/2;
- pointdist = sqrt(temp1*temp1 + temp2*temp2);
-
- if(b2 < b1 && b2 < b3 ){
- if(hwidth < pointdist)
- output = in_band(hwidth,hyp,facf0,0,1);
- }
- else if(b2 > b1 && b2 > b3 ){
- if(hwidth < pointdist)
- output = in_band(hwidth,hyp2,facf0,0,1);
- }
- else{
- if( hyp < hwidth && hyp2 > hwidth )
- output = in_band(hwidth,hyp,facf0,1,1);
- else if( hyp > hwidth && hyp2 < hwidth )
- output = in_band(hwidth,hyp2,facf0,1,1);
- else
- output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
- }
- if(!wipe->forward)output = 1-output;
- break;
- case DO_CLOCK_WIPE:
- /*
- temp1: angle of effect center in rads
- temp2: angle of line through (halfx,halfy) and (x,y) in rads
- temp3: angle of low side of blur
- temp4: angle of high side of blur
- */
- output = 1-facf0;
- widthf = wipe->edgeWidth*2*3.14159;
- temp1 = 2 * 3.14159 * facf0;
-
- if(wipe->forward){
- temp1 = 2*3.14159-temp1;
- }
-
- x = x - halfx;
- y = y - halfy;
-
- temp2 = asin(abs(y)/sqrt(x*x + y*y));
- if(x <= 0 && y >= 0)
- temp2 = 3.14159 - temp2;
- else if(x<=0 && y <= 0)
- temp2 += 3.14159;
- else if(x >= 0 && y <= 0)
- temp2 = 2*3.14159 - temp2;
-
- if(wipe->forward){
- temp3 = temp1-(widthf/2)*facf0;
- temp4 = temp1+(widthf/2)*(1-facf0);
- }
- else{
- temp3 = temp1-(widthf/2)*(1-facf0);
- temp4 = temp1+(widthf/2)*facf0;
- }
- if (temp3 < 0) temp3 = 0;
- if (temp4 > 2*3.14159) temp4 = 2*3.14159;
-
-
- if(temp2 < temp3)
- output = 0;
- else if (temp2 > temp4)
- output = 1;
- else
- output = (temp2-temp3)/(temp4-temp3);
- if(x == 0 && y == 0){
- output = 1;
- }
- if(output != output)
- output = 1;
- if(wipe->forward)
- output = 1 - output;
- break;
- /* BOX WIPE IS NOT WORKING YET */
- /* case DO_CROSS_WIPE: */
- /* BOX WIPE IS NOT WORKING YET */
- /* case DO_BOX_WIPE:
- if(invert)facf0 = 1-facf0;
-
- width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
- hwidth = (float)width/2.0;
- if (angle == 0)angle = 0.000001;
- b1 = posy/2 - (-angle)*posx/2;
- b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
- b2 = y - (-angle)*x;
-
- hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
- hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
-
- temp1 = xo*(1-facf0/2)-xo*facf0/2;
- temp2 = yo*(1-facf0/2)-yo*facf0/2;
- pointdist = sqrt(temp1*temp1 + temp2*temp2);
-
- if(b2 < b1 && b2 < b3 ){
- if(hwidth < pointdist)
- output = in_band(hwidth,hyp,facf0,0,1);
- }
- else if(b2 > b1 && b2 > b3 ){
- if(hwidth < pointdist)
- output = in_band(hwidth,hyp2,facf0,0,1);
- }
- else{
- if( hyp < hwidth && hyp2 > hwidth )
- output = in_band(hwidth,hyp,facf0,1,1);
- else if( hyp > hwidth && hyp2 < hwidth )
- output = in_band(hwidth,hyp2,facf0,1,1);
- else
- output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
- }
- if(invert)facf0 = 1-facf0;
- angle = -1/angle;
- b1 = posy/2 - (-angle)*posx/2;
- b3 = (yo-posy/2) - (-angle)*(xo-posx/2);
- b2 = y - (-angle)*x;
-
- hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1);
- hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1);
-
- if(b2 < b1 && b2 < b3 ){
- if(hwidth < pointdist)
- output *= in_band(hwidth,hyp,facf0,0,1);
- }
- else if(b2 > b1 && b2 > b3 ){
- if(hwidth < pointdist)
- output *= in_band(hwidth,hyp2,facf0,0,1);
- }
- else{
- if( hyp < hwidth && hyp2 > hwidth )
- output *= in_band(hwidth,hyp,facf0,1,1);
- else if( hyp > hwidth && hyp2 < hwidth )
- output *= in_band(hwidth,hyp2,facf0,1,1);
- else
- output *= in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1);
- }
-
- break;*/
- case DO_IRIS_WIPE:
- if(xo > yo) yo = xo;
- else xo = yo;
-
- if(!wipe->forward)
- facf0 = 1-facf0;
-
- width = (int)(wipe->edgeWidth*((xo+yo)/2.0));
- hwidth = (float)width/2.0;
-
- temp1 = (halfx-(halfx)*facf0);
- pointdist = sqrt(temp1*temp1 + temp1*temp1);
-
- temp2 = sqrt((halfx-x)*(halfx-x) + (halfy-y)*(halfy-y));
- if(temp2 > pointdist)
- output = in_band(hwidth,fabs(temp2-pointdist),facf0,0,1);
- else
- output = in_band(hwidth,fabs(temp2-pointdist),facf0,1,1);
-
- if(!wipe->forward)
- output = 1-output;
-
- break;
- }
- if (output < 0) output = 0;
- else if(output > 1) output = 1;
- return output;
-}
-
-void init_wipe_effect(Sequence *seq)
-{
- if(seq->effectdata)MEM_freeN(seq->effectdata);
- seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars");
-}
-
-void do_wipe_effect(Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
- int xo, yo;
- char *rt1, *rt2, *rt;
- rt1 = (char *)rect1;
- rt2 = (char *)rect2;
- rt = (char *)out;
-
- xo = x;
- yo = y;
- for(y=0;y<yo;y++) {
-
- for(x=0;x<xo;x++) {
- float check = check_zone(x,y,xo,yo,seq,facf0);
- if (check) {
- if (rt1) {
- rt[0] = (int)(rt1[0]*check)+ (int)(rt2[0]*(1-check));
- rt[1] = (int)(rt1[1]*check)+ (int)(rt2[1]*(1-check));
- rt[2] = (int)(rt1[2]*check)+ (int)(rt2[2]*(1-check));
- rt[3] = (int)(rt1[3]*check)+ (int)(rt2[3]*(1-check));
- } else {
- rt[0] = 0;
- rt[1] = 0;
- rt[2] = 0;
- rt[3] = 255;
- }
- } else {
- if (rt2) {
- rt[0] = rt2[0];
- rt[1] = rt2[1];
- rt[2] = rt2[2];
- rt[3] = rt2[3];
- } else {
- rt[0] = 0;
- rt[1] = 0;
- rt[2] = 0;
- rt[3] = 255;
- }
- }
-
- rt+=4;
- if(rt1 !=NULL){
- rt1+=4;
- }
- if(rt2 !=NULL){
- rt2+=4;
- }
- }
- }
-}
-
-/* Glow Functions */
-
-void RVBlurBitmap2 ( unsigned char* map, int width,int height,float blur,
- int quality)
-/* MUUUCCH better than the previous blur. */
-/* We do the blurring in two passes which is a whole lot faster. */
-/* I changed the math arount to implement an actual Gaussian */
-/* distribution. */
-/* */
-/* Watch out though, it tends to misbehaven with large blur values on */
-/* a small bitmap. Avoid avoid avoid. */
-/*=============================== */
-{
- unsigned char* temp=NULL,*swap;
- float *filter=NULL;
- int x,y,i,fx,fy;
- int index, ix, halfWidth;
- float fval, k, curColor[3], curColor2[3], weight=0;
-
- /* If we're not really blurring, bail out */
- if (blur<=0)
- return;
-
- /* Allocate memory for the tempmap and the blur filter matrix */
- temp= MEM_mallocN( (width*height*4), "blurbitmaptemp");
- if (!temp)
- return;
-
- /* Allocate memory for the filter elements */
- halfWidth = ((quality+1)*blur);
- filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter");
- if (!filter){
- MEM_freeN (temp);
- return;
- }
-
- /* Apparently we're calculating a bell curve */
- /* based on the standard deviation (or radius) */
- /* This code is based on an example */
- /* posted to comp.graphics.algorithms by */
- /* Blancmange (bmange@airdmhor.gen.nz) */
-
- k = -1.0/(2.0*3.14159*blur*blur);
- fval=0;
- for (ix = 0;ix< halfWidth;ix++){
- weight = (float)exp(k*(ix*ix));
- filter[halfWidth - ix] = weight;
- filter[halfWidth + ix] = weight;
- }
- filter[0] = weight;
-
- /* Normalize the array */
- fval=0;
- for (ix = 0;ix< halfWidth*2;ix++)
- fval+=filter[ix];
-
- for (ix = 0;ix< halfWidth*2;ix++)
- filter[ix]/=fval;
-
- /* Blur the rows */
- for (y=0;y<height;y++){
- /* Do the left & right strips */
- for (x=0;x<halfWidth;x++){
- index=(x+y*width)*4;
- fx=0;
- curColor[0]=curColor[1]=curColor[2]=0;
- curColor2[0]=curColor2[1]=curColor2[2]=0;
-
- for (i=x-halfWidth;i<x+halfWidth;i++){
- if ((i>=0)&&(i<width)){
- curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
- curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
- curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
-
- curColor2[0]+=map[(width-1-i+y*width)*4+GlowR] *
- filter[fx];
- curColor2[1]+=map[(width-1-i+y*width)*4+GlowG] *
- filter[fx];
- curColor2[2]+=map[(width-1-i+y*width)*4+GlowB] *
- filter[fx];
- }
- fx++;
- }
- temp[index+GlowR]=curColor[0];
- temp[index+GlowG]=curColor[1];
- temp[index+GlowB]=curColor[2];
-
- temp[((width-1-x+y*width)*4)+GlowR]=curColor2[0];
- temp[((width-1-x+y*width)*4)+GlowG]=curColor2[1];
- temp[((width-1-x+y*width)*4)+GlowB]=curColor2[2];
-
- }
- /* Do the main body */
- for (x=halfWidth;x<width-halfWidth;x++){
- index=(x+y*width)*4;
- fx=0;
- curColor[0]=curColor[1]=curColor[2]=0;
- for (i=x-halfWidth;i<x+halfWidth;i++){
- curColor[0]+=map[(i+y*width)*4+GlowR]*filter[fx];
- curColor[1]+=map[(i+y*width)*4+GlowG]*filter[fx];
- curColor[2]+=map[(i+y*width)*4+GlowB]*filter[fx];
- fx++;
- }
- temp[index+GlowR]=curColor[0];
- temp[index+GlowG]=curColor[1];
- temp[index+GlowB]=curColor[2];
- }
- }
-
- /* Swap buffers */
- swap=temp;temp=map;map=swap;
-
-
- /* Blur the columns */
- for (x=0;x<width;x++){
- /* Do the top & bottom strips */
- for (y=0;y<halfWidth;y++){
- index=(x+y*width)*4;
- fy=0;
- curColor[0]=curColor[1]=curColor[2]=0;
- curColor2[0]=curColor2[1]=curColor2[2]=0;
- for (i=y-halfWidth;i<y+halfWidth;i++){
- if ((i>=0)&&(i<height)){
- /* Bottom */
- curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
- curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
- curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
-
- /* Top */
- curColor2[0]+=map[(x+(height-1-i)*width) *
- 4+GlowR]*filter[fy];
- curColor2[1]+=map[(x+(height-1-i)*width) *
- 4+GlowG]*filter[fy];
- curColor2[2]+=map[(x+(height-1-i)*width) *
- 4+GlowB]*filter[fy];
- }
- fy++;
- }
- temp[index+GlowR]=curColor[0];
- temp[index+GlowG]=curColor[1];
- temp[index+GlowB]=curColor[2];
- temp[((x+(height-1-y)*width)*4)+GlowR]=curColor2[0];
- temp[((x+(height-1-y)*width)*4)+GlowG]=curColor2[1];
- temp[((x+(height-1-y)*width)*4)+GlowB]=curColor2[2];
- }
- /* Do the main body */
- for (y=halfWidth;y<height-halfWidth;y++){
- index=(x+y*width)*4;
- fy=0;
- curColor[0]=curColor[1]=curColor[2]=0;
- for (i=y-halfWidth;i<y+halfWidth;i++){
- curColor[0]+=map[(x+i*width)*4+GlowR]*filter[fy];
- curColor[1]+=map[(x+i*width)*4+GlowG]*filter[fy];
- curColor[2]+=map[(x+i*width)*4+GlowB]*filter[fy];
- fy++;
- }
- temp[index+GlowR]=curColor[0];
- temp[index+GlowG]=curColor[1];
- temp[index+GlowB]=curColor[2];
- }
- }
-
-
- /* Swap buffers */
- swap=temp;temp=map;map=swap;
-
- /* Tidy up */
- MEM_freeN (filter);
- MEM_freeN (temp);
-}
-
-
-/* Adds two bitmaps and puts the results into a third map. */
-/* C must have been previously allocated but it may be A or B. */
-/* We clamp values to 255 to prevent weirdness */
-/*=============================== */
-void RVAddBitmaps (unsigned char* a, unsigned char* b, unsigned char* c, int width, int height)
-{
- int x,y,index;
-
- for (y=0;y<height;y++){
- for (x=0;x<width;x++){
- index=(x+y*width)*4;
- c[index+GlowR]=MIN2(255,a[index+GlowR]+b[index+GlowR]);
- c[index+GlowG]=MIN2(255,a[index+GlowG]+b[index+GlowG]);
- c[index+GlowB]=MIN2(255,a[index+GlowB]+b[index+GlowB]);
- c[index+GlowA]=MIN2(255,a[index+GlowA]+b[index+GlowA]);
- }
- }
-}
-
-/* For each pixel whose total luminance exceeds the threshold, */
-/* Multiply it's value by BOOST and add it to the output map */
-void RVIsolateHighlights (unsigned char* in, unsigned char* out, int width, int height, int threshold, float boost, float clamp)
-{
- int x,y,index;
- int intensity;
-
-
- for(y=0;y< height;y++) {
- for (x=0;x< width;x++) {
- index= (x+y*width)*4;
-
- /* Isolate the intensity */
- intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold);
- if (intensity>0){
- out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255);
- out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255);
- out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255);
- out[index+GlowA]=MIN2(255*clamp, (in[index+GlowA]*boost*intensity)/255);
- }
- else{
- out[index+GlowR]=0;
- out[index+GlowG]=0;
- out[index+GlowB]=0;
- out[index+GlowA]=0;
- }
- }
- }
-}
-
-void init_glow_effect(Sequence *seq)
-{
- GlowVars *glow;
-
- if(seq->effectdata)MEM_freeN(seq->effectdata);
- seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars");
-
- glow = (GlowVars *)seq->effectdata;
- glow->fMini = 0.25;
- glow->fClamp = 1.0;
- glow->fBoost = 0.5;
- glow->dDist = 3.0;
- glow->dQuality = 3;
- glow->bNoComp = 0;
-}
-
-
-//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use)
-void do_glow_effect(Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out)
-{
- unsigned char *outbuf=(unsigned char *)out;
- unsigned char *inbuf=(unsigned char *)rect1;
- GlowVars *glow = (GlowVars *)seq->effectdata;
-
- RVIsolateHighlights (inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp);
- RVBlurBitmap2 (outbuf, x, y, glow->dDist,glow->dQuality);
- if (!glow->bNoComp)
- RVAddBitmaps (inbuf , outbuf, outbuf, x, y);
-}
-
void make_black_ibuf(ImBuf *ibuf)
{
- unsigned int *rect;
+ int *rect;
+ float *rect_float;
int tot;
- if(ibuf==0 || ibuf->rect==0) return;
+ if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return;
tot= ibuf->x*ibuf->y;
+
rect= ibuf->rect;
- while(tot--) *(rect++)= 0;
+ rect_float = ibuf->rect_float;
+ if (rect) {
+ memset(rect, 0, tot * sizeof(char) * 4);
+ }
+
+ if (rect_float) {
+ memset(rect_float, 0, tot * sizeof(float) * 4);
+ }
}
void multibuf(ImBuf *ibuf, float fmul)
{
char *rt;
+ float *rt_float;
+
int a, mul, icol;
mul= (int)(256.0*fmul);
a= ibuf->x*ibuf->y;
rt= (char *)ibuf->rect;
- while(a--) {
-
- icol= (mul*rt[0])>>8;
- if(icol>254) rt[0]= 255; else rt[0]= icol;
- icol= (mul*rt[1])>>8;
- if(icol>254) rt[1]= 255; else rt[1]= icol;
- icol= (mul*rt[2])>>8;
- if(icol>254) rt[2]= 255; else rt[2]= icol;
- icol= (mul*rt[3])>>8;
- if(icol>254) rt[3]= 255; else rt[3]= icol;
-
- rt+= 4;
+ rt_float = ibuf->rect_float;
+
+ if (rt) {
+ while(a--) {
+
+ icol= (mul*rt[0])>>8;
+ if(icol>254) rt[0]= 255; else rt[0]= icol;
+ icol= (mul*rt[1])>>8;
+ if(icol>254) rt[1]= 255; else rt[1]= icol;
+ icol= (mul*rt[2])>>8;
+ if(icol>254) rt[2]= 255; else rt[2]= icol;
+ icol= (mul*rt[3])>>8;
+ if(icol>254) rt[3]= 255; else rt[3]= icol;
+
+ rt+= 4;
+ }
+ }
+ if (rt_float) {
+ while(a--) {
+ rt_float[0] *= fmul;
+ rt_float[1] *= fmul;
+ rt_float[2] *= fmul;
+ rt_float[3] *= fmul;
+
+ rt_float += 4;
+ }
}
}
@@ -1627,7 +411,7 @@ void do_effect(int cfra, Sequence *seq, StripElem *se)
StripElem *se1, *se2, *se3;
float fac, facf;
int x, y;
- char *cp;
+ struct SeqEffectHandle sh = get_sequence_effect(seq);
if(se->se1==0 || se->se2==0 || se->se3==0) {
make_black_ibuf(se->ibuf);
@@ -1653,47 +437,38 @@ void do_effect(int cfra, Sequence *seq, StripElem *se)
do_seq_ipo(seq);
fac= seq->facf0;
facf= seq->facf1;
- }
- else if ( seq->type==SEQ_CROSS || seq->type==SEQ_GAMCROSS || seq->type==SEQ_PLUGIN || seq->type==SEQ_WIPE) {
- fac= (float)(cfra - seq->startdisp);
- facf= (float)(fac+0.5);
- fac /= seq->len;
- facf /= seq->len;
- }
- else {
- fac= facf= 1.0;
+ } else {
+ sh.get_default_fac(seq, cfra, &fac, &facf);
}
if( G.scene->r.mode & R_FIELDS ); else facf= fac;
- /* FIXME: This should be made available to external plugins too... */
- if (seq->type == SEQ_CROSS || seq->type == SEQ_GAMCROSS ||
- seq->type == SEQ_WIPE) {
- if (fac == 0.0 && facf == 0.0) {
- if (se1->ibuf==0) {
- make_black_ibuf(se->ibuf);
- return;
- }
- if (se->ibuf != se1->ibuf) {
- IMB_freeImBuf(se->ibuf);
- se->ibuf = se1->ibuf;
- IMB_refImBuf(se->ibuf);
- }
+ switch (sh.early_out(seq, fac, facf)) {
+ case 0:
+ break;
+ case 1:
+ if (se1->ibuf==0) {
+ make_black_ibuf(se->ibuf);
return;
- } else if (fac == 1.0 && facf == 1.0) {
- if (se2->ibuf==0) {
- make_black_ibuf(se->ibuf);
- return;
- }
- if (se->ibuf != se2->ibuf) {
- IMB_freeImBuf(se->ibuf);
- se->ibuf = se2->ibuf;
- IMB_refImBuf(se->ibuf);
- }
+ }
+ if (se->ibuf != se1->ibuf) {
+ IMB_freeImBuf(se->ibuf);
+ se->ibuf = se1->ibuf;
+ IMB_refImBuf(se->ibuf);
+ }
+ return;
+ case 2:
+ if (se2->ibuf==0) {
+ make_black_ibuf(se->ibuf);
return;
- }
- }
-
+ }
+ if (se->ibuf != se2->ibuf) {
+ IMB_freeImBuf(se->ibuf);
+ se->ibuf = se2->ibuf;
+ IMB_refImBuf(se->ibuf);
+ }
+ return;
+ }
if (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0) {
make_black_ibuf(se->ibuf);
@@ -1703,78 +478,22 @@ void do_effect(int cfra, Sequence *seq, StripElem *se)
x= se2->ibuf->x;
y= se2->ibuf->y;
- switch(seq->type) {
- case SEQ_CROSS:
- do_cross_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_GAMCROSS:
- do_gammacross_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_ADD:
- do_add_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_SUB:
- do_sub_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_MUL:
- do_mul_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_ALPHAOVER:
- do_alphaover_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_OVERDROP:
- do_drop_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- do_alphaover_effect(fac, facf, x, y, se1->ibuf->rect, se->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_ALPHAUNDER:
- do_alphaunder_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_WIPE:
- do_wipe_effect(seq, fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_GLOW:
- do_glow_effect(seq, fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect);
- break;
- case SEQ_PLUGIN:
- if(seq->plugin && seq->plugin->doit) {
-
- if((G.f & G_PLAYANIM)==0) waitcursor(1);
-
- if(seq->plugin->cfra)
- *(seq->plugin->cfra)= frame_to_float(CFRA);
-
- cp = PIL_dynlib_find_symbol(
- seq->plugin->handle, "seqname");
-
- if(cp) strncpy(cp, seq->name+2, 22);
-
- if (seq->plugin->current_private_data) {
- *seq->plugin->current_private_data
- = seq->plugin->instance_private_data;
- }
-
- if (seq->plugin->version<=2) {
- if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf);
- if(se2->ibuf) IMB_convert_rgba_to_abgr(se2->ibuf);
- if(se3->ibuf) IMB_convert_rgba_to_abgr(se3->ibuf);
- }
-
- ((SeqDoit)seq->plugin->doit)(
- seq->plugin->data, fac, facf, x, y,
- se1->ibuf, se2->ibuf, se->ibuf, se3->ibuf);
-
- if (seq->plugin->version<=2) {
- if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf);
- if(se2->ibuf) IMB_convert_rgba_to_abgr(se2->ibuf);
- if(se3->ibuf) IMB_convert_rgba_to_abgr(se3->ibuf);
- IMB_convert_rgba_to_abgr(se->ibuf);
- }
+ if (!se1->ibuf->rect_float && se->ibuf->rect_float) {
+ IMB_float_from_rect(se1->ibuf);
+ }
+ if (!se2->ibuf->rect_float && se->ibuf->rect_float) {
+ IMB_float_from_rect(se2->ibuf);
+ }
- if((G.f & G_PLAYANIM)==0) waitcursor(0);
- }
- break;
+ if (!se1->ibuf->rect && !se->ibuf->rect_float) {
+ IMB_rect_from_float(se1->ibuf);
+ }
+ if (!se2->ibuf->rect && !se->ibuf->rect_float) {
+ IMB_rect_from_float(se2->ibuf);
}
+ sh.execute(seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf,
+ se->ibuf);
}
StripElem *give_stripelem(Sequence *seq, int cfra)
@@ -1927,8 +646,12 @@ static void do_seq_unref_cfra(ListBase *seqbase, int cfra)
if(seq->seqbase.first) {
- if(cfra< seq->start) do_seq_unref_cfra(&seq->seqbase, seq->start);
- else if(cfra> seq->start+seq->len-1) do_seq_unref_cfra(&seq->seqbase, seq->start+seq->len-1);
+ if(cfra< seq->start) do_seq_unref_cfra(
+ &seq->seqbase, seq->start);
+ else if(cfra> seq->start+seq->len-1)
+ do_seq_unref_cfra(
+ &seq->seqbase,
+ seq->start+seq->len-1);
else do_seq_unref_cfra(&seq->seqbase, cfra);
}
@@ -1951,16 +674,25 @@ static void do_seq_test_unref_cfra(ListBase *seqbase, int cfra)
if(seq->seqbase.first) {
- if(cfra< seq->start) do_seq_test_unref_cfra(&seq->seqbase, seq->start);
- else if(cfra> seq->start+seq->len-1) do_seq_test_unref_cfra(&seq->seqbase, seq->start+seq->len-1);
- else do_seq_test_unref_cfra(&seq->seqbase, cfra);
+ if(cfra< seq->start)
+ do_seq_test_unref_cfra(
+ &seq->seqbase, seq->start);
+ else if(cfra> seq->start+seq->len-1)
+ do_seq_test_unref_cfra(
+ &seq->seqbase,
+ seq->start+seq->len-1);
+ else do_seq_test_unref_cfra(
+ &seq->seqbase, cfra);
}
if (seq->curelem && seq->curelem->ibuf
&& seq->curelem->isneeded) {
- if (IMB_cache_limiter_get_refcount(seq->curelem->ibuf)) {
- fprintf(stderr, "refcount Arggh: %p, %d\n",
- seq, seq->type);
+ if (IMB_cache_limiter_get_refcount(
+ seq->curelem->ibuf)) {
+ fprintf(stderr,
+ "sequence.c: imbuf-refcount "
+ "Arggh: %p, %d\n",
+ seq, seq->type);
}
}
}
@@ -1968,43 +700,36 @@ static void do_seq_test_unref_cfra(ListBase *seqbase, int cfra)
}
}
+static void do_build_seq_depend(Sequence * seq, int cfra);
+
static void do_effect_depend(int cfra, Sequence * seq, StripElem *se)
{
float fac, facf;
+ struct SeqEffectHandle sh = get_sequence_effect(seq);
if(seq->ipo && seq->ipo->curve.first) {
do_seq_ipo(seq);
fac= seq->facf0;
facf= seq->facf1;
- } else if ( seq->type == SEQ_CROSS
- || seq->type == SEQ_GAMCROSS
- || seq->type == SEQ_PLUGIN
- || seq->type == SEQ_WIPE) {
- fac= (float)(cfra - seq->startdisp);
- facf= (float)(fac+0.5);
- fac /= seq->len;
- facf /= seq->len;
} else {
- fac= facf= 1.0;
- }
+ sh.get_default_fac(seq, cfra, &fac, &facf);
+ }
if( G.scene->r.mode & R_FIELDS ); else facf= fac;
- /* FIXME: This should be made available to external plugins too... */
- if (seq->type == SEQ_CROSS || seq->type == SEQ_GAMCROSS ||
- seq->type == SEQ_WIPE) {
- if (fac == 0.0 && facf == 0.0) {
- do_build_seq_depend(seq->seq1, cfra);
- } else if (fac == 1.0 && facf == 1.0) {
- do_build_seq_depend(seq->seq2, cfra);
- } else {
- do_build_seq_depend(seq->seq1, cfra);
- do_build_seq_depend(seq->seq2, cfra);
- }
- } else {
+ switch (sh.early_out(seq, fac, facf)) {
+ case 0:
do_build_seq_depend(seq->seq1, cfra);
do_build_seq_depend(seq->seq2, cfra);
+ break;
+ case 1:
+ do_build_seq_depend(seq->seq1, cfra);
+ break;
+ case 2:
+ do_build_seq_depend(seq->seq2, cfra);
+ break;
}
+
do_build_seq_depend(seq->seq3, cfra);
}
@@ -2120,16 +845,22 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra)
if(seq->type==SEQ_IMAGE) {
if(se->ok && se->ibuf==0) {
+ /* if playanim or render:
+ no waitcursor */
+ if((G.f & G_PLAYANIM)==0)
+ waitcursor(1);
- /* if playanim or render: no waitcursor */
- if((G.f & G_PLAYANIM)==0) waitcursor(1);
-
- strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
+ strncpy(name, seq->strip->dir,
+ FILE_MAXDIR-1);
strncat(name, se->name, FILE_MAXFILE);
- BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
- se->ibuf= IMB_loadiffname(name, IB_rect);
+ BLI_convertstringcode(name,
+ G.sce,
+ G.scene->r.cfra);
+ se->ibuf= IMB_loadiffname(name,
+ IB_rect);
- if((G.f & G_PLAYANIM)==0) waitcursor(0);
+ if((G.f & G_PLAYANIM)==0)
+ waitcursor(0);
if(se->ibuf==0) se->ok= 0;
else {
@@ -2146,10 +877,6 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra)
}
else if(seq->type==SEQ_MOVIE) {
if(se->ok && se->ibuf==0) {
-
- /* if playanim r render: no waitcursor */
- if((G.f & G_PLAYANIM)==0) waitcursor(1);
-
if(seq->anim==0) {
strncpy(name, seq->strip->dir, FILE_MAXDIR-1);
strncat(name, seq->strip->stripdata->name, FILE_MAXFILE-1);
@@ -2158,6 +885,9 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra)
seq->anim = openanim(name, IB_rect);
}
if(seq->anim) {
+ IMB_anim_set_preseek(
+ seq->anim,
+ seq->anim_preseek);
se->ibuf = IMB_anim_absolute(seq->anim, se->nr);
}
@@ -2172,7 +902,6 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra)
if(seq->mul==0.0) seq->mul= 1.0;
if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul);
}
- if((G.f & G_PLAYANIM)==0) waitcursor(0);
}
}
else if(seq->type==SEQ_SCENE && se->ibuf==0 && seq->scene) { // scene can be NULL after deletions
@@ -2438,180 +1167,6 @@ ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown)
}
-static void rgb_to_yuv(float rgb[3], float yuv[3]) {
- yuv[0]= 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2];
- yuv[1]= 0.492*(rgb[2] - yuv[0]);
- yuv[2]= 0.877*(rgb[0] - yuv[0]);
-
- /* Normalize */
- yuv[1]*= 255.0/(122*2.0);
- yuv[1]+= 0.5;
-
- yuv[2]*= 255.0/(157*2.0);
- yuv[2]+= 0.5;
-}
-
-static void scope_put_pixel(unsigned char* table, unsigned char * pos)
-{
- char newval = table[*pos];
- pos[0] = pos[1] = pos[2] = newval;
- pos[3] = 255;
-}
-
-static void wform_put_line(int w,
- unsigned char * last_pos, unsigned char * new_pos)
-{
- if (last_pos > new_pos) {
- unsigned char* temp = new_pos;
- new_pos = last_pos;
- last_pos = temp;
- }
-
- while (last_pos < new_pos) {
- if (last_pos[0] == 0) {
- last_pos[0] = last_pos[1] = last_pos[2] = 32;
- last_pos[3] = 255;
- }
- last_pos += 4*w;
- }
-}
-
-struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf)
-{
- struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0);
- int x,y;
- unsigned char* src = (unsigned char*) ibuf->rect;
- unsigned char* tgt = (unsigned char*) rval->rect;
- int w = ibuf->x + 3;
- int h = 515;
- float waveform_gamma = 0.2;
- unsigned char wtable[256];
-
- for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
- waveform_gamma)*255);
- }
-
- for (y = 0; y < h; y++) {
- unsigned char * last_p = 0;
-
- for (x = 0; x < w; x++) {
- unsigned char * rgb = src + 4 * (ibuf->x * y + x);
- float v = 1.0 *
- ( 0.299*rgb[0]
- + 0.587*rgb[1]
- + 0.114*rgb[2]) / 255.0;
- unsigned char * p = tgt;
- p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1);
-
- scope_put_pixel(wtable, p);
- p += 4 * w;
- scope_put_pixel(wtable, p);
-
- if (last_p != 0) {
- wform_put_line(w, last_p, p);
- }
- last_p = p;
- }
- }
-
- for (x = 0; x < w; x++) {
- unsigned char * p = tgt + 4 * x;
- p[1] = p[3] = 255.0;
- p[4 * w + 1] = p[4 * w + 3] = 255.0;
- p = tgt + 4 * (w * (h - 1) + x);
- p[1] = p[3] = 255.0;
- p[-4 * w + 1] = p[-4 * w + 3] = 255.0;
- }
-
- for (y = 0; y < h; y++) {
- unsigned char * p = tgt + 4 * w * y;
- p[1] = p[3] = 255.0;
- p[4 + 1] = p[4 + 3] = 255.0;
- p = tgt + 4 * (w * y + w - 1);
- p[1] = p[3] = 255.0;
- p[-4 + 1] = p[-4 + 3] = 255.0;
- }
-
- return rval;
-}
-
-static void vectorscope_put_cross(unsigned char r, unsigned char g,
- unsigned char b,
- char * tgt, int w, int h, int size)
-{
- float rgb[3], yuv[3];
- char * p;
- int x = 0;
- int y = 0;
-
- rgb[0]= (float)r/255.0;
- rgb[1]= (float)g/255.0;
- rgb[2]= (float)b/255.0;
- rgb_to_yuv(rgb, yuv);
-
- p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
- + (int) ((yuv[1] * (w - 3) + 1)));
-
- if (r == 0 && g == 0 && b == 0) {
- r = 255;
- }
-
- for (y = -size; y <= size; y++) {
- for (x = -size; x <= size; x++) {
- char * q = p + 4 * (y * w + x);
- q[0] = r; q[1] = g; q[2] = b; q[3] = 255;
- }
- }
-}
-
-struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf)
-{
- struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0);
- int x,y;
- char* src = (char*) ibuf->rect;
- char* tgt = (char*) rval->rect;
- float rgb[3], yuv[3];
- int w = 515;
- int h = 515;
- float scope_gamma = 0.2;
- unsigned char wtable[256];
-
- for (x = 0; x < 256; x++) {
- wtable[x] = (unsigned char) (pow(((float) x + 1)/256,
- scope_gamma)*255);
- }
-
- for (x = 0; x <= 255; x++) {
- vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1);
- vectorscope_put_cross(255 , x, 0, tgt, w, h, 1);
- vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1);
- vectorscope_put_cross(0, 255, x, tgt, w, h, 1);
- vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1);
- vectorscope_put_cross(x, 0, 255, tgt, w, h, 1);
- }
-
- for (y = 0; y < h; y++) {
- for (x = 0; x < w; x++) {
- char * src1 = src + 4 * (ibuf->x * y + x);
- char * p;
-
- rgb[0]= (float)src1[0]/255.0;
- rgb[1]= (float)src1[1]/255.0;
- rgb[2]= (float)src1[2]/255.0;
- rgb_to_yuv(rgb, yuv);
-
- p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1))
- + (int) ((yuv[1] * (w - 3) + 1)));
- scope_put_pixel(wtable, p);
- }
- }
-
- vectorscope_put_cross(0, 0, 0, tgt, w, h, 3);
-
- return rval;
-}
-
void free_imbuf_effect_spec(int cfra)
{
Sequence *seq;