$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
pdf/load.hh
1 // Copyright (C) 2013 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_IO_PDF_LOAD_HH
27 # define MLN_IO_PDF_LOAD_HH
28 
32 
33 #include <iostream>
34 #include <mln/core/image/image2d.hh>
35 #include <poppler/cpp/poppler-document.h>
36 #include <poppler/cpp/poppler-page-renderer.h>
37 
38 
39 namespace mln
40 {
41 
42  namespace io
43  {
44 
45  namespace pdf
46  {
47 
58  template <typename I>
59  void load(util::array<I>& arr, const std::string& filename,
60  float dpi);
61 
77  template <typename I>
78  void load(util::array<I>& arr, const std::string& filename,
79  int first_page, int last_page, float dpi);
80 
81 
96  template <typename I>
97  void load(util::array<I>& arr, const std::string& filename,
98  util::array<int> pages, float dpi);
99 
114  template <typename I>
115  void load(Image<I>& ima, const std::string& filename,
116  int page, float dpi);
117 
118 
131  template <typename I>
132  void load(util::array<I>& arr, const std::string& filename);
133 
148  template <typename I>
149  void load(util::array<I>& arr, const std::string& filename,
150  util::array<int> pages);
151 
152 
153 # ifndef MLN_INCLUDE_ONLY
154 
155  namespace internal
156  {
157 
158  template <typename I>
159  void copy_data_argb32(I& ima, const poppler::image& pima)
160  {
161  mln_value(I) *vima = &ima(ima.domain().pmin());
162  const unsigned char *
163  nsites = (unsigned char *)pima.const_data()
164  + pima.width() * pima.height() * 4;
165 
166  unsigned next = 4;
167  for (const unsigned char *v = (unsigned char *)pima.const_data();
168  v < nsites; v += next, ++vima)
169  {
170  vima->red() = *(v + 2);
171  vima->green() = *(v + 1);
172  vima->blue() = *v;
173  }
174  }
175 
176  template <typename I>
177  void copy_data_rgb24(I& ima, const poppler::image& pima)
178  {
179  mln_value(I) *vima = &ima(ima.domain().pmin());
180  const unsigned char *
181  nsites = (unsigned char *)pima.const_data()
182  + pima.width() * pima.height() * 3;
183 
184  unsigned next = 3;
185  for (const unsigned char *v = (unsigned char *)pima.const_data();
186  v < nsites; v += next, ++vima)
187  {
188  vima->red() = *v;
189  vima->green() = *(v + 1);
190  vima->blue() = *(v + 2);
191  }
192  }
193 
194 
195  template <typename I>
196  void copy_data(I& ima, const poppler::image& pima)
197  {
198  mln_precondition(ima.is_valid());
199 
200  switch(pima.format())
201  {
202  case poppler::image::format_invalid:
203  case poppler::image::format_mono:
204  std::cerr << "Loading black and white pdf is not implemented!";
205  abort();
206  break;
207  case poppler::image::format_rgb24:
208  copy_data_rgb24(ima, pima);
209  break;
210  case poppler::image::format_argb32:
211  copy_data_argb32(ima, pima);
212  break;
213  }
214  }
215 
216 
217  template <typename I>
218  void extract_page(const poppler::document* pdf, int i,
219  util::array<I>& arr, float dpi)
220  {
221  // Read page
222  poppler::page* p = pdf->create_page(i);
223 
224  // Render Page
225  poppler::page_renderer pr;
226  if (! pr.can_render())
227  {
228  std::cerr << "PDF cannot be rendered! Make sure libpoppler is "
229  << "compiled with a render backend." << std::endl;
230  abort();
231  }
232  poppler::image pima = pr.render_page(p, dpi, dpi);
233 
234  // Prepare MLN image.
235  I ima(make::box2d(pima.height(), pima.width()), 0);
236  mln_assertion(ima.is_valid());
237 
238  // Copy data
239  internal::copy_data(ima, pima);
240 
241  // Append result
242  arr.append(ima);
243  }
244 
245  } // end of namespace mln::io::pdf::internal
246 
247 
248  template <typename I>
249  void load(util::array<I>& arr, const std::string& filename, float dpi)
250  {
251  mln_trace("mln::io::pdf::load");
252 
253  // Load document
254  poppler::document *pdf = poppler::document::load_from_file(filename);
255  if (pdf == 0)
256  {
257  std::cerr << "Error: Cannot load pdf " << filename << std::endl;
258  abort();
259  }
260 
261  for (int i = 0; i < pdf->pages(); ++i)
262  internal::extract_page(pdf, i, arr, dpi);
263 
264  delete pdf;
265 
266  }
267 
268  template <typename I>
269  void load(util::array<I>& arr, const std::string& filename,
270  int first_page, int last_page, float dpi)
271  {
272  mln_trace("mln::io::pdf::load");
273 
274  // Load document
275  poppler::document *pdf = poppler::document::load_from_file(filename);
276  if (pdf == 0)
277  {
278  std::cerr << "Error: Cannot load PDF " << filename << std::endl;
279  abort();
280  }
281 
282  if (first_page < 0 || first_page > (pdf->pages() - 1)
283  || last_page < 0 || last_page > (pdf->pages() - 1))
284  {
285  std::cerr << "Error while loading PDF: page range is not correct!"
286  << std::endl;
287  abort();
288  }
289 
290  for (int i = first_page; i <= last_page; ++i)
291  internal::extract_page(pdf, i, arr, dpi);
292 
293  delete pdf;
294 
295  }
296 
297 
298  template <typename I>
299  void load(util::array<I>& arr, const std::string& filename,
300  util::array<int> pages, float dpi)
301  {
302  mln_trace("mln::io::pdf::load");
303 
304  // Load document
305  poppler::document *pdf = poppler::document::load_from_file(filename);
306  if (pdf == 0)
307  {
308  std::cerr << "Error: Cannot load PDF " << filename << std::endl;
309  abort();
310  }
311 
312  for (unsigned i = 0; i < pages.size(); ++i)
313  {
314  if (pages[i] < 0 || pages[i] > pdf->pages() - 1)
315  {
316  std::cerr << "Error while loading PDF: selected page "
317  << pages[i] << " does not exist!" << std::endl;
318  abort();
319  }
320 
321  internal::extract_page(pdf, pages[i], arr, dpi);
322  }
323 
324  delete pdf;
325 
326  }
327 
328 
329  template <typename I>
330  void load(Image<I>& ima, const std::string& filename,
331  int page, float dpi)
332  {
333  util::array<I> arr;
334  load(arr, filename, page, page, dpi);
335  mln_assertion(arr.size() == 1);
336  exact(ima) = arr[0];
337  }
338 
339  template <typename I>
340  void load(util::array<I>& arr, const std::string& filename)
341  {
342  load(arr, filename, 300);
343  }
344 
345 
346  template <typename I>
347  void load(util::array<I>& arr, const std::string& filename,
348  util::array<int> pages)
349  {
350  load(arr, filename, pages, 300);
351  }
352 
353 
354 # endif // ! MLN_INCLUDE_ONLY
355 
356  } // end of namespace mln::io::pdf
357 
358  } // end of namespace mln::io
359 
360 } // end of namespace mln
361 
362 
363 #endif // ! MLN_IO_PDF_LOAD_HH