VideoTools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
grjpeg.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 // grjpeg.cpp
19 //
20 
21 #include "gdef.h"
22 #include "grjpeg.h"
23 #include "glog.h"
24 #include <stdexcept>
25 #include <istream>
26 
27 namespace {
28 
29 struct StreamAdaptor
30 {
31  explicit StreamAdaptor( std::istream & stream_in ) :
32  m_s(stream_in) ,
33  m_pos0(stream_in.tellg())
34  {
35  }
36  void skip( unsigned int n )
37  {
38  m_s.seekg( n , std::ios_base::cur ) ;
39  }
40  bool good() const
41  {
42  return m_s.good() ;
43  }
44  unsigned int get()
45  {
46  if( !good() ) return 0U ;
47  return static_cast<unsigned int>(m_s.get()) ;
48  }
49  unsigned int peek()
50  {
51  if( !good() ) return 0U ;
52  return static_cast<unsigned int>(m_s.peek()) ;
53  }
54  size_t offset() const
55  {
56  return m_s.tellg() - m_pos0 ;
57  }
58  std::istream & m_s ;
59  std::streampos m_pos0 ;
60 } ;
61 
62 struct DataStream
63 {
64  DataStream( const unsigned char * p , size_t n ) :
65  m_begin(p) ,
66  m_p(p) ,
67  m_end(p+n)
68  {
69  }
70  void skip( unsigned int n )
71  {
72  m_p += n ;
73  }
74  bool good() const
75  {
76  return m_p < m_end ;
77  }
78  unsigned int get()
79  {
80  if( m_p >= m_end ) return 0U ;
81  return *m_p++ ;
82  }
83  unsigned int peek()
84  {
85  if( m_p >= m_end ) return 0U ;
86  return *m_p ;
87  }
88  size_t offset() const
89  {
90  return m_p - m_begin ;
91  }
92  const unsigned char * m_begin ;
93  const unsigned char * m_p ;
94  const unsigned char * m_end ;
95 } ;
96 
97 template <typename T>
98 unsigned int get2( T & in )
99 {
100  unsigned int hi = in.get() ;
101  unsigned int lo = in.get() ;
102  return (hi<<8) + lo ;
103 }
104 
105 template <typename T>
106 void read( T & in , int & dx , int & dy , int & channels )
107 {
108  dx = 0 ;
109  dy = 0 ;
110  channels = 0 ;
111 
112  const unsigned int sof0 = 0xC0 ;
113  const unsigned int sof1 = 0xC1 ;
114  const unsigned int sof2 = 0xC2 ;
115  const unsigned int sof9 = 0xC9 ;
116  const unsigned int sof10 = 0xCA ;
117 
118  while( in.good() )
119  {
120  if( in.get() != 0xff ) break ;
121  unsigned int type = in.get() ;
122  unsigned int length = in.peek() == 0xff ? 0 : get2(in) ;
123  if( type == sof0 || type == sof1 || type == sof2 || type == sof9 || type == sof10 )
124  {
125  in.get() ; // precision
126  unsigned int height = get2(in) ;
127  unsigned int width = get2(in) ;
128  unsigned int components = in.get() ;
129  dx = static_cast<int>( width ) ;
130  dy = static_cast<int>( height ) ;
131  channels = static_cast<int>( components ) ;
132  break ;
133  }
134  if( length > 2U )
135  {
136  in.skip( length-2U ) ;
137  if( !in.good() )
138  G_DEBUG( "gjpeg::read: no sof chunk: offset=" << in.offset() << " skip=" << length ) ;
139  }
140  }
141 }
142 
143 }
144 
145 Gr::JpegInfo::JpegInfo( std::istream & stream_in )
146 {
147  StreamAdaptor s( stream_in ) ;
148  read( s , m_dx , m_dy , m_channels ) ;
149 }
150 
151 Gr::JpegInfo::JpegInfo( const unsigned char * p , size_t n )
152 {
153  DataStream s( p , n ) ;
154  read( s , m_dx , m_dy , m_channels ) ;
155 }
156 
157 Gr::JpegInfo::JpegInfo( const char * p , size_t n )
158 {
159  DataStream s( reinterpret_cast<const unsigned char *>(p) , n ) ;
160  read( s , m_dx , m_dy , m_channels ) ;
161 }
162 
164 {
165  return m_dx > 0 && m_dy > 0 && m_channels > 0 ;
166 }
167 
168 int Gr::JpegInfo::dx() const
169 {
170  return valid() ? m_dx : 0 ;
171 }
172 
173 int Gr::JpegInfo::dy() const
174 {
175  return valid() ? m_dy : 0 ;
176 }
177 
179 {
180  return valid() ? m_channels : 0 ;
181 }
182 
183 /// \file grjpeg.cpp
int dx() const
Returns the image width.
Definition: grjpeg.cpp:168
int dy() const
Returns the image height.
Definition: grjpeg.cpp:173
int channels() const
Returns the number of channels (eg. 3).
Definition: grjpeg.cpp:178
bool valid() const
Returns true if constructed successfully.
Definition: grjpeg.cpp:163
JpegInfo(const unsigned char *p, size_t)
Constructor.
Definition: grjpeg.cpp:151