46 m_monochrome_out(false)
53 m_monochrome_out = monochrome_out ;
58 return decodeFile( readType(path) , path , out , scale_to_fit ) ;
63 return decodeFile( image_type , path , out , scale_to_fit ) ;
73 file.open( path.
str().c_str() ) ;
76 throw Error(
"cannot open [" + path.
str() +
"]" ) ;
79 catch( std::exception & )
81 if( do_throw ) throw ;
88 G_DEBUG(
"Gr::ImageDecoder::decodeFile: path=[" << path <<
"] type=[" << type_in <<
"]" ) ;
90 int scale = scale_to_fit ? scale_to_fit(type_in) : m_scale ;
92 if( type_in.
isJpeg() && jpegAvailable() )
94 m_jpeg.setup( scale , m_monochrome_out ) ;
95 m_jpeg.decode( out , path ) ;
97 else if( type_in.
isPng() && pngAvailable() )
99 m_png.setup( scale , m_monochrome_out ) ;
100 m_png.decode( out , path ) ;
102 else if( type_in.
isPnm() )
104 m_pnm.setup( scale , m_monochrome_out ) ;
105 m_pnm.decode( out , path ) ;
109 throw Error(
"invalid file format" , path.
str() ) ;
111 return rawtype(out) ;
116 return decodeBuffer( type_in , data.data() , data.size() , out , scale_to_fit ) ;
121 return decodeBuffer( type_in , p , n , out , scale_to_fit ) ;
126 G_DEBUG(
"Gr::ImageDecoder::decodeBuffer: size=" << n <<
" type=[" << type_in <<
"]" ) ;
128 int scale = scale_to_fit ? scale_to_fit(type_in) : m_scale ;
130 if( type_in.
isJpeg() && jpegAvailable() )
132 m_jpeg.setup( scale , m_monochrome_out ) ;
133 m_jpeg.decode( out , p , n ) ;
135 else if( type_in.
isPng() && pngAvailable() )
137 m_png.setup( scale , m_monochrome_out ) ;
138 m_png.decode( out , p , n ) ;
140 else if( type_in.
isPnm() )
142 m_pnm.setup( scale , m_monochrome_out ) ;
143 m_pnm.decode( out , p , n ) ;
145 else if( type_in.
isRaw() )
148 ImageType type_out =
ImageType::raw( type_in , scale , m_monochrome_out ) ;
149 out.
resize( type_out.dx() , type_out.dy() , type_out.channels() ) ;
150 out.
copyIn( p , n , type_in.
dx() , type_in.
dy() , type_in.
channels() ,
true , scale ) ;
154 throw Error(
"invalid format" ) ;
156 return rawtype( out ) ;
161 G_DEBUG(
"Gr::ImageDecoder::decode: ImageBuffer type=[" << type_in <<
"]" ) ;
163 int scale = scale_to_fit ? scale_to_fit(type_in) : m_scale ;
165 if( type_in.
isJpeg() && jpegAvailable() )
167 m_jpeg.setup( scale , m_monochrome_out ) ;
168 m_jpeg.decode( out , image_buffer ) ;
170 else if( type_in.
isPng() && pngAvailable() )
172 m_png.setup( scale , m_monochrome_out ) ;
173 m_png.decode( out , image_buffer ) ;
175 else if( type_in.
isPnm() )
177 m_pnm.setup( scale , m_monochrome_out ) ;
178 m_pnm.decode( out , image_buffer ) ;
180 else if( type_in.
isRaw() )
185 out.
copyIn( image_buffer , type_in.
dx() , type_in.
dy() , type_in.
channels() ,
true , scale ) ;
189 throw Error(
"invalid format" ) ;
191 return rawtype( out ) ;
197 G_ASSERT( out_store.
type() == ImageData::Contiguous ) ;
200 if( type_in.
isPnm() )
201 pnm_info =
PnmInfo( p , size_in ) ;
204 if( type_in.
isJpeg() && jpegAvailable() )
206 m_jpeg.setup( m_scale , m_monochrome_out ) ;
207 m_jpeg.decode( out_store , p , size_in ) ;
208 p =
reinterpret_cast<char*
>( out_store.
p() ) ;
209 type_out = rawtype( out_store ) ;
211 else if( type_in.
isPng() && pngAvailable() )
213 m_png.setup( m_scale , m_monochrome_out ) ;
214 m_png.decode( out_store , p , size_in ) ;
215 p =
reinterpret_cast<char*
>( out_store.
p() ) ;
216 type_out = rawtype( out_store ) ;
218 else if( type_in.
isPnm() && pnm_info.binary8() &&
219 ( m_scale > 1 || type_in.
channels() != (m_monochrome_out?1:type_in.
channels()) ) )
222 type_out =
ImageType::raw( type_in , m_scale , m_monochrome_out ) ;
223 if( size_in <= pnm_info.offset() || (size_in-pnm_info.offset()) != type_out.
size() )
224 throw Error(
"invalid pnm size" ) ;
225 std::memmove( p , p+pnm_info.offset() , size_in-pnm_info.offset() ) ;
228 unsigned char * p_out =
reinterpret_cast<unsigned char*
>(p) ;
229 const unsigned char * p_in = p_out ;
230 size_t dp_in = sizet( m_scale , type_in.
channels() ) ;
231 for(
int y = 0 ; y < type_in.
dy() ; y += m_scale )
233 for(
int x = 0 ; x < type_in.
dx() ; x += m_scale , p += dp_in )
235 if( m_monochrome_out && type_in.
channels() == 3 )
237 else if( m_monochrome_out )
240 { *p_out++ = p_in[0] ; *p_out++ = p_in[1] ; *p_out++ = p_in[2] ; }
244 else if( type_in.
isPnm() && pnm_info.binary8() )
247 type_out =
ImageType::raw( type_in , m_scale , m_monochrome_out ) ;
248 if( size_in <= pnm_info.offset() || (size_in-pnm_info.offset()) != type_out.
size() )
249 throw Error(
"invalid pnm size" ) ;
250 std::memmove( p , p+pnm_info.offset() , size_in-pnm_info.offset() ) ;
252 else if( type_in.
isPnm() )
254 m_pnm.setup( m_scale , m_monochrome_out ) ;
255 m_pnm.decode( out_store , p , size_in ) ;
256 p =
reinterpret_cast<char*
>( out_store.
p() ) ;
257 type_out = rawtype( out_store ) ;
259 else if( type_in.
isRaw() && (m_scale > 1 || type_in.
channels() != (m_monochrome_out?1:type_in.
channels()) ) )
261 type_out =
ImageType::raw( type_in , m_scale , m_monochrome_out ) ;
262 unsigned char * p_out =
reinterpret_cast<unsigned char*
>(p) ;
263 const unsigned char * p_in = p_out ;
264 size_t dp_in = sizet( m_scale , type_in.
channels() ) ;
265 for(
int y = 0 ; y < type_in.
dy() ; y += m_scale )
267 for(
int x = 0 ; x < type_in.
dx() ; x += m_scale , p += dp_in )
269 if( m_monochrome_out && type_in.
channels() == 3 )
271 else if( m_monochrome_out )
274 { *p_out++ = p_in[0] ; *p_out++ = p_in[1] ; *p_out++ = p_in[2] ; }
278 else if( type_in.
isRaw() )
284 throw Error(
"invalid format" ) ;
289 bool Gr::ImageDecoder::jpegAvailable()
292 G_WARNING_ONCE(
"Gr::ImageDecoder::jpegAvailable: no jpeg library built-in" ) ;
296 bool Gr::ImageDecoder::pngAvailable()
299 G_WARNING_ONCE(
"Gr::ImageDecoder::jpegAvailable: no png library built-in" ) ;
305 int Gr::ImageDecoder::ScaleToFit::operator()(
const ImageType & type )
const
312 G_ASSERT( ff >= 0 && dx > 0 && dy > 0 ) ;
313 if( !type.valid() )
return 1 ;
314 int image_dx = type.dx() ;
if( ff > 0 ) image_dx -= (image_dx/ff) ;
315 int image_dy = type.dy() ;
if( ff > 0 ) image_dy -= (image_dy/ff) ;
316 int scale_x = (image_dx+dx-1) / std::max(1,dx) ;
317 int scale_y = (image_dy+dy-1) / std::max(1,dy) ;
320 G_ASSERT( scaled(image_dx,scale_x) <= dx ) ;
321 G_ASSERT( scaled(image_dy,scale_y) <= dy ) ;
322 if( scale_x > 1 ) G_ASSERT( scaled(image_dx,scale_x-1) > dx ) ;
323 if( scale_y > 1 ) G_ASSERT( scaled(image_dy,scale_y-1) > dy ) ;
326 int result = std::max( scale_x , scale_y ) ;
330 Gr::ImageDecoder::ScaleToFit::operator bool()
const
332 const bool zero = dx <= 0 && dy <= 0 ;
std::string str() const
Returns the path string.
bool isRaw() const
Returns true if a raw image type.
int dx() const
Returns the width.
ImageType decodeInPlace(ImageType type_in, char *&p, size_t size_in, ImageData &store)
Decodes an image buffer with raw decoding done in-place.
A holder for image data, having eight bits per sample and one or three channels.
void setup(int scale, bool monochrome_out)
Sets the scale factor.
void resize(int dx, int dy, int channels)
Resizes the image data.
bool isJpeg() const
Returns true if a jpeg image type.
int channels() const
Returns the number of channels.
Type type() const
Returns the contiguous/segmented enumeration.
An encapsulation of image type, including width, height and number of channels, with support for a st...
A class which acquires the process's special privileges on construction and releases them on destruct...
Vectors ImageBuffer
An ImageBuffer is used to hold raw image data, typically in more than one chunk.
static ImageType raw(int dx, int dy, int channels)
Factory function for a raw image type.
size_t size() const
Returns the product of dx, dy and channels.
ImageDecoder()
Default constructor.
static bool available()
Returns true if a jpeg library is available.
bool isPng() const
Returns true if a png image type.
int dy() const
Returns the image height.
void copyIn(const char *data_in, size_t data_size_in, int dx_in, int dy_in, int channels_in, bool use_colourspace=false, int scale=1)
Copies the image in from a raw buffer, with channel-count adjustment and optional scaling...
int channels() const
Returns the number of channels (zero, one or three).
static ImageType readType(const G::Path &path, bool do_throw=true)
A convenience function to read a file's image type.
unsigned char y_int(unsigned char r, unsigned char g, unsigned char b)
A fast conversion from rgb to y.
const unsigned char * p() const
Returns a const pointer to the image data, but throws if the data is not contiguous.
int dx() const
Returns the image width.
ImageType decode(const G::Path &path_in, ImageData &out, const ScaleToFit &=ScaleToFit())
Decodes a file, with a scale-to-fit option.
Describes scale-to-fit target dimensions.
A structure holding portable-anymap metadata.
int dy() const
Returns the height.
static bool available()
Returns true if the png library is available.
A Path object represents a file system path.
bool isPnm() const
Returns true if a pnm image type.