4

I wanted write simple program to read and edit image with boost::gil. Error occurs always with read image function. I proceed tutorials found on boost site.

#include <iostream>
#include <boost/gil/gil_all.hpp>
#include <boost/gil/extension/io/jpeg_io.hpp>
#include <boost/gil/extension/dynamic_image/any_image.hpp>
#include <boost/gil/channel.hpp>
#include <boost/mpl/vector.hpp>

int main(int argc, char *argv[])
{
    namespace bg = boost::gil;
    static const std::string resources_dir = "../resources";
    static const std::string filename = "face.jpg";
    typedef boost::mpl::vector<bg::gray8_image_t, bg::gray16_image_t, bg::rgb8_image_t, bg::rgb16_image_t> my_img_types;

    bg::any_image<my_img_types> runtime_image;
    try{
    bg::jpeg_read_image(resources_dir + filename, runtime_image);
    } catch (const std::ios_base::failure &e) {
        std::cout << e.what() << std::endl;
    }

    return 0;
}

Error is pretty long, don't know what is wrong. Seems like passing unsupported image type into template of image, but it shows regardless of the arguments - I also tried pass one type.

[ 50%] Building CXX object src/CMakeFiles/edges.dir/main.cpp.o
In file included from /usr/include/boost/config.hpp:57:0,
             from /usr/include/boost/gil/gil_config.hpp:24,
             from /usr/include/boost/gil/gil_all.hpp:25,
             from /home/mateusz/projects/edges1/src/main.cpp:2:
/usr/include/boost/gil/extension/io/jpeg_io.hpp: In instantiation of ‘const bool boost::gil::jpeg_read_support<boost::gil::any_image_view<boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >*> > >, boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >*> > >, boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >*> > >, boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >*> > >, boost::mpl::vector0<mpl_::na>, 0>, 0>, 0>, 0> > >::is_supported’:
/usr/include/boost/gil/extension/io/jpeg_io.hpp:91:5:   required from ‘void boost::gil::jpeg_read_image(const char*, Image&) [with Image = boost::gil::any_image<boost::mpl::vector<boost::gil::image<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >, false, std::allocator<unsigned char> >, boost::gil::image<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >, false, std::allocator<unsigned char> >, boost::gil::image<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >, false, std::allocator<unsigned char> >, boost::gil::image<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >, false, std::allocator<unsigned char> > > >]’
/usr/include/boost/gil/extension/io/jpeg_io.hpp:101:40:   required from ‘void boost::gil::jpeg_read_image(const string&, Image&) [with Image = boost::gil::any_image<boost::mpl::vector<boost::gil::image<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >, false, std::allocator<unsigned char> >, boost::gil::image<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >, false, std::allocator<unsigned char> >, boost::gil::image<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >, false, std::allocator<unsigned char> >, boost::gil::image<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >, false, std::allocator<unsigned char> > > >; std::string = std::basic_string<char>]’
/home/mateusz/projects/edges1/src/main.cpp:18:64:   required from here
/usr/include/boost/gil/extension/io/jpeg_io.hpp:40:5: error: invalid use of incomplete type ‘struct boost::gil::channel_type<boost::gil::any_image_view<boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >*> > >, boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >*> > >, boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >*> > >, boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >*> > >, boost::mpl::vector0<mpl_::na>, 0>, 0>, 0>, 0> > >’
     BOOST_STATIC_CONSTANT(bool,is_supported=
     ^
In file included from /usr/include/boost/gil/algorithm.hpp:25:0,
             from /usr/include/boost/gil/gil_all.hpp:27,
             from /home/mateusz/projects/edges1/src/main.cpp:2:
/usr/include/boost/gil/gil_concept.hpp:49:30: error: declaration of ‘struct boost::gil::channel_type<boost::gil::any_image_view<boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >*> > >, boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t> > >*> > >, boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<short unsigned int, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >*> > >, boost::mpl::v_item<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t> > >*> > >, boost::mpl::vector0<mpl_::na>, 0>, 0>, 0>, 0> > >’
 template <typename T> struct channel_type;

Im new also in writing CMakeLists.txt by myself, so I included these files. CMakeLists in main folder:

cmake_minimum_required(VERSION 2.8)
project(edges1)

set(CMAKE_BUILD_TYPE "Debug")
add_subdirectory(src)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})

CMakeLists.txt in src folder:

set(SOURCES main.cpp)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR}/include)

find_package(Boost REQUIRED COMPONENTS)
include_directories(${BOOST_INCLUDE_DIRS})

#link_directoires(${CMAKE_SOURCE_ROOT}/lib)
#link_directoires(${LIBRARY_OUTPUT_PATH})
add_executable(edges ${SOURCES})

using read_and_convert_image gives other error...

EDIT:

Installed libjpeg, CMakeLists in src dir:

set(SOURCES main.cpp)

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR}/include)
add_executable(edges ${SOURCES})

find_package(Boost REQUIRED COMPONENTS)
IF(BOOST_FOUND)
  target_link_libraries(edges Boost::boost)
ENDIF()
find_package(JPEG REQUIRED)
IF(JPEG_FOUND)
  include_directories(${JPEG_INCLUDE_DIR})
  target_link_libraries(edges ${JPEG_INCLUDE_DIR})
ENDIF()

cmake command:

cmake -DJPEG_LIBRARY:PATH=/usr/lib/x86_64-linux-gnu/libjpeg.so --libdir=/usr/lib64 ..

after make:

