CanvasImage: support for http protocol.

- Download and display images.
This commit is contained in:
Thomas Geymayer
2014-03-18 18:33:44 +01:00
parent b322864ef4
commit 6c75e2fe3c
4 changed files with 85 additions and 10 deletions

View File

@@ -23,6 +23,7 @@
namespace simgear
{
namespace HTTP { class Client; }
namespace canvas
{
@@ -35,6 +36,7 @@ namespace canvas
virtual void addCamera(osg::Camera* camera) const = 0;
virtual void removeCamera(osg::Camera* camera) const = 0;
virtual osg::Image* getImage(const std::string& path) const = 0;
virtual HTTP::Client* getHTTPClient() const = 0;
};
} // namespace canvas

View File

@@ -25,12 +25,12 @@
#include <simgear/scene/util/OsgMath.hxx>
#include <simgear/scene/util/parse_color.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/io/HTTPClient.hxx>
#include <osg/Array>
#include <osg/Geometry>
#include <osg/PrimitiveSet>
#include <boost/algorithm/string/predicate.hpp>
#include <osgDB/Registry>
namespace simgear
{
@@ -522,18 +522,29 @@ namespace canvas
}
else if( name == "file" )
{
static const std::string CANVAS_PROTOCOL = "canvas://";
const std::string& path = child->getStringValue();
static const std::string PROTOCOL_SEP = "://";
CanvasPtr canvas = _canvas.lock();
if( !canvas )
std::string url = child->getStringValue(),
protocol, path;
size_t sep_pos = url.find(PROTOCOL_SEP);
if( sep_pos != std::string::npos )
{
SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No canvas available");
return;
protocol = url.substr(0, sep_pos);
path = url.substr(sep_pos + PROTOCOL_SEP.length());
}
else
path = url;
if( boost::starts_with(path, CANVAS_PROTOCOL) )
if( protocol == "canvas" )
{
CanvasPtr canvas = _canvas.lock();
if( !canvas )
{
SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No canvas available");
return;
}
CanvasMgr* canvas_mgr = canvas->getCanvasMgr();
if( !canvas_mgr )
{
@@ -544,7 +555,7 @@ namespace canvas
const SGPropertyNode* canvas_node =
canvas_mgr->getPropertyRoot()
->getParent()
->getNode( path.substr(CANVAS_PROTOCOL.size()) );
->getNode( path );
if( !canvas_node )
{
SG_LOG(SG_GL, SG_ALERT, "canvas::Image: No such canvas: " << path);
@@ -562,6 +573,14 @@ namespace canvas
setSrcCanvas(src_canvas);
}
else if( protocol == "http" || protocol == "https" )
// TODO check https
{
Canvas::getSystemAdapter()
->getHTTPClient()
->load(url)
->done(this, &Image::handleImageLoadDone);
}
else
{
setImage( Canvas::getSystemAdapter()->getImage(path) );
@@ -637,5 +656,37 @@ namespace canvas
(*_texCoords)[i + 3].set(tl.x(), br.y());
}
//----------------------------------------------------------------------------
void Image::handleImageLoadDone(HTTP::Request* req)
{
if( req->responseCode() != 200 )
{
SG_LOG( SG_GL,
SG_WARN,
"canvas::Image: failed to download '" << req->url() << "': "
<< req->responseReason() );
return;
}
std::string ext = SGPath(req->path()).extension();
SG_LOG(SG_GL, SG_INFO, "canvas::Image: received " << req->url());
osgDB::ReaderWriter* rw =
osgDB::Registry::instance()->getReaderWriterForExtension(ext);
std::istringstream img_data(
static_cast<HTTP::MemoryRequest*>(req)->responseBody()
);
osgDB::ReaderWriter::ReadResult result = rw->readImage(img_data);
if( result.success() )
setImage( result.takeImage() );
else
SG_LOG( SG_GL,
SG_WARN,
"canvas::Image: failed to read image '" << req->url() << "': "
<< result.message() );
}
} // namespace canvas
} // namespace simgear

View File

@@ -27,6 +27,7 @@
namespace simgear
{
namespace HTTP { class Request; }
namespace canvas
{
@@ -103,6 +104,8 @@ namespace canvas
void setQuad(size_t index, const SGVec2f& tl, const SGVec2f& br);
void setQuadUV(size_t index, const SGVec2f& tl, const SGVec2f& br);
void handleImageLoadDone(HTTP::Request*);
osg::ref_ptr<osg::Texture2D> _texture;
// TODO optionally forward events to canvas
CanvasWeakPtr _src_canvas;

View File

@@ -8,6 +8,7 @@
#include <simgear/structure/SGSharedPtr.hxx>
#include <simgear/math/sg_types.hxx>
#include <boost/bind.hpp>
#include <boost/function.hpp>
class SGPropertyNode;
@@ -53,6 +54,12 @@ public:
*/
Request* done(const Callback& cb);
template<class C>
Request* done(C* instance, void (C::*mem_func)(Request*))
{
return done(boost::bind(mem_func, instance, _1));
}
/**
* Set the handler to be called when the request completes or aborts with an
* error.
@@ -62,6 +69,12 @@ public:
*/
Request* fail(const Callback& cb);
template<class C>
Request* fail(C* instance, void (C::*mem_func)(Request*))
{
return fail(boost::bind(mem_func, instance, _1));
}
/**
* Set the handler to be called when the request either successfully
* completes or fails.
@@ -71,6 +84,12 @@ public:
*/
Request* always(const Callback& cb);
template<class C>
Request* always(C* instance, void (C::*mem_func)(Request*))
{
return always(boost::bind(mem_func, instance, _1));
}
/**
* Set the data for the body of the request. The request is automatically
* send using the POST method.