VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
grimage.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2017 Graeme Walker
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program 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
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // grimage.cpp
19 //
20 
21 #include "gdef.h"
22 #include "grdef.h"
23 #include "grimage.h"
24 #include "grpnm.h"
25 #include "glimits.h"
26 #include "ghexdump.h"
27 #include "gdebug.h"
28 
29 namespace
30 {
31  size_t size_of( shared_ptr<const Gr::ImageBuffer> ptr )
32  {
33  return ptr.get() == nullptr ? 0U : Gr::imagebuffer::size_of(*ptr) ;
34  }
35 }
36 
38 {
39 }
40 
41 Gr::Image::Image( shared_ptr<const ImageBuffer> ptr , ImageType type ) :
42  m_ptr(ptr) ,
43  m_type(type)
44 {
45  if( type.isRaw() && size_of(ptr) != type.size() )
46  {
47  G_ASSERT( !"invalid raw image buffer size" ) ;
48  type = ImageType() ;
49  }
50  if( ptr.get() == nullptr )
51  type = ImageType() ;
52 }
53 
54 Gr::ImageBuffer * Gr::Image::blank( Image & image , ImageType type , bool contiguous )
55 {
56  G_ASSERT( type.isRaw() ) ;
57  if( !type.isRaw() )
58  throw std::runtime_error( "invalid type for blank image" ) ;
59 
60  shared_ptr<ImageBuffer> ptr = image.recycle() ;
61 
62  if( contiguous )
63  {
64  ptr->resize( 1U ) ;
65  ptr->at(0).resize( type.size() ) ;
66  }
67  else
68  {
69  size_t rowsize = type.rowsize() ;
70  const int dy = type.dy() ;
71  ptr->resize( dy ) ;
72  for( int y = 0 ; y < dy ; y++ )
73  ptr->at(y).resize( rowsize ) ;
74  }
75 
76  image = Image( ptr , type ) ;
77  return ptr.get() ;
78 }
79 
80 bool Gr::Image::valid() const
81 {
82  return !empty() && m_type.valid() ;
83 }
84 
86 {
87  return m_type ;
88 }
89 
90 bool Gr::Image::empty() const
91 {
92  return m_ptr.get() == nullptr ;
93 }
94 
96 {
97  m_ptr.reset() ;
98  m_type = ImageType() ;
99 }
100 
101 size_t Gr::Image::size() const
102 {
103  if( empty() ) return 0U ;
104  return size_of(m_ptr) ;
105 }
106 
107 shared_ptr<const Gr::ImageBuffer> Gr::Image::ptr() const
108 {
109  return m_ptr ;
110 }
111 
113 {
114  return *m_ptr ;
115 }
116 
117 shared_ptr<Gr::ImageBuffer> Gr::Image::recycle()
118 {
119  if( m_ptr.get() != nullptr && m_ptr.unique() )
120  return const_pointer_cast<ImageBuffer>(m_ptr) ;
121  else
122  return shared_ptr<ImageBuffer>( new ImageBuffer ) ;
123 }
124 
125 void Gr::Image::read( std::istream & in , Image & image , const std::string & help_text )
126 {
127  if( !in.good() )
128  throw ReadError( help_text ) ;
129 
130  ImageType image_type_in( in ) ;
131  G_DEBUG( "Gr::Image::read: type=[" << image_type_in << "]" ) ;
132 
133  shared_ptr<ImageBuffer> ptr = image.recycle() ;
134 
135  if( image_type_in.isPnm() ) // read pnm files as raw
136  {
137  ImageBuffer & image_buffer = *ptr ;
138  imagebuffer::resize( image_buffer , image_type_in.dx() , image_type_in.dy() , image_type_in.channels() ) ;
139  ImageData image_data( image_buffer , image_type_in.dx() , image_type_in.dy() , image_type_in.channels() ) ;
140  PnmReader reader ;
141  reader.decode( image_data , in ) ;
142  image_type_in = ImageType::raw( image_type_in.dx() , image_type_in.dy() , image_type_in.channels() ) ;
143  }
144  else
145  {
146  // raw files cannot be stored on disk because the the image size is
147  // not intrinsic to the format, so treat the file as jpeg or png
148  in >> *ptr ;
149  if( in.fail() )
150  throw ReadError( help_text ) ;
151  }
152  image = Image( ptr , image_type_in ) ;
153 }
154 
155 bool Gr::Image::receive( G::PublisherSubscription & channel , Image & image , std::string & type_str )
156 {
157  return receiveImp( false , channel , image , type_str ) ;
158 }
159 
160 bool Gr::Image::peek( G::PublisherSubscription & channel , Image & image , std::string & type_str )
161 {
162  return receiveImp( true , channel , image , type_str ) ;
163 }
164 
165 bool Gr::Image::receiveImp( bool peek , G::PublisherSubscription & channel , Image & image , std::string & type_str )
166 {
167  shared_ptr<ImageBuffer> ptr = image.recycle() ;
168  ptr->resize( 1U ) ;
169  std::vector<char> & buffer = ptr->at(0) ;
170 
171  bool ok = peek ? channel.peek(buffer,&type_str) : channel.receive(buffer,&type_str) ;
172  if( !ok )
173  return false ;
174 
175  ImageType image_type( type_str ) ;
176  image = Image( ptr , image_type ) ; // even if !image_type.valid()
177 
178  return true ;
179 }
180 
181 /// \file grimage.cpp
bool isRaw() const
Returns true if a raw image type.
bool receive(std::vector< char > &buffer, std::string *type_p=nullptr, G::EpochTime *time_p=nullptr)
Does a read for new publish()ed data.
Definition: gpublisher.cpp:459
shared_ptr< const ImageBuffer > ptr() const
Returns the image data shared pointer.
Definition: grimage.cpp:107
A holder for image data, having eight bits per sample and one or three channels.
Definition: grimagedata.h:46
size_t size() const
Returns the image data total size.
Definition: grimage.cpp:101
int channels() const
Returns the number of channels.
Definition: grimagetype.h:197
Synopsis:
static bool receive(G::PublisherSubscription &channel, Image &, std::string &type_str)
Reads a publication channel into an image.
Definition: grimage.cpp:155
void clear()
Clears the image as if default constructed.
Definition: grimage.cpp:95
An encapsulation of image type, including width, height and number of channels, with support for a st...
Definition: grimagetype.h:43
Vectors ImageBuffer
An ImageBuffer is used to hold raw image data, typically in more than one chunk.
Definition: grimagebuffer.h:47
An easy-to-use combination of a G::PublisherChannel object and a single G::PublisherSubscriber.
Definition: gpublisher.h:229
bool peek(std::vector< char > &buffer, std::string *type_p=nullptr, G::EpochTime *time_p=nullptr)
Does a receive() but without requiring a publication event.
Definition: gpublisher.cpp:464
static ImageType raw(int dx, int dy, int channels)
Factory function for a raw image type.
bool empty() const
Returns true if constructed with no image data.
Definition: grimage.cpp:90
A class holding shared read-only image data (Gr::ImageBuffer) and its associated image type (Gr::Imag...
Definition: grimage.h:41
size_t size() const
Returns the product of dx, dy and channels.
static void read(std::istream &, Image &, const std::string &exception_help_text=std::string())
Reads an input stream into an image. Throws on error.
Definition: grimage.cpp:125
static ImageBuffer * blank(Image &, ImageType raw_type, bool contiguous=false)
Factory function for a not-really-blank raw image that is temporarily writable via the returned image...
Definition: grimage.cpp:54
int dy() const
Returns the image height.
Definition: grimagetype.h:191
void decode(ImageData &out, const G::Path &in)
Decodes a pnm file into an image. Throws on error.
Definition: grpnm.cpp:383
bool valid() const
Returns !empty() && type().valid().
Definition: grimage.cpp:80
size_t rowsize() const
Returns the product of dx and channels.
ImageType type() const
Returns the image type.
Definition: grimage.cpp:85
const ImageBuffer & data() const
Returns the image data.
Definition: grimage.cpp:112
int dx() const
Returns the image width.
Definition: grimagetype.h:185
shared_ptr< ImageBuffer > recycle()
Creates a new shared pointer that can be deposited into a new Image, but if the current Image is not ...
Definition: grimage.cpp:117
A static interface for reading portable-anymap (pnm) files.
Definition: grpnm.h:110
Image()
Default constructor for an empty() image with an in-valid() type() and a null ptr().
Definition: grimage.cpp:37
static bool peek(G::PublisherSubscription &channel, Image &, std::string &type_str)
A variant on receive() that does a channel peek().
Definition: grimage.cpp:160
bool isPnm() const
Returns true if a pnm image type.