[ 50%] Linking CXX executable ../edges
CMakeFiles/edges.dir/main.cpp.o: In function `boost::gil::detail::jpeg_reader::init()':
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:89: undefined reference to `jpeg_std_error'
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:90: undefined reference to `jpeg_CreateDecompress'
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:91: undefined reference to `jpeg_stdio_src'
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:92: undefined reference to `jpeg_read_header'
CMakeFiles/edges.dir/main.cpp.o: In function `boost::gil::detail::jpeg_reader::~jpeg_reader()':
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:98: undefined reference to `jpeg_destroy_decompress'
CMakeFiles/edges.dir/main.cpp.o: In function `void boost::gil::detail::jpeg_reader::apply<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t>, boost::mpl::range_c<int, 0, 1> > >*> > > >(boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector1<boost::gil::gray_color_t>, boost::mpl::range_c<int, 0, 1> > >*> > > const&)':
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:102: undefined reference to `jpeg_start_decompress'
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:111: undefined reference to `jpeg_read_scanlines'
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:115: undefined reference to `jpeg_finish_decompress'
CMakeFiles/edges.dir/main.cpp.o: In function `void boost::gil::detail::jpeg_reader::apply<boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t>, boost::mpl::range_c<int, 0, 3> > >*> > > >(boost::gil::image_view<boost::gil::memory_based_2d_locator<boost::gil::memory_based_step_iterator<boost::gil::pixel<unsigned char, boost::gil::layout<boost::mpl::vector3<boost::gil::red_t, boost::gil::green_t, boost::gil::blue_t>, boost::mpl::range_c<int, 0, 3> > >*> > > const&)':
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:102: undefined reference to `jpeg_start_decompress'
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:111: undefined reference to `jpeg_read_scanlines'
/usr/include/boost/gil/extension/io/jpeg_io_private.hpp:115: undefined reference to `jpeg_finish_decompress'

still problem with jpeg, but including all three files from extension/io doesn't work :(

mloskot
  • 37,086
  • 11
  • 109
  • 136
Morales1235
  • 103
  • 10
  • The name of the variable holding the include dirs of Boost is case sensitive and called `Boost_INCLUDE_DIRS`. You might also want to link against `Boost::boost` for header only libraries, e.g. `target_link_libraries(edges Boost::boost)`. If doing so you can omit adding Boost to the global include directory path by deleting the line `include_directories(${Boost_INCLUDE_DIRS})`. The symbolic target `Boost::boost` carries all the necessary information. – vre Jul 02 '18 at 20:24
  • Earlier I tried without 'include_directories(${Boost_INCLUDE_DIRS})'. Now followed your proposition, the 'target_link_lib...' at the end - error still the same – Morales1235 Jul 03 '18 at 16:44
  • You are missing an include file. Adding `#include ` did the trick for me on Windows OS. – vre Jul 03 '18 at 18:34
  • Including jpeg_dynamic_io and private_io still makes error, but slight different, what conduced me to find I probably should install and link libjpeg. Edited the main post. – Morales1235 Jul 03 '18 at 20:02
  • You need to link against JPEG library, instead you are referencing the include files in the `target_link_libraries` call. My minimalistic CMakeLists.txt to test looks like this `find_package(JPEG REQUIRED) find_package(Boost REQUIRED) add_executable(edges ${SOURCES}) target_include_directories(edges PUBLIC ${JPEG_INCLUDE_DIR}) target_link_libraries(edges Boost::boost ${JPEG_LIBRARY})` And on the command line I was calling cmake from the build dir as follows: `cmake -G "Visual Studio 14 2015" -DBOOST_ROOT=D:\boost\vc14\boost_1_66_0 -DJPEG_INCLUDE_DIR=C:\Temp\boostgil\jpeg-9c ..` – vre Jul 03 '18 at 20:59

2 Answers2

2

You are missing includes

#include <boost/gil/extension/io/dynamic_io.hpp>
#include <boost/gil/extension/io/jpeg_dynamic_io.hpp>

Then it compiles and links:

g++ -Wall -Wextra -pedantic -pthread -o sotest test.cpp -ljpeg
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks! Both your and @vre answers was obligatory. Including jpeg_private_io was not nessecary, but i needed dynamic_io. And cmake works without setting those macros, just wrong way CMakeLists.txt was written. – Morales1235 Jul 05 '18 at 17:10
1

The answer provided by @sehe is perfectly correct for GIL released in Boost 1.67 or earlier.

Since, the I/O extensions have been entirely rewritten in Boost.GIL released in Boost 1.68, your example will need adjustments. Here it is updated, a minimal version:

#include <boost/gil.hpp>
#include <boost/gil/extension/dynamic_image/any_image.hpp>
#include <boost/gil/extension/io/jpeg.hpp>
#include <boost/mpl/vector.hpp>

int main()
{
    namespace bg = boost::gil;
    using my_img_types = boost::mpl::vector<bg::gray8_image_t, bg::gray16_image_t, bg::rgb8_image_t, bg::rgb16_image_t>;
    bg::any_image<my_img_types> runtime_image;
    bg::read_image("file.jpg", runtime_image, bg::jpeg_tag());
}

It may also be worth noting that latest Boost.GIL now requires a C++11-compliant compiler.

UPDATE: Boost 1.72 delivers GIL ported from Boost.MPL to Boost.MP11, see release notes, so mp_list should be used instead of mpl::vector.

mloskot
  • 37,086
  • 11
  • 109
  • 136