Boost.Asio で Web から画像を読み込んでくる
Boost.Asio を使用して、HTTP 通信で、画像の読み込みを行います。
ついでに読み込んだデータを OGLplus で描画とかしてみます。
[ソース]
#include <vector> #include <GL/glew.h> #include <oglplus/gl.hpp> // OGLplus 0.5.0 以降だと near far を undef しておかないと動かない #undef near #undef far // #include <oglplus/all.hpp> #include <oglplus/context.hpp> #include <oglplus/buffer.hpp> #include <oglplus/vertex_attrib.hpp> #include <oglplus/vertex_array.hpp> #include <oglplus/shader.hpp> #include <oglplus/program.hpp> #include <oglplus/pixel_data.hpp> #include <oglplus/texture.hpp> #include <oglplus/image.hpp> #include <oglplus/images/load.hpp> #include <oglplus/shapes/draw.hpp> #include <GL/Glut.h> #define BOOST_DATE_TIME_NO_LIB #define BOOST_REGEX_NO_LIB #define BOOST_ERROR_CODE_HEADER_ONLY #define BOOST_SYSTEM_NO_LIB #include <boost/asio.hpp> #include <gl/graphics.hpp> #include <fstream> #include <sstream> namespace glp = oglplus; typedef glp::Context glc; template<typename Stream> Stream& load_image( Stream& s, std::string const& path, std::string const& host ){ if(!s){ std::cout << "Unable to connect" << std::endl; abort(); } s << "GET " << path << " HTTP/1.0\r\n"; s << "Host: "<< host << "\r\n"; s << "\r\n"; s << std::flush; // バッファに溜めずに確実にネットワーク送信 // 受信 std::string line; while(std::getline(s, line) && !line.empty() && line != "\r"){ std::cout << line << std::endl; } return s; } struct texture : boost::noncopyable{ texture(){ vs.Source(R"delimiter( #version 330 in vec4 Position; in vec2 TexCoord; out vec2 vertTexCoord; void main(void){ vertTexCoord = TexCoord; gl_Position = Position; } )delimiter"); vs.Compile(); fs.Source(R"delimiter( #version 330 uniform sampler2D TexUnit; in vec2 vertTexCoord; out vec4 fragColor; void main(void){ fragColor = texture(TexUnit, vertTexCoord); vec4 t = texture(TexUnit, vertTexCoord); fragColor = vec4(t.rgb, 1.0); } )delimiter"); fs.Compile(); // attach the shaders to the program prog.AttachShader(vs); prog.AttachShader(fs); // link and use it prog.Link(); prog.Use(); // bind the VAO for the texture vertex_array.Bind(); // bind the VBO for the texture vertices verts.Bind(glp::Buffer::Target::Array); { GLfloat data[12] = { 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f }; // upload the data glp::Buffer::Data(glp::Buffer::Target::Array, 12, data ); // setup the vertex attribs array for the vertices glp::VertexAttribArray vert_attr(prog, "Position"); vert_attr.Setup(2, glp::DataType::Float); vert_attr.Enable(); } texcoords.Bind(glp::Buffer::Target::Array); { GLfloat data[12] = { 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f }; // upload the data glp::Buffer::Data(glp::Buffer::Target::Array, 12, data ); glp::VertexAttribArray attr(prog, "TexCoord"); attr.Setup(2, glp::DataType::Float); attr.Enable(); } // setup the texture tex.Bind(glp::Texture::Target::_2D); { tex.MinFilter(glp::Texture::Target::_2D, glp::TextureMinFilter::Linear); tex.MagFilter(glp::Texture::Target::_2D, glp::TextureMagFilter::Linear); tex.WrapS(glp::Texture::Target::_2D, glp::TextureWrap::Repeat); tex.WrapT(glp::Texture::Target::_2D, glp::TextureWrap::Repeat); namespace ip = boost::asio::ip; // web から画像を読み込んでくる // @manga_osyo のアイコン ip::tcp::iostream s( "a2.twimg.com", "http" ); if(!s){ std::cout << "Unable to connect" << std::endl; abort(); } std::string const path = "/profile_images/1662110818/bambi.PNG"; std::string const host = "a2.twimg.com"; tex.Image2D( glp::Texture::Target::_2D, glp::images::PNG(load_image( s, path, host )) ); } } void render() const{ vertex_array.Bind(); glc::DrawArrays(glp::PrimitiveType::Triangles, 0, 6); } private: glp::VertexShader vs; glp::FragmentShader fs; glp::Program prog; glp::VertexArray vertex_array; glp::Buffer verts; glp::Buffer texcoords; glp::Texture tex; }; int main(int argc, char *argv[]) try{ namespace glp = oglplus; typedef glp::Context glc; gl::graphics g(argc, argv, 500, 500, "test"); // glew の初期化 auto err = glewInit(); if (err != GLEW_OK) { fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); } glc::ClearColor(0.5f, 0.7f, 0.9f, 1.0f); glc::ClearDepth(1.0f); // テクスチャポリゴンの生成 texture tex; gl::displayfunc(g, [&](){ glc::Clear().ColorBuffer().DepthBuffer(); tex.render(); }); gl::reshapefunc(g, [&](int width, int height){ glc::Viewport(width, height); }); // キー入力イベント gl::keyboardfunc(g, [&tex](unsigned char key, int x, int y){ if(key == 'q') return exit(0); }); g.run(); return 0; } catch(glp::Error const& error){ std::cout << error.what() << std::endl; std::cout << "GLSymbol " << error.GLSymbol () << std::endl; std::cout << "File " << error.File () << std::endl; std::cout << "Func " << error.Func () << std::endl; std::cout << "Line " << error.Line () << std::endl; std::cout << "ClassName " << error.ClassName () << std::endl; std::cout << "ObjectDescription " << error.ObjectDescription () << std::endl; }
[出力]
HTTP/1.1 200 OK x-amz-id-2: Wa09wGDzkwFuok1YsW693owl0hz7lumLYccbjNqFFYKWQnbpxlb1BZh+9+BY+bu+ x-amz-request-id: 6251203F97195E3D Date: Mon, 28 Nov 2011 08:18:39 GMT Last-Modified: Mon, 28 Nov 2011 08:04:41 GMT ETag: "43078357c49e2a0719d4be75c028e01b" Accept-Ranges: bytes Content-Type: image/png Content-Length: 364906 Server: AmazonS3 Cache-Control: private, max-age=604800 Age: 0 Expires: Mon, 05 Dec 2011 08:18:39 GMT Connection: close
思ったよりも簡単に出来たので満足。
[boost]
- ver 1.48.0