void InfoWindow::update_thumbnail_for_clip(unsigned int clip_number) { if (clip_number >= clips_.size()) { g_critical("%s: Clip number bigger than size of known clips.", __FUNCTION__); return; } Clip *clip = app_->get_clip(clip_number); ClipInfoBox *clip_info = clips_.at(clip_number).get(); unsigned int frames = clip->size(); if (frames == 0) clutter_actor_hide(clip_info->image_); else { clutter_actor_show(clip_info->image_); Image *image = clip->get_image(0); if (image == 0) std::cout << __FUNCTION__ << ": Could not get a handle to any image!" << std::endl; else { std::string file_name = clip->get_image_full_path(image); load_thumbnail_from_file(CLUTTER_TEXTURE(clip_info->image_), file_name, 80, 60); } } }
/** * Slot for the Controller's add_frame_signal_ signal. * * Updates the onionskin texture */ void Gui::on_frame_added(unsigned int clip_number, unsigned int image_number) { if (owner_->get_configuration()->get_verbose()) std::cout << "Gui::on_frame_added" << std::endl; // Rotate the textures ClutterActor* _tmp = onionskin_textures_.back(); onionskin_textures_.insert(onionskin_textures_.begin() + 0, _tmp); onionskin_textures_.pop_back(); // Get image file name Clip* clip = owner_->get_clip(clip_number); Image* image = clip->get_image(image_number); if (image == 0) std::cout << __FUNCTION__ << ": Could not get a handle to any image!" << std::endl; else { GError *error = NULL; gboolean success; std::string file_name = clip->get_image_full_path(image); // Load file //std::cout << "Loading " << file_name << " for onion skin" << std::endl; success = clutter_texture_set_from_file(CLUTTER_TEXTURE(onionskin_textures_.at(0)), file_name.c_str(), &error); // If ever we have many onion skins, we might raise the latest one: // //clutter_container_raise_child(CLUTTER_CONTAINER(onionskin_group_), CLUTTER_ACTOR(onionskin_textures_.at(0)), NULL); if (!success) { std::cerr << "Failed to load pixbuf file: " << file_name << " " << error->message << std::endl; g_error_free(error); } else { //std::cout << "Loaded image " << image_full_path << std::endl; } } animate_flash(); }
bool Application::save_project(std::string &file_name) { namespace ss = statesaving; char buff[256]; // buff for node names and int properties xmlDocPtr doc = xmlNewDoc(XMLSTR "1.0"); // "project" node with its "name" attribute xmlNodePtr root_node = xmlNewNode(NULL, XMLSTR ss::ROOT_NODE); xmlDocSetRootElement(doc, root_node); xmlNewProp(root_node, XMLSTR ss::PROJECT_NAME_ATTR, XMLSTR ss::DEFAULT_PROJECT_NAME); xmlNewProp(root_node, XMLSTR ss::PROJECT_VERSION_ATTR, XMLSTR PACKAGE_VERSION); sprintf(buff, "%d", get_current_clip_number()); xmlNewProp(root_node, XMLSTR ss::CURRENT_CLIP_ATTR, XMLSTR buff); // "clips" node xmlNodePtr clips_node = xmlNewChild(root_node, NULL, XMLSTR ss::CLIPS_NODE, NULL); // No text contents for (ClipIterator iter = clips_.begin(); iter != clips_.end(); ++iter) { Clip *clip = iter->second.get(); if (clip->size() > 0) // do not save empty clips { xmlNodePtr clip_node = xmlNewChild(clips_node, NULL, XMLSTR ss::CLIP_NODE, NULL); // clip ID: sprintf(buff, "%d", clip->get_id()); xmlNewProp(clip_node, XMLSTR ss::CLIP_ID_PROPERTY, XMLSTR buff); // clip FPS: sprintf(buff, "%d", clip->get_playhead_fps()); xmlNewProp(clip_node, XMLSTR ss::CLIP_FPS_PROPERTY, XMLSTR buff); // clip direction: xmlNewProp(clip_node, XMLSTR ss::CLIP_DIRECTION_PROPERTY, XMLSTR clip->get_direction().c_str()); // images: xmlNodePtr images_node = xmlNewChild(clip_node, NULL, XMLSTR ss::IMAGES_NODE, NULL); for (unsigned int image_num = 0; image_num < clip->size(); image_num++) { Image *image = clip->get_image(image_num); xmlNodePtr image_node = xmlNewChild(images_node, NULL, XMLSTR ss::IMAGE_NODE, NULL); xmlNewProp(image_node, XMLSTR ss::IMAGE_NAME_ATTR, XMLSTR image->get_name().c_str()); } } } // Save document to file xmlSaveFormatFileEnc(file_name.c_str(), doc, "UTF-8", 1); if (config_->get_verbose()) std::cout << "Saved the project to " << file_name << std::endl; // Free the document + global variables that may have been allocated by the parser. xmlFreeDoc(doc); xmlCleanupParser(); return true; }
/** * Saves a GdkPixbuf image to the current clip. * * Needed, because the image might come from the last grabbed * frame, or the recording of every frame might be automatic. (video) * * The gdkpixbufsink element posts messages containing the pixbuf. */ void Pipeline::save_image_to_current_clip(GdkPixbuf *pixbuf) { Clip *thisclip = owner_->get_current_clip(); bool is_verbose = owner_->get_configuration()->get_verbose(); int current_clip_id = thisclip->get_id(); int w = gdk_pixbuf_get_width(pixbuf); int h = gdk_pixbuf_get_height(pixbuf); /* if this is the first frame grabbed, set frame properties in clip */ // TODO:2010-08-27:aalex:Use image size, not clip size. // A clip may contain images that are not the same size. if (! thisclip->get_has_recorded_frame()) { // TODO: each image should be a different size, if that's what it is. thisclip->set_width(w); thisclip->set_height(h); thisclip->set_has_recorded_frame(); } int new_image_number = thisclip->frame_add(); Image *new_image = thisclip->get_image(new_image_number); if (new_image == 0) { // This is very unlikely to happen std::cerr << "No image at " << new_image_number << std::endl; g_object_unref(pixbuf); return; } if (is_verbose) std::cout << "Grab a frame. Current clip: " << current_clip_id << ". Image number: " << new_image_number << std::endl; std::string file_name = thisclip->get_image_full_path(new_image); // We need 3 textures: // * the onionskin of the last frame grabbed. (or at the writehead position) // * the frame at the playhead position // * the current live input. (GST gives us this one) if (!gdk_pixbuf_save(pixbuf, file_name.c_str(), "jpeg", NULL, "quality", "100", NULL)) { g_print("Image %s could not be saved. Error\n", file_name.c_str()); } else { if (is_verbose) g_print("Image %s saved\n", file_name.c_str()); owner_->get_controller()->add_frame_signal_(current_clip_id, new_image_number); thisclip->remove_first_if_more_than(owner_->get_configuration()->get_max_images_per_clip()); } }
bool Pipeline::import_image(const std::string &file_name) { bool is_verbose = owner_->get_configuration()->get_verbose(); if (! toonloop::file_exists(file_name)) { if (is_verbose) std::cout << __FUNCTION__ << ": " << std::endl; return false; } Clip *clip = owner_->get_current_clip(); int clip_id = clip->get_id(); // TODO: set clip size if not set. int new_image_number = clip->frame_add(); Image *new_image = clip->get_image(new_image_number); if (new_image == 0) { // This is very unlikely to happen std::cerr << __FUNCTION__ << ": No image at " << new_image_number << std::endl; return false; } if (is_verbose) std::cout << "Import an image. Current clip: " << clip_id << ". Image number: " << new_image_number << std::endl; std::string save_as_file_name = clip->get_image_full_path(new_image); unsigned int width = (unsigned int) owner_->get_configuration()->get_capture_width(); unsigned int height = (unsigned int) owner_->get_configuration()->get_capture_height(); ImageImporter img(file_name, save_as_file_name, width, height, is_verbose); bool ok = img.resize(); if (! ok) return false; if (is_verbose) g_print("Image %s saved\n", save_as_file_name.c_str()); owner_->get_controller()->add_frame_signal_(clip_id, new_image_number); clip->remove_first_if_more_than(owner_->get_configuration()->get_max_images_per_clip()); return true; }