1 /* File: loader_webp.c
2 Time-stamp: <2012-12-09 21:19:30 gawen>
3
4 Copyright (c) 2011 David Hauweele <david@hauweele.net>
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of the University nor the names of its contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 SUCH DAMAGE. */
30
31 #define _BSD_SOURCE 1
32
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <fcntl.h>
39
40 #include <webp/decode.h>
41 #include <webp/encode.h>
42 #include <Imlib2.h>
43
44 #include "imlib2_common.h"
45 #include "loader.h"
46
read_file(const char * filename,size_t * size,ImlibProgressFunction progress)47 static uint8_t * read_file(const char *filename, size_t *size,
48 ImlibProgressFunction progress)
49 {
50 struct stat buf;
51 uint8_t *data = NULL;
52 int fd;
53
54 #ifndef __EMX__
55 if((fd = open(filename, O_RDONLY)) < 0)
56 #else
57 if((fd = open(filename, O_RDONLY | O_BINARY)) < 0)
58 #endif
59 return NULL;
60
61 if(fstat(fd, &buf) < 0 ||
62 !(data = malloc(buf.st_size)))
63 goto EXIT;
64
65 *size = read(fd, data, buf.st_size);
66
67 EXIT:
68 close(fd);
69 return data;
70 }
71
load(ImlibImage * im,ImlibProgressFunction progress,char progress_granularity,char immediate_load)72 char load(ImlibImage * im, ImlibProgressFunction progress,
73 char progress_granularity, char immediate_load)
74 {
75 uint8_t *data;
76 size_t size;
77 int w,h;
78 int has_alpha;
79 #if (WEBP_DECODER_ABI_VERSION >= 0x200)
80 WebPBitstreamFeatures features;
81 #endif
82 char ret = 0;
83
84 if(im->data)
85 return 0;
86
87 if(!(data = read_file(im->real_file, &size, progress)))
88 return 0;
89
90 #if (WEBP_DECODER_ABI_VERSION >= 0x200)
91 if(WebPGetFeatures(data, size, &features) != VP8_STATUS_OK)
92 goto EXIT;
93 w = features.width;
94 h = features.height;
95 has_alpha = features.has_alpha;
96 #else /* compatibility with versions <= 0.1.3 */
97 if (!WebPGetInfo(data, size, &w, &h))
98 goto EXIT;
99 has_alpha = 0;
100 #endif
101
102 if(!im->loader && !im->data) {
103 im->w = w;
104 im->h = h;
105
106 if(!IMAGE_DIMENSIONS_OK(w, h))
107 goto EXIT;
108
109 if(!has_alpha)
110 UNSET_FLAGS(im->flags, F_HAS_ALPHA);
111 else
112 SET_FLAGS(im->flags, F_HAS_ALPHA);
113 im->format = strdup("webp");
114 }
115
116 if((!im->data && im->loader) || immediate_load || progress)
117 im->data = (DATA32*)WebPDecodeBGRA(data, size, &w, &h);
118
119 if(progress)
120 progress(im, 100, 0, 0, 0, 0);
121
122 ret = 1;
123
124 EXIT:
125 free(data);
126 return ret;
127 }
128
save(ImlibImage * im,ImlibProgressFunction progress,char progress_granularity)129 char save(ImlibImage *im, ImlibProgressFunction progress,
130 char progress_granularity)
131 {
132 ImlibImageTag *tag;
133 uint8_t *data;
134 float fqual;
135 size_t size;
136 int fd;
137 int quality = 75;
138 char ret = 0;
139
140 if(!im->data)
141 return 0;
142
143 #ifndef __EMX__
144 if((fd = open(im->real_file, O_WRONLY | O_CREAT,
145 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0)
146 #else
147 if((fd = open(im->real_file, O_WRONLY | O_CREAT | O_BINARY,
148 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) < 0)
149 #endif
150 return 0;
151
152 /* look for tags attached to image to get extra parameters like quality
153 settings etc. - this is the "api" to hint for extra information for
154 saver modules */
155 tag = __imlib_GetTag(im, "compression");
156 if(tag) {
157 int compression = tag->val;
158
159 if(compression < 0)
160 compression = 0;
161 else if(compression > 9)
162 compression = 9;
163
164 quality = (9 - compression) * 10;
165 quality = quality * 10 / 9;
166 }
167 tag = __imlib_GetTag(im, "quality");
168 if(tag) {
169 quality = tag->val;
170
171 if(quality < 1)
172 quality = 1;
173 else if(quality > 100)
174 quality = 100;
175 }
176
177 fqual = (float)quality;
178
179 if(!(size = WebPEncodeBGRA((const uint8_t *)im->data, im->w, im->h,
180 im->w << 2, fqual, &data)))
181 goto EXIT;
182
183 if(write(fd, data, size) != size)
184 goto EXIT;
185
186 if(progress)
187 progress(im, 100, 0, 0, 0, 0);
188
189 ret = 1;
190
191 EXIT:
192 close(fd);
193 if(data)
194 free(data);
195 return ret;
196 }
197
formats(ImlibLoader * l)198 void formats(ImlibLoader *l)
199 {
200 int i;
201 char *list_formats[] = { "webp" };
202
203 l->num_formats = (sizeof(list_formats) / sizeof(char *));
204 l->formats = malloc(sizeof(char *) * l->num_formats);
205 for(i = 0 ; i < l->num_formats ; i++)
206 l->formats[i] = strdup(list_formats[i]);
207 }
208