34 template <
typename T> T append_c( T p , T p_end ,
char c )
36 if( p != p_end ) *p++ = c ;
39 template <
typename T> T append_s( T p , T p_end ,
const char * s )
42 p = append_c( p , p_end , *s ) ;
45 template <
typename T> T append_n( T p_in , T p_end ,
int n )
47 n = std::max( 0 , n ) ;
49 for( ; p != p_end && n > 0 ; n /= 10 )
50 *p++ = static_cast<char>(
'0'+(n%10)) ;
51 std::reverse( p_in , p ) ;
55 T append_size( T p , T p_end ,
int dx ,
int dy ,
int channels )
57 p = append_s( p , p_end ,
";xsize=" ) ;
58 p = append_n( p , p_end , dx ) ;
59 p = append_c( p , p_end ,
'x' ) ;
60 p = append_n( p , p_end , dy ) ;
61 p = append_c( p , p_end ,
'x' ) ;
62 p = append_n( p , p_end , channels ) ;
63 append_c( p , p_end ,
'\0' ) ;
66 int atoi(
const std::string & s ,
size_t p ,
size_t n )
69 for(
size_t i = 0U ; i < n ; i++ , p++ )
71 if( s.at(p) <
'0' || s.at(p) >
'9' )
break ;
73 result +=
static_cast<int>(s.at(p)-
'0') ;
116 init( reinterpret_cast<const unsigned char *>(&buffer[0]) , buffer.size() ) ;
128 imagebuf inbuf( buffer ) ;
129 std::istream instream( &inbuf ) ;
141 init( reinterpret_cast<const unsigned char *>(p) , n ) ;
163 int default_channels = 3 ;
164 if( type_str.find(
"image/x.raw") == 0U )
167 default_channels = 0 ;
169 else if( type_str.find(
"image/jpeg") == 0U )
173 else if( type_str.find(
"image/png") == 0U )
177 else if( type_str.find(
"image/x-portable-anymap") == 0U )
182 if( m_type != t_invalid )
184 typedef std::string::size_type pos_t ;
185 const pos_t npos = std::string::npos ;
188 pos_t p0 = type_str.find(
';') ;
189 pos_t p1 = p0 == npos ? npos : type_str.find(
"xsize=",p0+1) ;
190 if( p1 != npos ) p1 += 5U ;
191 pos_t p2 = p1 == npos ? npos : type_str.find_first_of(
",_x",p1+1U) ;
192 pos_t p3 = p2 == npos ? npos : type_str.find_first_of(
",_x",p2+1U) ;
196 m_channels = default_channels ;
198 if( p1 != npos && p2 != npos )
199 m_dx = atoi( type_str , p1+1U , p2-p1-1U ) ;
201 if( m_dx && p2 != npos && p3 != npos )
202 m_dy = atoi( type_str , p2+1U , p3-p2-1U ) ;
204 if( m_dy && p3 != npos && p3 < type_str.size() )
205 m_channels = atoi( type_str , p3+1U , type_str.size()-p3-1U ) ;
216 return std::string( s.s ) ;
223 return 0 == std::strcmp( s.c_str() , other.c_str() ) ;
236 append_size( out.s+std::strlen(out.s) , out.s+
sizeof(out.s)-1U , m_dx , m_dy , m_channels ) ;
237 out.s[
sizeof(out.s)-1U] =
'\0' ;
241 void Gr::ImageType::setsimple( String & out )
const
243 G_ASSERT(
sizeof(out.s) > 30U ) ;
245 if( m_type == t_jpeg ) std::strcpy( out.s ,
"image/jpeg" ) ;
246 else if( m_type == t_png ) std::strcpy( out.s ,
"image/png" ) ;
247 else if( m_type == t_raw ) std::strcpy( out.s ,
"image/x.raw" ) ;
248 else if( m_type == t_pnm ) std::strcpy( out.s ,
"image/x-portable-anymap" ) ;
255 return std::string( s.s ) ;
261 return m_type != t_invalid && m_dx > 0 && m_dy > 0 && (m_channels==1||m_channels==3) ;
266 return m_type == t_raw ;
271 return m_type == t_jpeg ;
276 return m_type == t_png ;
281 return m_type == t_pnm ;
286 return sizet( m_dx , m_dy , m_channels ) ;
291 G_ASSERT( isRaw() ) ;
292 return sizet( m_dx , 1 , m_channels ) ;
297 return m_type == other.m_type && m_dx == other.m_dx && m_dy == other.m_dy && m_channels == other.m_channels ;
302 return !( (*this) == other ) ;
307 if( m_type != other.m_type )
return int(m_type) < int(other.m_type) ;
308 if( m_dx != other.m_dx )
return m_dx < other.m_dx ;
309 if( m_dy != other.m_dy )
return m_dy < other.m_dy ;
310 return m_channels < other.m_channels ;
315 return ImageType( t_jpeg , dx , dy , channels ) ;
320 return jpeg( scaled(type_in.
dx(),scale) , scaled(type_in.
dy(),scale) , monochrome?1:type_in.
channels() ) ;
325 return ImageType( t_raw , dx , dy , channels ) ;
330 return raw( scaled(type_in.
dx(),scale) , scaled(type_in.
dy(),scale) , monochrome?1:type_in.
channels() ) ;
335 return ImageType( t_png , dx , dy , channels ) ;
340 return png( scaled(type_in.
dx(),scale) , scaled(type_in.
dy(),scale) , monochrome?1:type_in.
channels() ) ;
343 void Gr::ImageType::init( ImageType::Type t ,
int dx ,
int dy ,
int channels )
348 m_channels = channels ;
351 void Gr::ImageType::init( std::istream & stream )
353 std::streampos pos = stream.tellg() ;
355 unsigned char buffer[6] = { 0 , 0 , 0 , 0 , 0 , 0 } ;
356 stream.read( reinterpret_cast<char*>(&buffer[0]) ,
sizeof(buffer) ) ;
357 size_t n =
static_cast<size_t>(stream.gcount()) ;
359 stream.seekg( pos , std::ios_base::beg ) ;
360 if( pos == -1 || stream.tellg() != pos )
361 throw std::runtime_error(
"stream not seekable" ) ;
363 Type t = typeFromSignature( buffer , n ) ;
366 JpegInfo info( stream ) ;
368 init( t_jpeg , info.dx() , info.dy() , info.channels() ) ;
370 else if( t == t_png )
372 PngInfo info( stream ) ;
374 init( t_png , info.dx() , info.dy() , 3 ) ;
376 else if( t == t_pnm )
378 PnmInfo info( stream ) ;
380 init( t_pnm , info.dx() , info.dy() , info.channels() ) ;
383 stream.seekg( pos , std::ios_base::beg ) ;
384 if( pos == -1 || stream.tellg() != pos )
385 throw std::runtime_error(
"stream not seekable" ) ;
388 void Gr::ImageType::init(
const unsigned char * p ,
size_t n )
390 Type t = typeFromSignature( p , n ) ;
393 JpegInfo info( p , n ) ;
395 init( t_jpeg , info.dx() , info.dy() , info.channels() ) ;
397 else if( t == t_png )
399 PngInfo info( p , n ) ;
401 init( t_png , info.dx() , info.dy() , 3 ) ;
403 else if( t == t_pnm )
405 PnmInfo info( p , n ) ;
407 init( t_pnm , info.dx() , info.dy() , info.channels() ) ;
411 Gr::ImageType::Type Gr::ImageType::typeFromSignature(
const unsigned char * p ,
size_t n )
414 p[0] == 0xff && p[1] == 0xd8 &&
420 p[0] == 0x89 && p[1] ==
'P' && p[2] ==
'N' && p[3] ==
'G' )
424 else if( n > 4U && p[0] ==
'P' &&
426 ( p[1] ==
'1' || p[1] ==
'2' || p[1] ==
'3' || p[1] ==
'4' || p[1] ==
'5' || p[1] ==
'6' ) &&
427 ( p[2] ==
' ' || p[2] ==
'\n' || p[2] ==
'\r' ) )
bool isRaw() const
Returns true if a raw image type.
A traits class that can be specialised for Gr::ImageBuffer candidates.
bool isJpeg() const
Returns true if a jpeg image type.
bool operator<(const ImageType &) const
Comparison operator.
int channels() const
Returns the number of channels.
static ImageType jpeg(int dx, int dy, int channels=3)
Factory function for a jpeg image type.
An encapsulation of image type, including width, height and number of channels, with support for a st...
Vectors ImageBuffer
An ImageBuffer is used to hold raw image data, typically in more than one chunk.
String & set(String &out) const
Returns str() by reference.
static ImageType raw(int dx, int dy, int channels)
Factory function for a raw image type.
std::string str() const
Returns the image type string (including the size parameter).
size_t size() const
Returns the product of dx, dy and channels.
bool valid() const
Returns true if valid.
bool isPng() const
Returns true if a png image type.
int dy() const
Returns the image height.
void streamOut(std::ostream &) const
Used by op<<().
size_t rowsize() const
Returns the product of dx and channels.
bool matches(const std::string &str) const
Returns true if this type matches the given type (including size decorations).
int dx() const
Returns the image width.
std::string simple() const
Returns the basic image type string, excluding the size parameter.
bool operator!=(const ImageType &) const
Comparison operator.
ImageType()
Default constructor for an in-valid() image type with dimensions of zero.
A small-string class used for stringised Gr::ImageType instances.
bool operator==(const ImageType &) const
Comparison operator.
bool isPnm() const
Returns true if a pnm image type.
static ImageType png(int dx, int dy, int channels=3)
Factory function for a png image type.