Skip to content

Commit

Permalink
allow to set callback as gif writer
Browse files Browse the repository at this point in the history
  • Loading branch information
sidorares committed May 24, 2013
1 parent df6f4bc commit 4018b0d
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 6 deletions.
36 changes: 36 additions & 0 deletions src/animated_gif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "animated_gif.h"
#include "buffer_compat.h"

#include <iostream>

using namespace v8;
using namespace node;

Expand All @@ -20,6 +22,7 @@ AnimatedGif::Initialize(Handle<Object> target)
NODE_SET_PROTOTYPE_METHOD(t, "getGif", GetGif);
NODE_SET_PROTOTYPE_METHOD(t, "end", End);
NODE_SET_PROTOTYPE_METHOD(t, "setOutputFile", SetOutputFile);
NODE_SET_PROTOTYPE_METHOD(t, "setOutputCallback", SetOutputCallback);
target->Set(String::NewSymbol("AnimatedGif"), t->GetFunction());
}

Expand Down Expand Up @@ -242,3 +245,36 @@ AnimatedGif::SetOutputFile(const Arguments &args)
return Undefined();
}

int
stream_writer(GifFileType *gif_file, const GifByteType *data, int size)
{
AnimatedGif *gif = (AnimatedGif *)gif_file->UserData;
Buffer *retbuf = Buffer::New(size);
memcpy(BufferData(retbuf), data, size);
Handle<Value> argv[1] = {
retbuf->handle_
};
//Local<Value> callback_v = gif->Wrap()->Get(String::New("ondata"));
//assert(callback_v->IsFunction());
//Local<Function> callback = Local<Function>::Cast(callback_v);
gif->ondata->Call(Context::GetCurrent()->Global(), 1, argv);
return size;
}

Handle<Value>
AnimatedGif::SetOutputCallback(const Arguments &args)
{
HandleScope scope;

if (args.Length() != 1)
return VException("One argument required - path to output file.");

if (!args[0]->IsFunction())
return VException("First argument must be string.");

Local<Function> callback = Local<Function>::Cast(args[0]);
AnimatedGif *gif = ObjectWrap::Unwrap<AnimatedGif>(args.This());
gif->ondata = Persistent<Function>::New(callback);
gif->gif_encoder.set_output_func(stream_writer, (void*)gif);
return Undefined();
}
4 changes: 4 additions & 0 deletions src/animated_gif.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class AnimatedGif : public node::ObjectWrap {
Color transparency_color;

public:

v8::Persistent<v8::Function> ondata;

static void Initialize(v8::Handle<v8::Object> target);

AnimatedGif(int wwidth, int hheight, buffer_type bbuf_type);
Expand All @@ -28,6 +31,7 @@ class AnimatedGif : public node::ObjectWrap {
static v8::Handle<v8::Value> End(const v8::Arguments &args);
static v8::Handle<v8::Value> GetGif(const v8::Arguments &args);
static v8::Handle<v8::Value> SetOutputFile(const v8::Arguments &args);
static v8::Handle<v8::Value> SetOutputCallback(const v8::Arguments &args);
};

#endif
Expand Down
20 changes: 14 additions & 6 deletions src/gif_encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ GifEncoder::get_gif_len() const
// Animated Gif Encoder
AnimatedGifEncoder::AnimatedGifEncoder(int wwidth, int hheight, buffer_type bbuf_type) :
width(wwidth), height(hheight), buf_type(bbuf_type),
gif_buf(NULL), output_color_map(NULL), gif_file(NULL), color_map_size(256),
gif_buf(NULL), output_color_map(NULL), gif_file(NULL), color_map_size(256), write_func(0), write_user_data(0),
headers_set(false) {}

AnimatedGifEncoder::~AnimatedGifEncoder() { end_encoding(); }
Expand All @@ -258,17 +258,19 @@ void
AnimatedGifEncoder::new_frame(unsigned char *data, int delay)
{
if (!gif_file) {
if (file_name.empty()) { // memory writer
if (write_func != NULL) {
int nError;
gif_file = EGifOpen(write_user_data, write_func, &nError);
if (!gif_file) throw "EGifOpen in AnimatedGifEncoder::new_frame failed";
} else if (file_name.empty()) { // memory writer
int nError;
gif_file = EGifOpen(&gif, gif_writer, &nError);
if (!gif_file) throw "EGifOpen in AnimatedGifEncoder::new_frame failed";
}
else {
} else {
int nError;
gif_file = EGifOpenFileName(file_name.c_str(), FALSE, &nError);
if (!gif_file) throw "EGifOpenFileName in AnimatedGifEncoder::new_frame failed";
}

output_color_map = GifMakeMapObject(color_map_size, ext_web_safe_palette);
if (!output_color_map) throw "MakeMapObject in AnimatedGifEncoder::new_frame failed";

Expand Down Expand Up @@ -323,7 +325,7 @@ AnimatedGifEncoder::new_frame(unsigned char *data, int delay)
if (EGifPutImageDesc(gif_file, 0, 0, width, height, FALSE, NULL) == GIF_ERROR) {
throw "EGifPutImageDesc in AnimatedGifEncoder::new_frame failed";
}

GifByteType *gif_bufp = gif_buf;
for (int i = 0; i < height; i++) {
if (EGifPutLine(gif_file, gif_bufp, width) == GIF_ERROR) {
Expand Down Expand Up @@ -372,3 +374,9 @@ AnimatedGifEncoder::set_output_file(const char *ffile_name)
file_name = ffile_name;
}

void
AnimatedGifEncoder::set_output_func(OutputFunc func, void *user_data)
{
write_func = func;
write_user_data = user_data;
}
3 changes: 3 additions & 0 deletions src/gif_encoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class AnimatedGifEncoder {
Color transparency_color;

std::string file_name;
OutputFunc write_func;
void *write_user_data;

void end_encoding();
public:
Expand All @@ -61,6 +63,7 @@ class AnimatedGifEncoder {
void set_transparency_color(const Color &c);

void set_output_file(const char *ffile_name);
void set_output_func(OutputFunc func, void* user_data);

const unsigned char *get_gif() const;
const int get_gif_len() const;
Expand Down

0 comments on commit 4018b0d

Please sign in to comment.