1 /******************************************************************************
2 * $Id$
3 *
4 * Project: MapServer
5 * Purpose: MapCache tile caching support file: high level image format I/O
6 * Author: Thomas Bonfort and the MapServer team.
7 *
8 ******************************************************************************
9 * Copyright (c) 1996-2011 Regents of the University of Minnesota.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies of this Software or works derived from this Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 *****************************************************************************/
29
30 #include "mapcache.h"
31 #include <png.h>
32 #include <jpeglib.h>
33
34 /**\addtogroup imageio*/
35 /** @{ */
36
mapcache_imageio_is_valid_format(mapcache_context * ctx,mapcache_buffer * buffer)37 int mapcache_imageio_is_valid_format(mapcache_context *ctx, mapcache_buffer *buffer)
38 {
39 mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,buffer);
40 if(t==GC_PNG || t==GC_JPEG) {
41 return MAPCACHE_TRUE;
42 } else {
43 return MAPCACHE_FALSE;
44 }
45 }
46
mapcache_imageio_header_sniff(mapcache_context * ctx,mapcache_buffer * buffer)47 mapcache_image_format_type mapcache_imageio_header_sniff(mapcache_context *ctx, mapcache_buffer *buffer)
48 {
49 if(!buffer) {
50 return GC_UNKNOWN;
51 }
52 if(buffer->size >= 8 && png_sig_cmp((png_bytep)buffer->buf, 0, 8) == 0) {
53 return GC_PNG;
54 } else if(buffer->size >= 2 && ((unsigned char*)buffer->buf)[0] == 0xFF && ((unsigned char*)buffer->buf)[1] == 0xD8) {
55 return GC_JPEG;
56 } else {
57 return GC_UNKNOWN;
58 }
59 }
60
mapcache_imageio_alpha_sniff(mapcache_context * ctx,mapcache_buffer * buffer)61 mapcache_image_alpha_type mapcache_imageio_alpha_sniff(mapcache_context *ctx, mapcache_buffer *buffer)
62 {
63 const unsigned char * b = buffer->buf;
64 mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,buffer);
65 mapcache_image_alpha_type alpha_type;
66
67 switch (t) {
68 case GC_JPEG:
69 // JPEG files are opaque
70 alpha_type = MC_ALPHA_NO;
71 break;
72 case GC_PNG:
73 if (buffer->size >= 26) {
74 // Check color type of PNG file in IHDR chunk
75 if ( (b[12]|32)=='i' && (b[13]|32)=='h' && (b[14]|32)=='d' && (b[15]|32)=='r' ) {
76 switch (b[25]) {
77 case 4:
78 case 6:
79 // Gray or RGB with alpha
80 alpha_type = MC_ALPHA_YES;
81 break;
82 default:
83 // Other colortypes have no alpha channel
84 alpha_type = MC_ALPHA_NO;
85 }
86 }
87 } else {
88 alpha_type = MC_ALPHA_UNKNOWN;
89 }
90 break;
91 default:
92 alpha_type = MC_ALPHA_UNKNOWN;
93 break;
94 }
95 return alpha_type;
96 }
97
mapcache_imageio_decode(mapcache_context * ctx,mapcache_buffer * buffer)98 mapcache_image* mapcache_imageio_decode(mapcache_context *ctx, mapcache_buffer *buffer)
99 {
100 mapcache_image_format_type type = mapcache_imageio_header_sniff(ctx,buffer);
101 if(type == GC_PNG) {
102 return _mapcache_imageio_png_decode(ctx,buffer);
103 } else if(type == GC_JPEG) {
104 return _mapcache_imageio_jpeg_decode(ctx,buffer);
105 } else {
106 ctx->set_error(ctx, 500, "mapcache_imageio_decode: unrecognized image format");
107 return NULL;
108 }
109 }
110
mapcache_image_create_empty(mapcache_context * ctx,mapcache_cfg * cfg)111 void mapcache_image_create_empty(mapcache_context *ctx, mapcache_cfg *cfg)
112 {
113 unsigned int color=0;
114
115 /* create a transparent image for PNG, and a white one for jpeg */
116 if(cfg->default_image_format->mime_type && !strstr(cfg->default_image_format->mime_type,"png")) {
117 color = 0xffffffff;
118 }
119 cfg->empty_image = cfg->default_image_format->create_empty_image(ctx, cfg->default_image_format,
120 256,256, color);
121 GC_CHECK_ERROR(ctx);
122 }
123
mapcache_imageio_decode_to_image(mapcache_context * ctx,mapcache_buffer * buffer,mapcache_image * image)124 void mapcache_imageio_decode_to_image(mapcache_context *ctx, mapcache_buffer *buffer,
125 mapcache_image *image)
126 {
127 mapcache_image_format_type type = mapcache_imageio_header_sniff(ctx,buffer);
128 if(type == GC_PNG) {
129 _mapcache_imageio_png_decode_to_image(ctx,buffer,image);
130 } else if(type == GC_JPEG) {
131 _mapcache_imageio_jpeg_decode_to_image(ctx,buffer,image);
132 } else {
133 ctx->set_error(ctx, 500, "mapcache_imageio_decode: unrecognized image format");
134 }
135 return;
136 }
137
138 /** @} */
139
140 /* vim: ts=2 sts=2 et sw=2
141 */
142