31 m_type(G::Test::enabled(
"contiguous")?Contiguous:type) ,
35 m_data(m_data_store) ,
46 m_data(image_buffer) ,
49 G_ASSERT( image_buffer.empty() ) ;
53 m_type(image_buffer.size()>1U?Segmented:Contiguous) ,
56 m_channels(channels) ,
57 m_data(image_buffer) ,
60 G_ASSERT( image_buffer.empty() || ( dx > 0 && dy > 0 && (channels==1 || channels==3) ) ) ;
61 G_ASSERT( image_buffer.empty() || image_buffer.size() == 1U || image_buffer.size() == sizet(dy) ) ;
62 G_ASSERT( image_buffer.empty() || image_buffer.at(0U).size() == imagebuffer::size_of(image_buffer) || image_buffer.at(0U).size() == sizet(dx,channels) ) ;
63 G_ASSERT( imagebuffer::size_of(image_buffer) == sizet(dx,dy,channels) ) ;
65 if( image_buffer.empty() && dx != 0 && dy != 0 )
66 throw Error(
"empty image buffer" ) ;
68 if( dx < 0 || dy < 0 || !(image_buffer.empty() || channels==1 || channels==3) )
69 throw Error(
"invalid dimensions" ) ;
71 if( !image_buffer.empty() && image_buffer.size() != 1U && image_buffer.size() != sizet(dy) )
72 throw Error(
"incorrect image buffer size" ) ;
86 return m_dx == 0 || m_dy == 0 || m_channels == 0 ;
91 G_ASSERT( dx > 0 && dy > 0 ) ;
92 G_ASSERT( channels == 1 || channels == 3 ) ;
94 if( dx == m_dx && dy == m_dy && channels == m_channels )
99 m_channels = channels ;
101 if( m_type == Contiguous )
103 m_data.resize( 1U ) ;
104 m_data[0].resize( sizet(m_dx,m_dy,m_channels) ) ;
109 m_data.reserve( m_dy ) ;
110 const size_t rowsize = sizet(m_dx,m_channels) ;
111 for(
int y = 0 ; y < m_dy ; y++ )
113 m_data.push_back( std::vector<char>() ) ;
114 m_data.back().resize( rowsize ) ;
118 G_ASSERT( valid() ) ;
121 void Gr::ImageData::setRows()
const
126 m_rows.resize( m_dy ) ;
127 if( m_type == Contiguous )
129 const unsigned char * row_p = storerow(0) ;
130 const size_t rowsize = sizet( m_dx , m_channels ) ;
131 for(
int y = 0 ; y < m_dy ; y++ , row_p += rowsize )
132 m_rows[y] = const_cast<unsigned char*>(row_p) ;
136 for(
int y = 0 ; y < m_dy ; y++ )
137 m_rows[y] = const_cast<unsigned char*>(storerow(y)) ;
157 return reinterpret_cast<char**
>(rowPointers()) ;
160 bool Gr::ImageData::contiguous()
const
162 return m_data.size() == 1U ;
167 G_ASSERT( valid() ) ;
168 if( scale_in < 1 )
throw Error(
"invalid scale factor" ) ;
169 if( scale_in == 1 && (monochrome_out?1:m_channels) == m_channels ) return ;
170 if( m_data.empty() )
throw Error(
"empty" ) ;
174 unsigned char * p_out = storerow( 0 ) ;
175 const size_t dp = sizet( m_channels , scale_in ) ;
176 for(
int y = 0 ; y < m_dy ; y += scale_in , y_new++ )
178 const unsigned char * p_in = row( y ) ;
179 if( m_data.size() > 1U ) p_out = row( y_new ) ;
180 for(
int x = x_new = 0 ; x < m_dx ; x += scale_in , p_in += dp , x_new++ )
182 if( monochrome_out && m_channels == 3 && use_colourspace )
186 else if( monochrome_out || m_channels == 1 )
198 G_ASSERT( x_new == scaled(m_dx,scale_in) ) ;
199 G_ASSERT( y_new == scaled(m_dy,scale_in) ) ;
202 m_channels = monochrome_out ? 1 : m_channels ;
204 if( m_data.size() == 1U )
206 m_data[0].resize( sizet(m_dx,m_dy,m_channels) ) ;
210 size_t drow = sizet( m_dx , m_channels ) ;
211 m_data.resize( m_dy ) ;
212 for(
int y = 0 ; y < m_dy ; y++ )
213 m_data[y].resize( drow ) ;
216 G_ASSERT( valid() ) ;
221 G_ASSERT( y >= 0 && y < m_dy ) ;
222 G_ASSERT( scale >= 1 ) ;
223 if( y < 0 || y >= m_dy || scale < 1 )
224 throw Error(
"invalid parameters" ) ;
226 if( scale == 1 && !monochrome_out )
228 std::memcpy( &out[0] , row(y) , rowsize() ) ;
232 out.resize( sizet(scaled(m_dx,scale),monochrome_out?1:m_channels) ) ;
233 const unsigned char * p_in = row( y ) ;
234 const unsigned char * p_in_end = p_in + rowsize() ;
235 unsigned char * p_out =
reinterpret_cast<unsigned char*
>(&out[0]) ;
236 size_t dp_in = sizet( scale , m_channels ) ;
237 for( ; p_in < p_in_end ; p_in += dp_in )
239 if( m_channels == 3 && monochrome_out && use_colourspace )
243 else if( m_channels == 3 && monochrome_out )
247 else if( m_channels == 3 )
261 void Gr::ImageData::copyRowIn(
int y ,
const unsigned char * p_in ,
size_t n_in ,
int channels_in ,
bool use_colourspace ,
int scale )
263 G_ASSERT( y >= 0 && p_in !=
nullptr ) ;
264 G_ASSERT( y < m_dy ) ;
265 G_ASSERT( channels_in == 1 || channels_in == 3 ) ;
266 G_ASSERT( scale >= 1 ) ;
267 if( p_in ==
nullptr || y < 0 || y >= m_dy || !(channels_in==1||channels_in==3) || scale < 1 )
268 throw Error(
"invalid row parameter" ) ;
269 if( m_dx != scaled(
int(n_in)/channels_in,scale) )
270 throw Error(
"invalid row copy" ) ;
272 copyRowInImp( row(y) , p_in , channels_in , use_colourspace , scale ) ;
275 void Gr::ImageData::copyRowInImp(
unsigned char * row_out ,
const unsigned char * row_in ,
int channels_in ,
bool use_colourspace ,
int scale )
277 if( m_channels == 3 && channels_in == 1 )
281 const int drow_out = m_dx * 3 ;
282 for(
int x_in = 0 ; x_out < drow_out ; x_in += scale , x_out += 3 )
284 row_out[x_out+0] = row_out[x_out+1] = row_out[x_out+2] = row_in[x_in] ;
287 else if( m_channels == 1 && channels_in == 3 )
291 const int dx_in = 3 * scale ;
292 for(
int x_in = 0 ; x_out < m_dx ; x_in += dx_in , x_out++ )
294 row_out[x_out] = use_colourspace ?
Gr::ColourSpace::y_int(row_in[x_in],row_in[x_in+1],row_in[x_in+2]) : row_in[x_in] ;
297 else if( scale > 1 && m_channels == 1 )
300 for(
int x_in = 0 ; x_out < m_dx ; x_in += scale , x_out++ )
302 row_out[x_out] = row_in[x_in] ;
308 const int dx_in = 3 * scale ;
309 int drow_out = m_dx * 3 ;
310 for(
int x_in = 0 ; x_out < drow_out ; x_in += dx_in , x_out += 3 )
312 row_out[x_out+0] = row_in[x_in+0] ;
313 row_out[x_out+1] = row_in[x_in+1] ;
314 row_out[x_out+2] = row_in[x_in+2] ;
319 std::memcpy( row_out , row_in , sizet(m_dx,m_channels) ) ;
323 void Gr::ImageData::copyIn(
const char * data_in ,
size_t size_in ,
int dx_in ,
int dy_in ,
int channels_in ,
bool use_colourspace ,
int scale )
325 G_ASSERT( scale >= 1 ) ;
326 G_ASSERT( channels_in==1 || channels_in==3 ) ;
327 G_ASSERT( dx_in > 0 && dy_in > 0 ) ;
328 G_ASSERT( data_in !=
nullptr && size_in != 0U ) ;
330 if( scale < 1 || data_in ==
nullptr || size_in == 0U || dx_in <= 0 || dy_in <= 0 || !( channels_in == 1 || channels_in == 3 ) )
331 throw Error(
"invalid parameter" ) ;
333 if( size_in != sizet(dx_in,dy_in,channels_in) || scaled(dx_in,scale) != m_dx || scaled(dy_in,scale) != m_dy )
334 throw Error(
"copy-in size mismatch" ) ;
336 const size_t drow_in = sizet( dx_in , channels_in , scale ) ;
337 const unsigned char * p_in =
reinterpret_cast<const unsigned char*
>(data_in) ;
338 for(
int y = 0 ; y < m_dy ; y++ , p_in += drow_in )
340 copyRowInImp( row(y) , p_in , channels_in , use_colourspace , scale ) ;
346 G_ASSERT( scale >= 1 ) ;
347 G_ASSERT( channels_in==1 || channels_in==3 ) ;
348 G_ASSERT( !data_in.empty() ) ;
349 G_ASSERT( data_in.size() == sizet(dy_in) || data_in.size() == 1U ) ;
350 G_ASSERT( data_in.at(0U).size() == sizet(channels_in,dx_in) || data_in.at(0U).size() == sizet(channels_in,dx_in,dy_in) ) ;
352 if( scale < 1 || ( data_in.size() != sizet(dy_in) && data_in.size() != 1U ) || data_in.empty() ||
353 ( data_in.at(0U).size() != sizet(channels_in,dx_in) && data_in.at(0U).size() != sizet(channels_in,dx_in,dy_in) ) ||
354 !(channels_in==1 || channels_in==3) )
355 throw Error(
"invalid parameter" ) ;
357 if( scaled(dx_in,scale) != m_dx || scaled(dy_in,scale) != m_dy )
358 throw Error(
"copy-in size mismatch" ) ;
360 if( data_in.size() == 1U )
362 const size_t drow_in = sizet(scale,dx_in,channels_in) ;
363 const unsigned char * row_in =
reinterpret_cast<const unsigned char*
>(&(data_in.at(0))[0]) ;
364 for(
int y_out = 0 ; y_out < m_dy ; y_out++ , row_in += drow_in )
366 copyRowInImp( row(y_out) , row_in , channels_in , use_colourspace , scale ) ;
372 for(
int y_out = 0 ; y_out < m_dy ; y_out++ , y_in += scale )
374 const unsigned char * row_in =
reinterpret_cast<const unsigned char*
>(&(data_in.at(y_in))[0]) ;
375 copyRowInImp( row(y_out) , row_in , channels_in , use_colourspace , scale ) ;
382 out.resize( size() ) ;
383 if( contiguous() && m_dy > 0 )
385 std::memcpy( &out[0] , storerow(0) , size() ) ;
389 char * out_p = &out[0] ;
390 const size_t drow = sizet( m_dx , m_channels ) ;
391 for(
int y = 0 ; y < m_dy ; y++ , out_p += drow )
393 std::memcpy( out_p , row(y) , drow ) ;
401 imagebuffer::resize( out , m_dx , m_dy , m_channels ) ;
402 const size_t drow = rowsize() ;
404 row_iterator
const end = imagebuffer::row_end( out ) ;
405 for( row_iterator p = imagebuffer::row_begin(out) ; p != end ; ++p , y++ )
407 std::memcpy( imagebuffer::row_ptr(p) , row(y) , drow ) ;
414 throw Error(
"empty" ) ;
416 throw Error(
"not contiguous" ) ;
423 throw Error(
"empty" ) ;
425 throw Error(
"not contiguous" ) ;
431 return sizet( m_dx , m_dy , m_channels ) ;
436 return sizet( m_dx , m_channels ) ;
441 if( (g==r && b==r ) || m_channels == 1 )
443 size_t n = rowsize() ;
444 for(
int y = 0 ; y < m_dy ; y++ )
445 std::memset( row(y) , r , n ) ;
449 for(
int y = 0 ; y < m_dy ; y++ )
451 for(
int x = 0 ; x < m_dx ; x++ )
452 rgb( x , y , r , g , b ) ;
457 template <
typename Fn>
458 void Gr::ImageData::modify( Fn fn )
460 const size_t drow = rowsize() ;
461 for(
int y = 0 ; y < m_dy ; y++ )
463 unsigned char * p = row( y ) ;
464 for(
size_t i = 0U ; i < drow ; i++ , p++ )
471 template <
typename Fn>
472 void Gr::ImageData::modify(
const Gr::ImageData & other , Fn fn )
474 int dy = std::min( m_dy , other.m_dy ) ;
475 int dx = std::min( m_dx , other.m_dx ) ;
476 if( m_channels == other.m_channels )
478 const size_t drow = sizet( dx , m_channels ) ;
479 for(
int y = 0 ; y < dy ; y++ )
481 unsigned char * p_this = row( y ) ;
482 const unsigned char * p_other = other.
row( y ) ;
483 for(
size_t i = 0U ; i < drow ; i++ , p_this++ , p_other++ )
485 fn( *p_this , *p_other ) ;
489 else if( m_channels == 1 && other.m_channels == 3 )
491 const size_t drow = sizet( dx ) ;
492 for(
int y = 0 ; y < dy ; y++ )
494 unsigned char * p_this = row( y ) ;
495 const unsigned char * p_other = other.
row( y ) ;
496 for(
size_t i = 0U ; i < drow ; i++ , p_this++ , p_other += 3 )
498 fn( *p_this , p_other[0] , p_other[1] , p_other[2] ) ;
502 else if( m_channels == 3 && other.m_channels == 1 )
504 const size_t drow = sizet( dx , 3 ) ;
505 for(
int y = 0 ; y < dy ; y++ )
507 unsigned char * p_this = row( y ) ;
508 const unsigned char * p_other = other.
row( y ) ;
510 for(
size_t i = 0U ; i < drow ; i++ , p_this++ )
512 fn( *p_this , *p_other ) ;
513 c = c == 0 ? 1 : ( c == 1 ? 2 : 0 ) ;
514 if( c == 0 ) ++p_other ;
520 template <
typename Fn>
523 if( m_dx != data_1.m_dx ||
524 m_dy != data_1.m_dy ||
525 m_channels != data_1.m_channels ||
526 data_1.m_dx != data_2.m_dx ||
527 data_1.m_dy != data_2.m_dy ||
528 data_1.m_channels != data_2.m_channels )
529 throw ImageData::Error(
"mismatched image sizes" ) ;
531 const size_t drow = sizet( m_dx , m_channels ) ;
532 for(
int y = 0 ; y < m_dy ; y++ )
534 unsigned char * p_this = row( y ) ;
535 const unsigned char * p_1 = data_1.
row( y ) ;
536 const unsigned char * p_2 = data_2.
row( y ) ;
537 for(
size_t i = 0U ; i < drow ; i++ , p_this++ , p_1++ , p_2++ )
539 fn( *p_this , *p_1 , *p_2 ) ;
548 Shift(
unsigned int n ) : m_n(n) {}
549 void operator()(
unsigned char & c )
const
559 modify( Shift(shift) ) ;
566 Fractionate(
unsigned int n ,
unsigned int d ) : m_n(n) , m_d(d) {}
567 void operator()(
unsigned char & c )
const
569 unsigned int cc = c ;
572 cc = std::min( 255U , cc ) ;
573 c =
static_cast<unsigned char>(cc) ;
582 if( numerator == 0U )
584 else if( denominator != 0U && numerator != denominator )
585 modify( Fractionate(numerator,denominator) ) ;
592 Mix(
unsigned int n1 ,
unsigned int n2 ,
unsigned int d ) : m_n1(n1) , m_n2(n2) , m_d(d?d:1U) {}
593 void operator()(
unsigned char & c ,
unsigned char c_1 ,
unsigned char c_2 )
const
595 unsigned int cc_1 = c_1 ;
598 cc_1 = std::min( 255U , cc_1 ) ;
600 unsigned int cc_2 = c_2 ;
603 cc_2 = std::min( 255U , cc_2 ) ;
605 unsigned int cc = cc_1 + cc_2 ;
606 cc = std::min( 255U , cc ) ;
608 c =
static_cast<unsigned char>(cc) ;
619 resize( data_1.
dx() , data_1.
dy() , data_1.
channels() ) ;
620 modify( data_1 , data_2 , Mix(n1,n2,d) ) ;
627 void operator()(
unsigned char & c_this ,
unsigned char c_other )
const
629 const unsigned int n = c_this + c_other ;
630 c_this = std::min( n , 255U ) ;
632 void operator()(
unsigned char & c_this ,
unsigned char c0 ,
unsigned char c1 ,
unsigned char c2 )
const
641 modify( other , Add() ) ;
648 void operator()(
unsigned char & c_this ,
unsigned char c_other )
650 const unsigned int n = c_this > c_other ?
static_cast<unsigned int>(c_this-c_other) : 0U ;
651 c_this = std::min( n , 255U ) ;
653 void operator()(
unsigned char & c_this ,
unsigned char c0 ,
unsigned char c1 ,
unsigned char c2 )
662 modify( other , Subtract() ) ;
667 if( dx_new >= m_dx && dy_new >= m_dy )
670 dx_new = std::min( dx_new , m_dx ) ;
671 dy_new = std::min( dy_new , m_dy ) ;
673 const int top = (m_dy-dy_new) / 2 ;
674 const int left = (m_dx-dx_new) / 2 ;
676 const size_t dleft = sizet( left , m_channels ) ;
677 const size_t dtop = sizet( top , m_dx , m_channels ) ;
678 const size_t drow_out = sizet( dx_new , m_channels ) ;
679 const size_t drow_in = sizet( m_dx , m_channels ) ;
683 const unsigned char * row_in = storerow(0) + dtop ;
684 unsigned char * row_out = storerow(0) ;
685 for(
int y = 0 ; y < dy_new ; y++ , row_in += drow_in , row_out += drow_out )
687 std::memmove( row_out , row_in+dleft , drow_out ) ;
689 m_data[0].resize( sizet(dx_new,dy_new,m_channels) ) ;
693 std::rotate( m_data.begin() , m_data.begin() + top , m_data.end() ) ;
694 m_data.resize( dy_new ) ;
695 for(
int y = 0 ; y < dy_new ; y++ )
697 unsigned char * p_out = storerow( y ) ;
698 std::memmove( p_out , p_out+dleft , drow_out ) ;
699 m_data[y].resize( drow_out ) ;
706 G_ASSERT( valid() ) ;
711 if( dx_new <= m_dx && dy_new <= m_dy )
714 dx_new = std::max( dx_new , m_dx ) ;
715 dy_new = std::max( dy_new , m_dy ) ;
717 const int top = (dy_new-m_dy) / 2 ;
718 const int left = (dx_new-m_dx) / 2 ;
719 const int right = dx_new - m_dx - left ;
721 const size_t dleft = sizet( left , m_channels ) ;
722 const size_t dright = sizet( right , m_channels ) ;
723 const size_t drow_in = sizet( m_dx , m_channels ) ;
724 const size_t drow_out = sizet( dx_new , m_channels ) ;
728 m_data[0].resize( sizet(dx_new,dy_new,m_channels) ) ;
729 const unsigned char * p_in = storerow(0) + (m_dy-1)*m_dx*m_channels ;
730 unsigned char * p_out = storerow(0) + (top+(m_dy-1))*dx_new*m_channels ;
731 for(
int y = m_dy-1 ; y >= 0 ; y-- , p_in -= drow_in , p_out -= drow_out )
733 std::memmove( p_out+dleft , p_in , drow_in ) ;
734 std::memset( p_out , 0 , dleft ) ;
735 std::memset( p_out+dleft+drow_in , 0 , dright ) ;
737 p_out = storerow(0) ;
738 for(
int y = 0 ; y < dy_new ; y++ , p_out += drow_out )
740 if( y < top ) std::memset( p_out , 0 , drow_out ) ;
745 m_data.resize( dy_new ) ;
746 for(
int y = m_dy ; y < dy_new ; y++ )
747 m_data[y].resize( dx_new ) ;
748 std::rotate( m_data.begin() , m_data.begin()+m_dy , m_data.begin()+m_dy+top ) ;
749 for(
int y = 0 ; y < dy_new ; y++ )
751 m_data[y].resize( drow_out ) ;
752 unsigned char * row = storerow( y ) ;
753 std::memmove( row+dleft , row , drow_in ) ;
754 std::memset( row , 0 , dleft ) ;
761 G_ASSERT( valid() ) ;
770 m_image_data(image_data) ,
773 m_foreground(foreground) ,
774 m_background(background) ,
775 m_draw_background(draw_background)
778 void operator()(
int x_in ,
int y_in ,
bool b )
782 if( x >= 0 && x < m_image_data.dx() &&
783 y >= 0 && y < m_image_data.dy() )
786 m_image_data.rgb( x , y , m_foreground.r() , m_foreground.g() , m_foreground.b() ) ;
787 else if( m_draw_background )
788 m_image_data.rgb( x , y , m_background.r() , m_background.g() , m_background.b() ) ;
796 bool m_draw_background ;
801 Colour foreground ,
Colour background ,
bool draw_background ,
bool wrap_on_nl )
803 return ImageDataWriter( *
this , x , y , foreground , background , draw_background , wrap_on_nl ) ;
809 GlyphOut out( *
this , x , y , foreground , background , draw_background ) ;
817 checker(
bool & ok ) : m_ok(ok) {}
818 void operator()(
bool checked_ok ) { G_ASSERT(checked_ok) ;
if(!checked_ok) m_ok = false ; }
823 bool Gr::ImageData::valid()
const
828 checker check( ok ) ;
830 if( m_dx == 0 || m_dx == 0 || m_channels == 0 || m_data.empty() )
834 check( m_channels == 0 ) ;
835 check( m_data.empty() ) ;
836 check( !m_rows_set ) ;
840 check( m_dx > 0 && m_dy > 0 && m_channels > 0 ) ;
841 check( m_data.empty() || m_data.size() == 1U || m_data.size() == sizet(m_dy) ) ;
844 check( m_rows.empty() ) ;
846 else if( m_data.size() == 1U )
848 check( m_data[0].size() == sizet(m_dx,m_dy,m_channels) ) ;
849 check( !m_rows_set || m_rows.size() == sizet(m_dy) ) ;
850 check( !m_rows_set || m_rows[0] == storerow(0) ) ;
851 check( contiguous() ) ;
855 check( m_data[0].size() == sizet(m_dx,m_channels) ) ;
856 check( m_data[1].size() == sizet(m_dx,m_channels) ) ;
859 check( m_rows.size() == sizet(m_dy) ) ;
860 for(
size_t y = 0 ; y < std::min(m_rows.size(),sizet(m_dy)) ; y++ )
861 check( m_rows.at(y) == storerow(y) ) ;
871 Colour foreground ,
Colour background ,
bool draw_background ,
bool wrap_on_nl ) :
878 m_foreground(foreground) ,
879 m_background(background) ,
880 m_draw_background(draw_background) ,
881 m_wrap_on_nl(wrap_on_nl)
885 bool Gr::ImageDataWriter::pre(
char c )
887 if( m_wrap_on_nl && c ==
'\n' )
899 void Gr::ImageDataWriter::post(
char c )
triple< unsigned char > rgb(triple< unsigned char > yuv) g__noexcept
A top-level function that calculates rgb from yuv with default implementation options.
size_t rowsize() const
Returns the row size, ie. dx()*channels().
int dx() const
Returns the width.
A traits class that can be specialised for Gr::ImageBuffer candidates.
A holder for image data, having eight bits per sample and one or three channels.
void mix(const ImageData &_1, const ImageData &_2, unsigned int numerator_1, unsigned int numerator_2, unsigned int denominator)
Creates a mixed image from two equally-shaped sources images.
size_t size() const
Returns the total image size, ie. dx()*dy()*channels().
void resize(int dx, int dy, int channels)
Resizes the image data.
void expand(int dx, int dy)
Expands the image so that the new image has the dimensions given, with the original image centered in...
Type type() const
Returns the contiguous/segmented enumeration.
unsigned char * row(int y)
Returns a pointer to the y'th row.
void scale(int factor, bool monochrome, bool use_colourspace)
Scales-down the image by sub-sampling.
A simple rgb colour structure.
Vectors ImageBuffer
An ImageBuffer is used to hold raw image data, typically in more than one chunk.
bool empty() const
Returns true if the size() is zero.
void subtract(const ImageData &other)
Subtracts the given image data from this.
unsigned char ** rowPointers()
Returns a pointer to the array of row pointers.
void copyTo(std::vector< char > &out) const
Copies the image to the given output buffer, resizing the output vector as necessary.
ImageDataWriter(Gr::ImageData &data, int x, int y, Gr::Colour foreground, Gr::Colour background, bool draw_background, bool wrap_on_nl)
Constructor.
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).
void copyRowIn(int y, const unsigned char *row_buffer_in, size_t row_buffer_in_size, int channels_in, bool use_colourspace=false, int scale=1)
Sets a row of pixels by copying, with channel-count adjustment and optional scaling.
unsigned char y_int(unsigned char r, unsigned char g, unsigned char b)
A fast conversion from rgb to y.
void dim(unsigned int shift)
Dims the image by right-shifting all pixel values.
const unsigned char * p() const
Returns a const pointer to the image data, but throws if the data is not contiguous.
static void output(const std::string &s, Tout &out_functor)
Calls an (x,y,bool) functor for all the glyph points corresponding to the given line of text...
ImageData(Type=Segmented)
Default constructor for a zero-size image.
void fill(unsigned char r, unsigned char g, unsigned char b)
Fills the image with a solid colour as if calling rgb() for every pixel.
ImageDataWriter writer(int x, int y, Colour foreground, Colour background, bool draw_background, bool wrap_on_nl)
Returns a functor that calls write().
void crop(int dx, int dy)
Crops the image so that it fits inside the given dimensions.
void copyRowOut(int y, std::vector< char > &out, int scale=1, bool monochrome_out=false, bool use_colourspace=true) const
Copies a row into the given output buffer, resizing the output vector as necessary.
void add(const ImageData &other)
Adds the given image data to this.
int dy() const
Returns the height.
void write(char c, int x, int y, Colour foreground, Colour background, bool draw_background)
Draws a latin-1 character into the image at the given position.