Skip to content

Commit

Permalink
Take PNG opacity into account when merging tiles
Browse files Browse the repository at this point in the history
  • Loading branch information
jbo-ads committed Nov 5, 2019
1 parent 765ad96 commit c3f706d
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 2 deletions.
5 changes: 5 additions & 0 deletions include/mapcache.h
Expand Up @@ -1534,6 +1534,11 @@ void _mapcache_imageio_jpeg_decode_to_image(mapcache_context *ctx, mapcache_buff
*/
mapcache_image_format_type mapcache_imageio_header_sniff(mapcache_context *ctx, mapcache_buffer *buffer);

/**
* \brief lookup the first few bytes of a buffer to check for alpha channel
*/
mapcache_image_alpha_type mapcache_imageio_alpha_sniff(mapcache_context *ctx, mapcache_buffer *buffer);

/**
* \brief checks if the given buffer is a recognized image format
*/
Expand Down
24 changes: 24 additions & 0 deletions lib/imageio.c
Expand Up @@ -58,6 +58,30 @@ mapcache_image_format_type mapcache_imageio_header_sniff(mapcache_context *ctx,
}
}

mapcache_image_alpha_type mapcache_imageio_alpha_sniff(mapcache_context *ctx, mapcache_buffer *buffer)
{
const unsigned char * b = buffer->buf;
mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,buffer);
if (t==GC_JPEG) {
// A JPG file is opaque
return MC_ALPHA_NO;
} else if (t==GC_PNG && buffer->size >= 26 && (b[12]|32) == 'i' && (b[13]|32) == 'h' && (b[14]|32) == 'd' && (b[15]|32) == 'r') {
// Check color type of PNG file in IHDR chunk
if (b[25] == 0 || b[25] == 2) {
// Gray or RGB without alpha
return MC_ALPHA_NO;
} else if (b[25] == 4 || b[25] == 6) {
// Gray or RGB with alpha
return MC_ALPHA_YES;
} else {
// TODO: Should check palette index
return MC_ALPHA_UNKNOWN;
}
} else {
return MC_ALPHA_UNKNOWN;
}
}

mapcache_image* mapcache_imageio_decode(mapcache_context *ctx, mapcache_buffer *buffer)
{
mapcache_image_format_type type = mapcache_imageio_header_sniff(ctx,buffer);
Expand Down
1 change: 1 addition & 0 deletions lib/imageio_jpeg.c
Expand Up @@ -243,6 +243,7 @@ void _mapcache_imageio_jpeg_decode_to_image(mapcache_context *r, mapcache_buffer
return;
}

img->has_alpha = MC_ALPHA_NO;
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
img->w = cinfo.output_width;
Expand Down
3 changes: 3 additions & 0 deletions lib/imageio_png.c
Expand Up @@ -408,6 +408,7 @@ void _mapcache_imageio_png_decode_to_image(mapcache_context *ctx, mapcache_buffe
unsigned char pixel[4];
uint8_t alpha;
unsigned char *pixptr = row_pointers[i];
img->has_alpha = MC_ALPHA_NO;
for(j=0; j<img->w; j++) {

memcpy (pixel, pixptr, sizeof (uint32_t));
Expand All @@ -417,10 +418,12 @@ void _mapcache_imageio_png_decode_to_image(mapcache_context *ctx, mapcache_buffe
pixptr[1] = pixel[1];
pixptr[2] = pixel[0];
} else if (alpha == 0) {
img->has_alpha = MC_ALPHA_YES;
pixptr[0] = 0;
pixptr[1] = 0;
pixptr[2] = 0;
} else {
img->has_alpha = MC_ALPHA_YES;
PREMULTIPLY(pixptr[0],pixel[2],alpha);
PREMULTIPLY(pixptr[1],pixel[1],alpha);
PREMULTIPLY(pixptr[2],pixel[0],alpha);
Expand Down
4 changes: 2 additions & 2 deletions lib/tileset.c
Expand Up @@ -903,8 +903,8 @@ void mapcache_tileset_tile_set_get_with_subdimensions(mapcache_context *ctx, map
if(GC_HAS_ERROR(ctx))
goto cleanup;
}
if((subtile->encoded_data && mapcache_imageio_header_sniff(ctx,subtile->encoded_data) == GC_JPEG)||
(subtile->raw_image && subtile->raw_image->has_alpha == MC_ALPHA_NO)) {
if ((mapcache_imageio_alpha_sniff(ctx,subtile->encoded_data) == MC_ALPHA_NO) ||
(subtile->raw_image && subtile->raw_image->has_alpha == MC_ALPHA_NO)) {
/* the returned image is fully opaque, we don't need to get/decode/merge any further subtiles */
if(assembled_image)
assembled_image->has_alpha = MC_ALPHA_NO;
Expand Down

0 comments on commit c3f706d

Please sign in to comment.