this patch features several cleanups and bugfixes for the sequencer:
- blur works again (this was a serious bug in gamwarp...) - seperates all sequence effects into a seperate file with a clean interface - thereby fixing some obscure segfaults - seperates the scope views into a seperate file - adds float support to all effects and scope views - removes a bad level call to open_plugin_seq - FFMPEG seeking improved a lot. - FFMPEG compiles with debian sarge version cleanly - Makes hdaudio seek and resample code really work
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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; */
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -153,6 +153,7 @@ struct anim {
|
||||
int orientation;
|
||||
size_t framesize;
|
||||
int interlacing;
|
||||
int preseek;
|
||||
|
||||
/* data */
|
||||
struct ImBuf * ibuf1, * ibuf2;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -624,23 +644,50 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) {
|
||||
(unsigned char*) ibuf->rect,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
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) {
|
||||
rectf = ibuf->rect_float;
|
||||
|
||||
gamma = 1.0 / gamma;
|
||||
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
83
source/blender/include/BSE_seqeffects.h
Normal file
83
source/blender/include/BSE_seqeffects.h
Normal file
@@ -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
|
||||
|
||||
38
source/blender/include/BSE_seqscopes.h
Normal file
38
source/blender/include/BSE_seqscopes.h
Normal file
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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);
|
||||
/* free previous effect and init new effect */
|
||||
struct SeqEffectHandle sh;
|
||||
|
||||
switch(last_seq->type){
|
||||
case SEQ_WIPE:
|
||||
init_wipe_effect(last_seq);
|
||||
break;
|
||||
case SEQ_GLOW:
|
||||
init_glow_effect(last_seq);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -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) {
|
||||
long decode_pos = 0;
|
||||
|
||||
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;
|
||||
|
||||
av_seek_frame(hdaudio->pFormatCtx, -1,
|
||||
(long long) frame_position * AV_TIME_BASE,
|
||||
AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
|
||||
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) {
|
||||
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;
|
||||
int data_size;
|
||||
int len;
|
||||
uint8_t *audio_pkt_data;
|
||||
int audio_pkt_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;
|
||||
}
|
||||
if(packet.stream_index != hdaudio->audioStream) {
|
||||
av_free_packet(&packet);
|
||||
continue;
|
||||
}
|
||||
|
||||
audio_pkt_size -= len;
|
||||
audio_pkt_data += len;
|
||||
audio_pkt_data = packet.data;
|
||||
audio_pkt_size = packet.size;
|
||||
|
||||
decode_pos +=
|
||||
data_size / sizeof(short);
|
||||
if (decode_pos + data_size
|
||||
/ sizeof(short)
|
||||
> hdaudio->decode_cache_size) {
|
||||
av_free_packet(&packet);
|
||||
break;
|
||||
}
|
||||
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)];
|
||||
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;
|
||||
|
||||
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);
|
||||
hdaudio->frame_position = frame_position;
|
||||
|
||||
if (st_time == AV_NOPTS_VALUE) {
|
||||
st_time = 0;
|
||||
}
|
||||
memcpy(target_buffer, temp_buffer,
|
||||
nb_samples * target_channels * sizeof(short));
|
||||
|
||||
pos += st_time * AV_TIME_BASE * time_base;
|
||||
|
||||
av_seek_frame(hdaudio->pFormatCtx, -1,
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 (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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
2515
source/blender/src/seqeffects.c
Normal file
2515
source/blender/src/seqeffects.c
Normal file
@@ -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;
|
||||
}
|
||||
340
source/blender/src/seqscopes.c
Normal file
340
source/blender/src/seqscopes.c
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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= ibuf->rect;
|
||||
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--) {
|
||||
rt_float = ibuf->rect_float;
|
||||
|
||||
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;
|
||||
if (rt) {
|
||||
while(a--) {
|
||||
|
||||
rt+= 4;
|
||||
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((G.f & G_PLAYANIM)==0) waitcursor(0);
|
||||
}
|
||||
break;
|
||||
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 (!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;
|
||||
|
||||
Reference in New Issue
Block a user