void Instance::save_surface(const synfig::Surface &surface, const synfig::String &filename) { if (surface.get_h() <= 0 || surface.get_w() <= 0) return; String ext = filename_extension(filename); if (ext.empty()) return; ext.erase(0, 1); String tmpfile = FileContainerTemporary::generate_temporary_filename(); etl::handle<Target_Scanline> target = etl::handle<Target_Scanline>(Target::create(Target::ext_book()[ext],tmpfile,TargetParam())); if (!target) return; target->set_canvas(get_canvas()); RendDesc desc; desc.set_w(surface.get_w()); desc.set_h(surface.get_h()); desc.set_x_res(1); desc.set_y_res(1); desc.set_frame_rate(1); desc.set_frame(0); desc.set_frame_start(0); desc.set_frame_end(0); target->set_rend_desc(&desc); target->add_frame(&surface); target = NULL; FileSystem::copy(FileSystemNative::instance(), tmpfile, get_file_system(), filename); FileSystemNative::instance()->file_remove(tmpfile); }
void software::Contour::render_contour( synfig::Surface &target_surface, const rendering::Contour::ChunkList &chunks, bool invert, bool antialias, rendering::Contour::WindingStyle winding_style, const Matrix &transform_matrix, const Color &color, Color::value_type opacity, Color::BlendMethod blend_method ) { Polyspan polyspan; polyspan.init(0, 0, target_surface.get_w(), target_surface.get_h()); build_polyspan(chunks, transform_matrix, polyspan); polyspan.sort_marks(); return render_polyspan( target_surface, polyspan, invert, antialias, winding_style, color, opacity, blend_method ); }
void Action::LayerPaint::PaintStroke::copy_to_cairo_surface(const synfig::Surface &surface, synfig::CairoSurface &csurface) { int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, surface.get_w()); unsigned char *data = (unsigned char*)malloc(stride * surface.get_h()); unsigned char *p = data; for(int y = 0; y < surface.get_h(); ++y, p += stride) { CairoColor *c = (CairoColor*)p; for(int x = 0; x < surface.get_w(); ++x, ++c) *c = CairoColor(surface[y][x]); } cairo_surface_t *cs = cairo_image_surface_create_for_data( data, CAIRO_FORMAT_ARGB32, surface.get_w(), surface.get_h(), stride ); csurface.set_cairo_surface(cs); csurface.map_cairo_image(); cairo_surface_destroy(cs); }
bool exr_mptr::get_frame(synfig::Surface &out_surface, const synfig::RendDesc &/*renddesc*/, Time, synfig::ProgressCallback *cb) { try { Imf::RgbaInputFile in(identifier.filename.c_str()); int w = in.dataWindow().max.x - in.dataWindow().min.x + 1; int h = in.dataWindow().max.y - in.dataWindow().min.y + 1; //int dx = in.dataWindow().min.x; //int dy = in.dataWindow().min.y; etl::surface<Imf::Rgba> in_surface; in_surface.set_wh(w,h); in.setFrameBuffer (reinterpret_cast<Imf::Rgba *>(in_surface[0]), 1, w); in.readPixels (in.dataWindow().min.y, in.dataWindow().max.y); int x; int y; out_surface.set_wh(w,h); for(y=0;y<out_surface.get_h();y++) for(x=0;x<out_surface.get_w();x++) { Color &color(out_surface[y][x]); Imf::Rgba &rgba(in_surface[y][x]); color.set_r(rgba.r); color.set_g(rgba.g); color.set_b(rgba.b); color.set_a(rgba.a); } } catch (const std::exception& e) { if(cb)cb->error(e.what()); else synfig::error(e.what()); return false; } return true; }
bool bmp_mptr::get_frame(synfig::Surface &surface, const synfig::RendDesc &/*renddesc*/, Time /*time*/, synfig::ProgressCallback *cb) { FILE *file=fopen(filename.c_str(),"rb"); if(!file) { if(cb)cb->error("bmp_mptr::GetFrame(): "+strprintf(_("Unable to open %s"),filename.c_str())); else synfig::error("bmp_mptr::GetFrame(): "+strprintf(_("Unable to open %s"),filename.c_str())); return false; } synfig::BITMAPFILEHEADER fileheader; synfig::BITMAPINFOHEADER infoheader; char b_char=fgetc(file); char m_char=fgetc(file); if(b_char!='B' || m_char!='M') { if(cb)cb->error("bmp_mptr::GetFrame(): "+strprintf(_("%s is not in BMP format"),filename.c_str())); else synfig::error("bmp_mptr::GetFrame(): "+strprintf(_("%s is not in BMP format"),filename.c_str())); return false; } if(fread(&fileheader.bfSize, 1, sizeof(synfig::BITMAPFILEHEADER)-4, file)!=sizeof(synfig::BITMAPFILEHEADER)-4) { String str("bmp_mptr::get_frame(): "+strprintf(_("Failure while reading BITMAPFILEHEADER from %s"),filename.c_str())); if(cb)cb->error(str); else synfig::error(str); return false; } if(fread(&infoheader, 1, sizeof(synfig::BITMAPINFOHEADER), file)!=sizeof(synfig::BITMAPINFOHEADER)) { String str("bmp_mptr::get_frame(): "+strprintf(_("Failure while reading BITMAPINFOHEADER from %s"),filename.c_str())); if(cb)cb->error(str); else synfig::error(str); return false; } int offset=little_endian(fileheader.bfOffsetBits); if(offset!=sizeof(synfig::BITMAPFILEHEADER)+sizeof(synfig::BITMAPINFOHEADER)-2) { String str("bmp_mptr::get_frame(): "+strprintf(_("Bad BITMAPFILEHEADER in %s. (bfOffsetBits=%d, should be %d)"),filename.c_str(),offset,sizeof(synfig::BITMAPFILEHEADER)+sizeof(synfig::BITMAPINFOHEADER)-2)); if(cb)cb->error(str); else synfig::error(str); return false; } if(little_endian(infoheader.biSize)!=little_endian(40)) { String str("bmp_mptr::get_frame(): "+strprintf(_("Bad BITMAPINFOHEADER in %s. (biSize=%d, should be 40)"),filename.c_str(),little_endian(infoheader.biSize))); if(cb)cb->error(str); else synfig::error(str); return false; } int w,h,bit_count; w=little_endian(infoheader.biWidth); h=little_endian(infoheader.biHeight); bit_count=little_endian_short(infoheader.biBitCount); synfig::warning("w:%d\n",w); synfig::warning("h:%d\n",h); synfig::warning("bit_count:%d\n",bit_count); if(little_endian(infoheader.biCompression)) { if(cb)cb->error("bmp_mptr::GetFrame(): "+string(_("Reading compressed bitmaps is not supported"))); else synfig::error("bmp_mptr::GetFrame(): "+string(_("Reading compressed bitmaps is not supported"))); return false; } if(bit_count!=24 && bit_count!=32) { if(cb)cb->error("bmp_mptr::GetFrame(): "+strprintf(_("Unsupported bit depth (bit_count=%d, should be 24 or 32)"),bit_count)); else synfig::error("bmp_mptr::GetFrame(): "+strprintf(_("Unsupported bit depth (bit_count=%d, should be 24 or 32)"),bit_count)); return false; } int x; int y; surface.set_wh(w,h); for(y=0;y<surface.get_h();y++) for(x=0;x<surface.get_w();x++) { // float b=(float)(unsigned char)fgetc(file)*(1.0/255.0); // float g=(float)(unsigned char)fgetc(file)*(1.0/255.0); // float r=(float)(unsigned char)fgetc(file)*(1.0/255.0); float b=gamma().b_U8_to_F32((unsigned char)fgetc(file)); float g=gamma().g_U8_to_F32((unsigned char)fgetc(file)); float r=gamma().r_U8_to_F32((unsigned char)fgetc(file)); surface[h-y-1][x]=Color( r, g, b, 1.0 ); if(bit_count==32) fgetc(file); } fclose(file); return true; }
bool imagemagick_mptr::get_frame(synfig::Surface &surface, const synfig::RendDesc &renddesc, Time /*time*/, synfig::ProgressCallback *cb) { //#define HAS_LIBPNG 1 #if 1 if(identifier.filename.empty()) { if(cb)cb->error(_("No file to load")); else synfig::error(_("No file to load")); return false; } string temp_file="/tmp/deleteme.png"; string temp_container_file=""; // todo: "container:" and "images" literals if (identifier.filename.substr(0, String("#images/").size())=="#images/") { temp_container_file = "/tmp/synfigtmp.png"; // try to copy file to a temp file if (!FileSystem::copy(identifier.file_system, identifier.filename, identifier.file_system, temp_container_file)) { if(cb)cb->error(_("Cannot create temporary file of ")+ identifier.filename); else synfig::error(_("Cannot create temporary file of ")+ identifier.filename); return false; } } string filename = temp_container_file.size() == 0 ? identifier.filename : temp_container_file; #if defined(WIN32_PIPE_TO_PROCESSES) if(file) pclose(file); string command; if(identifier.filename.find("psd")!=String::npos) command=strprintf("convert \"%s\" -flatten \"png32:%s\"\n",filename.c_str(),temp_file.c_str()); else command=strprintf("convert \"%s\" \"png32:%s\"\n",filename.c_str(),temp_file.c_str()); if(system(command.c_str())!=0) return false; #elif defined(UNIX_PIPE_TO_PROCESSES) string output="png32:"+temp_file; pid_t pid = fork(); if (pid == -1) { return false; } if (pid == 0){ // Child process if(identifier.filename.find("psd")!=String::npos) execlp("convert", "convert", filename.c_str(), "-flatten", output.c_str(), (const char *)NULL); else execlp("convert", "convert", filename.c_str(), output.c_str(), (const char *)NULL); // We should never reach here unless the exec failed return false; } int status; waitpid(pid, &status, 0); if( (WIFEXITED(status) && WEXITSTATUS(status) != 0) || !WIFEXITED(status) ) return false; #else #error There are no known APIs for creating child processes #endif //if any delete container tmp file if(temp_container_file.size()) identifier.file_system->file_remove(temp_container_file); Importer::Handle importer(Importer::open(synfig::FileSystem::Identifier(synfig::FileSystemNative::instance(), temp_file))); if(!importer) { if(cb)cb->error(_("Unable to open ")+temp_file); else synfig::error(_("Unable to open ")+temp_file); return false; } if(!importer->get_frame(surface,renddesc,0,cb)) { if(cb)cb->error(_("Unable to get frame from ")+temp_file); else synfig::error(_("Unable to get frame from ")+temp_file); return false; } if(!surface) { if(cb)cb->error(_("Bad surface from ")+temp_file); else synfig::error(_("Bad surface from ")+temp_file); return false; } if(1) { // remove odd premultiplication for(int i=0;i<surface.get_w()*surface.get_h();i++) { Color c(surface[0][i]); if(c.get_a()) { surface[0][i].set_r(c.get_r()/c.get_a()/c.get_a()); surface[0][i].set_g(c.get_g()/c.get_a()/c.get_a()); surface[0][i].set_b(c.get_b()/c.get_a()/c.get_a()); } else { surface[0][i].set_r(0); surface[0][i].set_g(0); surface[0][i].set_b(0); } surface[0][i].set_a(c.get_a()); } } Surface bleh(surface); surface=bleh; //remove(temp_file.c_str()); return true; #else #error This code contains tempfile and arbitrary shell command execution vulnerabilities if(file) pclose(file); string command; if(identifier.filename.empty()) { if(cb)cb->error(_("No file to load")); else synfig::error(_("No file to load")); return false; } command=strprintf("convert \"%s\" -flatten ppm:-\n",identifier.filename.c_str()); file=popen(command.c_str(),POPEN_BINARY_READ_TYPE); if(!file) { if(cb)cb->error(_("Unable to open pipe to imagemagick")); else synfig::error(_("Unable to open pipe to imagemagick")); return false; } int w,h; float divisor; char cookie[2]; while((cookie[0]=fgetc(file))!='P' && !feof(file)); if(feof(file)) { if(cb)cb->error(_("Reached end of stream without finding PPM header")); else synfig::error(_("Reached end of stream without finding PPM header")); return false; } cookie[1]=fgetc(file); if(cookie[0]!='P' || cookie[1]!='6') { if(cb)cb->error(string(_("stream not in PPM format"))+" \""+cookie[0]+cookie[1]+'"'); else synfig::error(string(_("stream not in PPM format"))+" \""+cookie[0]+cookie[1]+'"'); return false; } fgetc(file); fscanf(file,"%d %d\n",&w,&h); fscanf(file,"%f",&divisor); fgetc(file); if(feof(file)) { if(cb)cb->error(_("Premature end of file (after header)")); else synfig::error(_("Premature end of file (after header)")); return false; } int x; int y; frame.set_wh(w,h); for(y=0;y<frame.get_h();y++) for(x=0;x<frame.get_w();x++) { if(feof(file)) { if(cb)cb->error(_("Premature end of file")); else synfig::error(_("Premature end of file")); return false; } float b=gamma().r_U8_to_F32((unsigned char)fgetc(file)); float g=gamma().g_U8_to_F32((unsigned char)fgetc(file)); float r=gamma().b_U8_to_F32((unsigned char)fgetc(file)); /* float b=(float)(unsigned char)fgetc(file)/divisor; float g=(float)(unsigned char)fgetc(file)/divisor; float r=(float)(unsigned char)fgetc(file)/divisor; */ frame[y][x]=Color( b, g, r, 1.0 ); } surface=frame; return true; #endif }
bool bmp_mptr::get_frame(synfig::Surface &surface, const synfig::RendDesc &/*renddesc*/, Time /*time*/, synfig::ProgressCallback *cb) { FileSystem::ReadStreamHandle stream = identifier.get_read_stream(); if(!stream) { if(cb)cb->error("bmp_mptr::GetFrame(): "+strprintf(_("Unable to open %s"),identifier.filename.c_str())); else synfig::error("bmp_mptr::GetFrame(): "+strprintf(_("Unable to open %s"),identifier.filename.c_str())); return false; } synfig::BITMAP::FILEHEADER fileheader; synfig::BITMAP::INFOHEADER infoheader; if (!stream->read_variable(fileheader.bfType) || fileheader.bfType[0] != 'B' || fileheader.bfType[1] != 'M') { if(cb)cb->error("bmp_mptr::GetFrame(): "+strprintf(_("%s is not in BMP format"),identifier.filename.c_str())); else synfig::error("bmp_mptr::GetFrame(): "+strprintf(_("%s is not in BMP format"),identifier.filename.c_str())); return false; } if(!stream->read_whole_block(&fileheader.bfSize, sizeof(synfig::BITMAP::FILEHEADER)-2)) { String str("bmp_mptr::get_frame(): "+strprintf(_("Failure while reading BITMAP::FILEHEADER from %s"),identifier.filename.c_str())); if(cb)cb->error(str); else synfig::error(str); return false; } if(!stream->read_whole_block(&infoheader, sizeof(synfig::BITMAP::INFOHEADER))) { String str("bmp_mptr::get_frame(): "+strprintf(_("Failure while reading BITMAP::INFOHEADER from %s"),identifier.filename.c_str())); if(cb)cb->error(str); else synfig::error(str); return false; } int offset=little_endian(fileheader.bfOffsetBits); if(offset!=sizeof(synfig::BITMAP::FILEHEADER)+sizeof(synfig::BITMAP::INFOHEADER)) { String str("bmp_mptr::get_frame(): "+strprintf(_("Bad BITMAP::FILEHEADER in %s. (bfOffsetBits=%d, should be %d)"),identifier.filename.c_str(),offset,sizeof(synfig::BITMAP::FILEHEADER)+sizeof(synfig::BITMAP::INFOHEADER))); if(cb)cb->error(str); else synfig::error(str); return false; } if(little_endian(infoheader.biSize)!=sizeof(synfig::BITMAP::INFOHEADER)) { String str("bmp_mptr::get_frame(): "+strprintf(_("Bad BITMAP::INFOHEADER in %s. (biSize=%d, should be %d)"),identifier.filename.c_str(),little_endian(infoheader.biSize),sizeof(synfig::BITMAP::INFOHEADER))); if(cb)cb->error(str); else synfig::error(str); return false; } int w,h,bit_count; w=little_endian(infoheader.biWidth); h=little_endian(infoheader.biHeight); bit_count=little_endian_short(infoheader.biBitCount); synfig::warning("w:%d\n",w); synfig::warning("h:%d\n",h); synfig::warning("bit_count:%d\n",bit_count); if(little_endian(infoheader.biCompression)) { if(cb)cb->error("bmp_mptr::GetFrame(): "+string(_("Reading compressed bitmaps is not supported"))); else synfig::error("bmp_mptr::GetFrame(): "+string(_("Reading compressed bitmaps is not supported"))); return false; } if(bit_count!=24 && bit_count!=32) { if(cb)cb->error("bmp_mptr::GetFrame(): "+strprintf(_("Unsupported bit depth (bit_count=%d, should be 24 or 32)"),bit_count)); else synfig::error("bmp_mptr::GetFrame(): "+strprintf(_("Unsupported bit depth (bit_count=%d, should be 24 or 32)"),bit_count)); return false; } int x; int y; surface.set_wh(w,h); for(y=0;y<surface.get_h();y++) for(x=0;x<surface.get_w();x++) { // float b=(float)(unsigned char)stream->getc()*(1.0/255.0); // float g=(float)(unsigned char)stream->getc()*(1.0/255.0); // float r=(float)(unsigned char)stream->getc()*(1.0/255.0); float b=gamma().b_U8_to_F32((unsigned char)stream->get()); float g=gamma().g_U8_to_F32((unsigned char)stream->get()); float r=gamma().r_U8_to_F32((unsigned char)stream->get()); surface[h-y-1][x]=Color( r, g, b, 1.0 ); if(bit_count==32) stream->get(); } return true; }
static inline Color nearest(const synfig::Surface &surface, const Vector &pos) { return surface[ std::max(std::min((int)floor(pos[1]), surface.get_h()-1), 0) ] [ std::max(std::min((int)floor(pos[0]), surface.get_w()-1), 0) ]; }