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