fix rotated images

This commit is contained in:
Isaac Connor 2020-07-30 19:50:25 -04:00
parent 366ce5b3eb
commit be05040a47
2 changed files with 156 additions and 128 deletions

View File

@ -196,14 +196,20 @@ Image::Image(const AVFrame *frame) {
text[0] = '\0'; text[0] = '\0';
width = frame->width; width = frame->width;
linesize = frame->linesize[0];
height = frame->height; height = frame->height;
pixels = width*height; pixels = width*height;
colours = ZM_COLOUR_RGB32; colours = ZM_COLOUR_RGB32;
subpixelorder = ZM_SUBPIX_ORDER_RGBA; subpixelorder = ZM_SUBPIX_ORDER_RGBA;
size = linesize * height; #if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size = av_image_get_buffer_size(AV_PIX_FMT_RGBA, width, height, 32);
// av_image_get_linesize isn't aligned, so we have to do that.
linesize = FFALIGN(av_image_get_linesize(AV_PIX_FMT_RGBA, width, 0), 32);
#else
linesize = FFALIGN(av_image_get_linesize(AV_PIX_FMT_RGBA, width, 0), 1);
size = avpicture_get_size(AV_PIX_FMT_RGBA, width, height);
#endif
buffer = 0; buffer = 0;
holdbuffer = 0; holdbuffer = 0;
AllocImgBuffer(size); AllocImgBuffer(size);
@ -263,24 +269,16 @@ Image::~Image() {
/* Should be called as part of program shutdown to free everything */ /* Should be called as part of program shutdown to free everything */
void Image::Deinitialise() { void Image::Deinitialise() {
if ( !initialised ) return; if ( !initialised ) return;
/*
delete[] y_table;
delete[] uv_table;
delete[] r_v_table;
delete[] g_v_table;
delete[] g_u_table;
delete[] b_u_table;
*/
initialised = false; initialised = false;
if ( readjpg_dcinfo ) { if ( readjpg_dcinfo ) {
jpeg_destroy_decompress(readjpg_dcinfo); jpeg_destroy_decompress(readjpg_dcinfo);
delete readjpg_dcinfo; delete readjpg_dcinfo;
readjpg_dcinfo = 0; readjpg_dcinfo = NULL;
} }
if ( decodejpg_dcinfo ) { if ( decodejpg_dcinfo ) {
jpeg_destroy_decompress(decodejpg_dcinfo); jpeg_destroy_decompress(decodejpg_dcinfo);
delete decodejpg_dcinfo; delete decodejpg_dcinfo;
decodejpg_dcinfo = 0; decodejpg_dcinfo = NULL;
} }
for ( unsigned int quality=0; quality <= 100; quality += 1 ) { for ( unsigned int quality=0; quality <= 100; quality += 1 ) {
if ( writejpg_ccinfo[quality] ) { if ( writejpg_ccinfo[quality] ) {
@ -491,9 +489,17 @@ void Image::Initialise() {
} }
/* Requests a writeable buffer to the image. This is safer than buffer() because this way we can guarantee that a buffer of required size exists */ /* Requests a writeable buffer to the image. This is safer than buffer() because this way we can guarantee that a buffer of required size exists */
uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder) { uint8_t* Image::WriteBuffer(
const unsigned int p_width,
const unsigned int p_height,
const unsigned int p_colours,
const unsigned int p_subpixelorder) {
if ( p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32 ) { if ( p_colours != ZM_COLOUR_GRAY8
&&
p_colours != ZM_COLOUR_RGB24
&&
p_colours != ZM_COLOUR_RGB32 ) {
Error("WriteBuffer called with unexpected colours: %d", p_colours); Error("WriteBuffer called with unexpected colours: %d", p_colours);
return NULL; return NULL;
} }
@ -504,6 +510,7 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
} }
if ( p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder ) { if ( p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder ) {
unsigned int newsize = (p_width * p_height) * p_colours; unsigned int newsize = (p_width * p_height) * p_colours;
if ( buffer == NULL ) { if ( buffer == NULL ) {
@ -524,6 +531,7 @@ uint8_t* Image::WriteBuffer(const unsigned int p_width, const unsigned int p_hei
width = p_width; width = p_width;
height = p_height; height = p_height;
colours = p_colours; colours = p_colours;
linesize = p_width * p_colours;
subpixelorder = p_subpixelorder; subpixelorder = p_subpixelorder;
pixels = height*width; pixels = height*width;
size = newsize; size = newsize;
@ -581,8 +589,9 @@ void Image::AssignDirect(
size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size size = new_buffer_size; // was pixels*colours, but we already calculated it above as new_buffer_size
/* Copy into the held buffer */ /* Copy into the held buffer */
if ( new_buffer != buffer ) if ( new_buffer != buffer ) {
(*fptr_imgbufcpy)(buffer, new_buffer, size); (*fptr_imgbufcpy)(buffer, new_buffer, size);
}
/* Free the new buffer */ /* Free the new buffer */
DumpBuffer(new_buffer, p_buffertype); DumpBuffer(new_buffer, p_buffertype);
@ -603,9 +612,15 @@ void Image::AssignDirect(
buffertype = p_buffertype; buffertype = p_buffertype;
buffer = new_buffer; buffer = new_buffer;
} }
} } // end void Image::AssignDirect
void Image::Assign(const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size) { void Image::Assign(
const unsigned int p_width,
const unsigned int p_height,
const unsigned int p_colours,
const unsigned int p_subpixelorder,
const uint8_t* new_buffer,
const size_t buffer_size) {
unsigned int new_size = (p_width * p_height) * p_colours; unsigned int new_size = (p_width * p_height) * p_colours;
if ( new_buffer == NULL ) { if ( new_buffer == NULL ) {
@ -652,24 +667,30 @@ void Image::Assign(const unsigned int p_width, const unsigned int p_height, cons
if ( new_buffer != buffer ) if ( new_buffer != buffer )
(*fptr_imgbufcpy)(buffer, new_buffer, size); (*fptr_imgbufcpy)(buffer, new_buffer, size);
Debug(1,"Assign");
} }
void Image::Assign(const Image &image) { void Image::Assign(const Image &image) {
unsigned int new_size = (image.width * image.height) * image.colours; unsigned int new_size = image.height * image.linesize;
if ( image.buffer == NULL ) { if ( image.buffer == NULL ) {
Error("Attempt to assign image with an empty buffer"); Error("Attempt to assign image with an empty buffer");
return; return;
} }
if ( image.colours != ZM_COLOUR_GRAY8 && image.colours != ZM_COLOUR_RGB24 && image.colours != ZM_COLOUR_RGB32 ) { if ( image.colours != ZM_COLOUR_GRAY8
&&
image.colours != ZM_COLOUR_RGB24
&&
image.colours != ZM_COLOUR_RGB32 ) {
Error("Attempt to assign image with unexpected colours per pixel: %d", image.colours); Error("Attempt to assign image with unexpected colours per pixel: %d", image.colours);
return; return;
} }
if ( !buffer || image.width != width || image.height != height if ( !buffer
|| image.colours != colours || image.subpixelorder != subpixelorder) { || image.width != width || image.height != height
|| image.colours != colours || image.subpixelorder != subpixelorder
|| image.linesize != linesize
) {
if ( holdbuffer && buffer ) { if ( holdbuffer && buffer ) {
if ( new_size > allocation ) { if ( new_size > allocation ) {
@ -689,13 +710,19 @@ void Image::Assign( const Image &image ) {
colours = image.colours; colours = image.colours;
subpixelorder = image.subpixelorder; subpixelorder = image.subpixelorder;
size = new_size; size = new_size;
linesize = image.linesize;
} }
if ( image.buffer != buffer ) if ( image.buffer != buffer )
(*fptr_imgbufcpy)(buffer, image.buffer, size); (*fptr_imgbufcpy)(buffer, image.buffer, size);
} }
Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p_subpixelorder, const Box *limits ) { Image *Image::HighlightEdges(
Rgb colour,
unsigned int p_colours,
unsigned int p_subpixelorder,
const Box *limits
) {
if ( colours != ZM_COLOUR_GRAY8 ) { if ( colours != ZM_COLOUR_GRAY8 ) {
Panic("Attempt to highlight image edges when colours = %d", colours); Panic("Attempt to highlight image edges when colours = %d", colours);
} }
@ -722,10 +749,13 @@ Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) { for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) {
bool edge = false; bool edge = false;
if ( *p ) { if ( *p ) {
edge = (x > 0 && !*(p-1)) || (x < (width-1) && !*(p+1)) || (y > 0 && !*(p-width)) || (y < (height-1) && !*(p+width));
#if 0
if ( !edge && x > 0 && !*(p-1) ) edge = true; if ( !edge && x > 0 && !*(p-1) ) edge = true;
if ( !edge && x < (width-1) && !*(p+1) ) edge = true; if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
if ( !edge && y > 0 && !*(p-width) ) edge = true; if ( !edge && y > 0 && !*(p-width) ) edge = true;
if ( !edge && y < (height-1) && !*(p+width) ) edge = true; if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
#endif
} }
if ( edge ) { if ( edge ) {
*phigh = colour; *phigh = colour;
@ -739,10 +769,13 @@ Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh += 3 ) { for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh += 3 ) {
bool edge = false; bool edge = false;
if ( *p ) { if ( *p ) {
edge = (x > 0 && !*(p-1)) || (x < (width-1) && !*(p+1)) || (y > 0 && !*(p-width)) || (y < (height-1) && !*(p+width));
#if 0
if ( !edge && x > 0 && !*(p-1) ) edge = true; if ( !edge && x > 0 && !*(p-1) ) edge = true;
if ( !edge && x < (width-1) && !*(p+1) ) edge = true; if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
if ( !edge && y > 0 && !*(p-width) ) edge = true; if ( !edge && y > 0 && !*(p-width) ) edge = true;
if ( !edge && y < (height-1) && !*(p+width) ) edge = true; if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
#endif
} }
if ( edge ) { if ( edge ) {
RED_PTR_RGBA(phigh) = RED_VAL_RGBA(colour); RED_PTR_RGBA(phigh) = RED_VAL_RGBA(colour);
@ -758,10 +791,13 @@ Image *Image::HighlightEdges( Rgb colour, unsigned int p_colours, unsigned int p
for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) { for ( unsigned int x = lo_x; x <= hi_x; x++, p++, phigh++ ) {
bool edge = false; bool edge = false;
if ( *p ) { if ( *p ) {
edge = (x > 0 && !*(p-1)) || (x < (width-1) && !*(p+1)) || (y > 0 && !*(p-width)) || (y < (height-1) && !*(p+width));
#if 0
if ( !edge && x > 0 && !*(p-1) ) edge = true; if ( !edge && x > 0 && !*(p-1) ) edge = true;
if ( !edge && x < (width-1) && !*(p+1) ) edge = true; if ( !edge && x < (width-1) && !*(p+1) ) edge = true;
if ( !edge && y > 0 && !*(p-width) ) edge = true; if ( !edge && y > 0 && !*(p-width) ) edge = true;
if ( !edge && y < (height-1) && !*(p+width) ) edge = true; if ( !edge && y < (height-1) && !*(p+width) ) edge = true;
#endif
} }
if ( edge ) { if ( edge ) {
*phigh = colour; *phigh = colour;
@ -872,14 +908,11 @@ bool Image::ReadJpeg(const char *filename, unsigned int p_colours, unsigned int
switch ( p_colours ) { switch ( p_colours ) {
case ZM_COLOUR_GRAY8: case ZM_COLOUR_GRAY8:
{
cinfo->out_color_space = JCS_GRAYSCALE; cinfo->out_color_space = JCS_GRAYSCALE;
new_colours = ZM_COLOUR_GRAY8; new_colours = ZM_COLOUR_GRAY8;
new_subpixelorder = ZM_SUBPIX_ORDER_NONE; new_subpixelorder = ZM_SUBPIX_ORDER_NONE;
break; break;
}
case ZM_COLOUR_RGB32: case ZM_COLOUR_RGB32:
{
#ifdef JCS_EXTENSIONS #ifdef JCS_EXTENSIONS
new_colours = ZM_COLOUR_RGB32; new_colours = ZM_COLOUR_RGB32;
if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
@ -900,10 +933,8 @@ bool Image::ReadJpeg(const char *filename, unsigned int p_colours, unsigned int
#else #else
Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead."); Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead.");
#endif #endif
}
case ZM_COLOUR_RGB24: case ZM_COLOUR_RGB24:
default: default:
{
new_colours = ZM_COLOUR_RGB24; new_colours = ZM_COLOUR_RGB24;
if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGR ) { if ( p_subpixelorder == ZM_SUBPIX_ORDER_BGR ) {
#ifdef JCS_EXTENSIONS #ifdef JCS_EXTENSIONS
@ -927,8 +958,7 @@ cinfo->out_color_space = JCS_RGB;
new_subpixelorder = ZM_SUBPIX_ORDER_RGB; new_subpixelorder = ZM_SUBPIX_ORDER_RGB;
} }
break; break;
} } // end switch p_colours
}
if ( WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL ) { if ( WriteBuffer(new_width, new_height, new_colours, new_subpixelorder) == NULL ) {
Error("Failed requesting writeable buffer for reading JPEG image."); Error("Failed requesting writeable buffer for reading JPEG image.");
@ -939,11 +969,10 @@ cinfo->out_color_space = JCS_RGB;
jpeg_start_decompress(cinfo); jpeg_start_decompress(cinfo);
JSAMPROW row_pointer; /* pointer to a single row */ JSAMPROW row_pointer = buffer;
int row_stride = width * colours; /* physical row width in buffer */
while ( cinfo->output_scanline < cinfo->output_height ) { while ( cinfo->output_scanline < cinfo->output_height ) {
row_pointer = &buffer[cinfo->output_scanline * row_stride];
jpeg_read_scanlines(cinfo, &row_pointer, 1); jpeg_read_scanlines(cinfo, &row_pointer, 1);
row_pointer += linesize;
} }
jpeg_finish_decompress(cinfo); jpeg_finish_decompress(cinfo);
@ -957,16 +986,16 @@ cinfo->out_color_space = JCS_RGB;
// Note quality=zero means default // Note quality=zero means default
bool Image::WriteJpeg(const char *filename, int quality_override) const { bool Image::WriteJpeg(const char *filename, int quality_override) const {
return Image::WriteJpeg(filename, quality_override, (timeval){0,0}); return Image::WriteJpeg(filename, quality_override, (timeval){0,0}, false);
} }
bool Image::WriteJpeg(const char *filename) const { bool Image::WriteJpeg(const char *filename) const {
return Image::WriteJpeg(filename, 0, (timeval){0,0}); return Image::WriteJpeg(filename, 0, (timeval){0,0}, false);
} }
bool Image::WriteJpeg(const char *filename, bool on_blocking_abort) const { bool Image::WriteJpeg(const char *filename, bool on_blocking_abort) const {
return Image::WriteJpeg(filename, 0, (timeval){0,0}, on_blocking_abort); return Image::WriteJpeg(filename, 0, (timeval){0,0}, on_blocking_abort);
} }
bool Image::WriteJpeg(const char *filename, struct timeval timestamp) const { bool Image::WriteJpeg(const char *filename, struct timeval timestamp) const {
return Image::WriteJpeg(filename, 0, timestamp); return Image::WriteJpeg(filename, 0, timestamp, false);
} }
bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp) const { bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval timestamp) const {
@ -984,14 +1013,12 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval
struct jpeg_compress_struct *cinfo = writejpg_ccinfo[quality]; struct jpeg_compress_struct *cinfo = writejpg_ccinfo[quality];
FILE *outfile = NULL; FILE *outfile = NULL;
static int raw_fd = 0; static int raw_fd = 0;
bool need_create_comp = false;
raw_fd = 0; raw_fd = 0;
if ( !cinfo ) { if ( !cinfo ) {
cinfo = writejpg_ccinfo[quality] = new jpeg_compress_struct; cinfo = writejpg_ccinfo[quality] = new jpeg_compress_struct;
cinfo->err = jpeg_std_error(&jpg_err.pub); cinfo->err = jpeg_std_error(&jpg_err.pub);
jpeg_create_compress(cinfo); jpeg_create_compress(cinfo);
need_create_comp = true;
} }
if ( !on_blocking_abort ) { if ( !on_blocking_abort ) {
jpg_err.pub.error_exit = zm_jpeg_error_exit; jpg_err.pub.error_exit = zm_jpeg_error_exit;
@ -1009,8 +1036,6 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval
return false; return false;
} }
} }
if ( need_create_comp )
jpeg_create_compress(cinfo);
if ( !on_blocking_abort ) { if ( !on_blocking_abort ) {
if ( (outfile = fopen(filename, "wb")) == NULL ) { if ( (outfile = fopen(filename, "wb")) == NULL ) {
@ -1041,13 +1066,16 @@ bool Image::WriteJpeg(const char *filename, int quality_override, struct timeval
case ZM_COLOUR_RGB32: case ZM_COLOUR_RGB32:
#ifdef JCS_EXTENSIONS #ifdef JCS_EXTENSIONS
cinfo->input_components = 4; cinfo->input_components = 4;
if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { if ( subpixelorder == ZM_SUBPIX_ORDER_RGBA ) {
cinfo->in_color_space = JCS_EXT_RGBX;
} else if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
cinfo->in_color_space = JCS_EXT_BGRX; cinfo->in_color_space = JCS_EXT_BGRX;
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) { } else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
cinfo->in_color_space = JCS_EXT_XRGB; cinfo->in_color_space = JCS_EXT_XRGB;
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) { } else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
cinfo->in_color_space = JCS_EXT_XBGR; cinfo->in_color_space = JCS_EXT_XBGR;
} else { } else {
Warning("Unknwon subpixelorder %d", subpixelorder);
/* Assume RGBA */ /* Assume RGBA */
cinfo->in_color_space = JCS_EXT_RGBX; cinfo->in_color_space = JCS_EXT_RGBX;
} }
@ -1117,16 +1145,12 @@ cinfo->out_color_space = JCS_RGB;
jpeg_write_marker(cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes)); jpeg_write_marker(cinfo, EXIF_CODE, (const JOCTET *)exiftimes, sizeof(exiftimes));
} }
JSAMPROW row_pointer; /* pointer to a single row */ JSAMPROW row_pointer = buffer; /* pointer to a single row */
int row_stride = linesize;
//cinfo->image_width * colours; /* physical row width in buffer */
while ( cinfo->next_scanline < cinfo->image_height ) { while ( cinfo->next_scanline < cinfo->image_height ) {
row_pointer = &buffer[cinfo->next_scanline * row_stride];
jpeg_write_scanlines(cinfo, &row_pointer, 1); jpeg_write_scanlines(cinfo, &row_pointer, 1);
row_pointer += linesize;
} }
jpeg_finish_compress(cinfo); jpeg_finish_compress(cinfo);
fclose(outfile); fclose(outfile);
return true; return true;
@ -1240,11 +1264,10 @@ cinfo->out_color_space = JCS_RGB;
jpeg_start_decompress(cinfo); jpeg_start_decompress(cinfo);
JSAMPROW row_pointer; /* pointer to a single row */ JSAMPROW row_pointer = buffer; /* pointer to a single row */
int row_stride = width * colours; /* physical row width in buffer */
while ( cinfo->output_scanline < cinfo->output_height ) { while ( cinfo->output_scanline < cinfo->output_height ) {
row_pointer = &buffer[cinfo->output_scanline * row_stride];
jpeg_read_scanlines(cinfo, &row_pointer, 1); jpeg_read_scanlines(cinfo, &row_pointer, 1);
row_pointer += linesize;
} }
jpeg_finish_decompress(cinfo); jpeg_finish_decompress(cinfo);
@ -1284,13 +1307,16 @@ bool Image::EncodeJpeg(JOCTET *outbuffer, int *outbuffer_size, int quality_overr
case ZM_COLOUR_RGB32: case ZM_COLOUR_RGB32:
#ifdef JCS_EXTENSIONS #ifdef JCS_EXTENSIONS
cinfo->input_components = 4; cinfo->input_components = 4;
if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) { if ( subpixelorder == ZM_SUBPIX_ORDER_RGBA ) {
cinfo->in_color_space = JCS_EXT_RGBX;
} else if ( subpixelorder == ZM_SUBPIX_ORDER_BGRA ) {
cinfo->in_color_space = JCS_EXT_BGRX; cinfo->in_color_space = JCS_EXT_BGRX;
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) { } else if ( subpixelorder == ZM_SUBPIX_ORDER_ARGB ) {
cinfo->in_color_space = JCS_EXT_XRGB; cinfo->in_color_space = JCS_EXT_XRGB;
} else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) { } else if ( subpixelorder == ZM_SUBPIX_ORDER_ABGR ) {
cinfo->in_color_space = JCS_EXT_XBGR; cinfo->in_color_space = JCS_EXT_XBGR;
} else { } else {
Warning("unknown subpixelorder %d", subpixelorder);
/* Assume RGBA */ /* Assume RGBA */
cinfo->in_color_space = JCS_EXT_RGBX; cinfo->in_color_space = JCS_EXT_RGBX;
} }
@ -1331,11 +1357,10 @@ cinfo->out_color_space = JCS_RGB;
jpeg_start_compress(cinfo, TRUE); jpeg_start_compress(cinfo, TRUE);
JSAMPROW row_pointer; /* pointer to a single row */ JSAMPROW row_pointer = buffer;
int row_stride = linesize; /* physical row width in buffer */
while ( cinfo->next_scanline < cinfo->image_height ) { while ( cinfo->next_scanline < cinfo->image_height ) {
row_pointer = &buffer[cinfo->next_scanline * row_stride];
jpeg_write_scanlines(cinfo, &row_pointer, 1); jpeg_write_scanlines(cinfo, &row_pointer, 1);
row_pointer += linesize;
} }
jpeg_finish_compress(cinfo); jpeg_finish_compress(cinfo);
@ -1620,7 +1645,6 @@ void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) {
} else { } else {
Error("Overlay called with unexpected colours: %d", colours); Error("Overlay called with unexpected colours: %d", colours);
} }
Debug(1, "Overlay");
} // end void Image::Overlay( const Image &image, unsigned int x, unsigned int y ) } // end void Image::Overlay( const Image &image, unsigned int x, unsigned int y )
void Image::Blend( const Image &image, int transparency ) { void Image::Blend( const Image &image, int transparency ) {
@ -1760,7 +1784,7 @@ Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb thres
return result; return result;
} }
/* New function to allow buffer re-using instead of allocationg memory for the delta image every time */ /* New function to allow buffer re-using instead of allocating memory for the delta image every time */
void Image::Delta( const Image &image, Image* targetimage) const { void Image::Delta( const Image &image, Image* targetimage) const {
#ifdef ZM_IMAGE_PROFILING #ifdef ZM_IMAGE_PROFILING
struct timespec start,end,diff; struct timespec start,end,diff;
@ -2333,9 +2357,7 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) {
double grad; double grad;
//Debug( 9, "dx: %.2lf, dy: %.2lf", dx, dy );
if ( fabs(dx) <= fabs(dy) ) { if ( fabs(dx) <= fabs(dy) ) {
//Debug( 9, "dx <= dy" );
if ( y1 != y2 ) if ( y1 != y2 )
grad = dx/dy; grad = dx/dy;
else else
@ -2345,9 +2367,7 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) {
int y, yinc = (y1<y2)?1:-1; int y, yinc = (y1<y2)?1:-1;
grad *= yinc; grad *= yinc;
if ( colours == ZM_COLOUR_GRAY8 ) { if ( colours == ZM_COLOUR_GRAY8 ) {
//Debug( 9, "x1:%d, x2:%d, y1:%d, y2:%d, gr:%.2f", x1, x2, y1, y2, grad );
for ( x = x1, y = y1; y != y2; y += yinc, x += grad ) { for ( x = x1, y = y1; y != y2; y += yinc, x += grad ) {
//Debug( 9, "x:%.2f, y:%d", x, y );
buffer[(y*width)+int(round(x))] = colour; buffer[(y*width)+int(round(x))] = colour;
} }
} else if ( colours == ZM_COLOUR_RGB24 ) { } else if ( colours == ZM_COLOUR_RGB24 ) {
@ -2434,7 +2454,8 @@ void Image::Fill(Rgb colour, int density, const Polygon &polygon) {
#ifndef ZM_DBG_OFF #ifndef ZM_DBG_OFF
if ( logLevel() >= Logger::DEBUG9 ) { if ( logLevel() >= Logger::DEBUG9 ) {
for ( int i = 0; i < n_global_edges; i++ ) { for ( int i = 0; i < n_global_edges; i++ ) {
Debug( 9, "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", i, global_edges[i].min_y, global_edges[i].max_y, global_edges[i].min_x, global_edges[i]._1_m ); Debug(9, "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f",
i, global_edges[i].min_y, global_edges[i].max_y, global_edges[i].min_x, global_edges[i]._1_m);
} }
} }
#endif #endif
@ -2461,7 +2482,8 @@ void Image::Fill(Rgb colour, int density, const Polygon &polygon) {
#ifndef ZM_DBG_OFF #ifndef ZM_DBG_OFF
if ( logLevel() >= Logger::DEBUG9 ) { if ( logLevel() >= Logger::DEBUG9 ) {
for ( int i = 0; i < n_active_edges; i++ ) { for ( int i = 0; i < n_active_edges; i++ ) {
Debug( 9, "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", y, i, active_edges[i].min_y, active_edges[i].max_y, active_edges[i].min_x, active_edges[i]._1_m ); Debug(9, "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f",
y, i, active_edges[i].min_y, active_edges[i].max_y, active_edges[i].min_x, active_edges[i]._1_m );
} }
} }
#endif #endif
@ -2519,18 +2541,12 @@ void Image::Fill( Rgb colour, const Polygon &polygon ) {
Fill(colour, 1, polygon); Fill(colour, 1, polygon);
} }
/* RGB32 compatible: complete */
void Image::Rotate(int angle) { void Image::Rotate(int angle) {
angle %= 360; angle %= 360;
if ( !angle ) { if ( !angle || angle%90 ) {
return; return;
} }
if ( angle%90 ) {
return;
}
unsigned int new_height = height; unsigned int new_height = height;
unsigned int new_width = width; unsigned int new_width = width;
uint8_t* rotate_buffer = AllocBuffer(size); uint8_t* rotate_buffer = AllocBuffer(size);
@ -2554,17 +2570,17 @@ void Image::Rotate( int angle ) {
} }
} else if ( colours == ZM_COLOUR_RGB32 ) { } else if ( colours == ZM_COLOUR_RGB32 ) {
Rgb* s_rptr = (Rgb*)s_ptr; Rgb* s_rptr = (Rgb*)s_ptr;
for ( unsigned int i = new_width; i > 0; i-- ) { for ( unsigned int i = new_width; i; i-- ) {
Rgb* d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2)); Rgb* d_rptr = (Rgb*)(rotate_buffer+((i-1)<<2));
for ( unsigned int j = new_height; j > 0; j-- ) { for ( unsigned int j = new_height; j; j-- ) {
*d_rptr = *s_rptr++; *d_rptr = *s_rptr++;
d_rptr += new_width; d_rptr += new_width;
} }
} }
} else /* Assume RGB24 */ { } else /* Assume RGB24 */ {
for ( unsigned int i = new_width; i > 0; i-- ) { for ( unsigned int i = new_width; i; i-- ) {
unsigned char *d_ptr = rotate_buffer+((i-1)*3); unsigned char *d_ptr = rotate_buffer+((i-1)*3);
for ( unsigned int j = new_height; j > 0; j-- ) { for ( unsigned int j = new_height; j; j-- ) {
*d_ptr = *s_ptr++; *d_ptr = *s_ptr++;
*(d_ptr+1) = *s_ptr++; *(d_ptr+1) = *s_ptr++;
*(d_ptr+2) = *s_ptr++; *(d_ptr+2) = *s_ptr++;
@ -2644,7 +2660,7 @@ void Image::Rotate( int angle ) {
} }
AssignDirect(new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM); AssignDirect(new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM);
} } // void Image::Rotate(int angle)
/* RGB32 compatible: complete */ /* RGB32 compatible: complete */
void Image::Flip( bool leftright ) { void Image::Flip( bool leftright ) {
@ -2701,7 +2717,6 @@ void Image::Flip( bool leftright ) {
} }
AssignDirect(width, height, colours, subpixelorder, flip_buffer, size, ZM_BUFTYPE_ZM); AssignDirect(width, height, colours, subpixelorder, flip_buffer, size, ZM_BUFTYPE_ZM);
} }
void Image::Scale(unsigned int factor) { void Image::Scale(unsigned int factor) {
@ -2764,7 +2779,7 @@ void Image::Scale( unsigned int factor ) {
unsigned int last_h_index = 0; unsigned int last_h_index = 0;
unsigned int last_w_index = 0; unsigned int last_w_index = 0;
unsigned int h_index; unsigned int h_index;
for ( unsigned int y = 0; y < (unsigned int)height; y++ ) { for ( unsigned int y = 0; y < height; y++ ) {
h_count += factor; h_count += factor;
h_index = h_count/ZM_SCALE_BASE; h_index = h_count/ZM_SCALE_BASE;
if ( h_index > last_h_index ) { if ( h_index > last_h_index ) {
@ -2773,7 +2788,7 @@ void Image::Scale( unsigned int factor ) {
last_w_index = 0; last_w_index = 0;
unsigned char *ps = &buffer[y*wc]; unsigned char *ps = &buffer[y*wc];
for ( unsigned int x = 0; x < (unsigned int)width; x++ ) { for ( unsigned int x = 0; x < width; x++ ) {
w_count += factor; w_count += factor;
w_index = w_count/ZM_SCALE_BASE; w_index = w_count/ZM_SCALE_BASE;
@ -2833,7 +2848,6 @@ void Image::Deinterlace_Discard() {
} else { } else {
Error("Deinterlace called with unexpected colours: %d", colours); Error("Deinterlace called with unexpected colours: %d", colours);
} }
} }
void Image::Deinterlace_Linear() { void Image::Deinterlace_Linear() {
@ -3634,6 +3648,7 @@ __attribute__((noinline)) void fast_delta8_argb(const uint8_t* col1, const uint8
result += 4; result += 4;
} }
} }
__attribute__((noinline)) void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { __attribute__((noinline)) void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) {
/* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */
int r,g,b; int r,g,b;

View File

@ -201,9 +201,22 @@ public:
width = linesize = height = colours = size = pixels = subpixelorder = 0; width = linesize = height = colours = size = pixels = subpixelorder = 0;
} }
void Assign( unsigned int p_width, unsigned int p_height, unsigned int p_colours, unsigned int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size); void Assign(
unsigned int p_width,
unsigned int p_height,
unsigned int p_colours,
unsigned int p_subpixelorder,
const uint8_t* new_buffer,
const size_t buffer_size);
void Assign(const Image &image); void Assign(const Image &image);
void AssignDirect( const unsigned int p_width, const unsigned int p_height, const unsigned int p_colours, const unsigned int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype); void AssignDirect(
const unsigned int p_width,
const unsigned int p_height,
const unsigned int p_colours,
const unsigned int p_subpixelorder,
uint8_t *new_buffer,
const size_t buffer_size,
const int p_buffertype);
inline void CopyBuffer(const Image &image) { inline void CopyBuffer(const Image &image) {
Assign(image); Assign(image);