blob: 88899697c423202441e57dcfe248d4b89524b687 [file] [log] [blame]
Kristian Høgsbergb41d76c2011-04-23 15:03:15 -04001/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <stdint.h>
26#include <errno.h>
27#include <png.h>
28
29#include "compositor.h"
30
31static inline int
32multiply_alpha(int alpha, int color)
33{
34 int temp = (alpha * color) + 0x80;
35
36 return ((temp + (temp >> 8)) >> 8);
37}
38
39static void
40premultiply_data(png_structp png,
41 png_row_infop row_info,
42 png_bytep data)
43{
44 unsigned int i;
45 png_bytep p;
46
47 for (i = 0, p = data; i < row_info->rowbytes; i += 4, p += 4) {
48 png_byte alpha = p[3];
49 uint32_t w;
50
51 if (alpha == 0) {
52 w = 0;
53 } else {
54 png_byte red = p[0];
55 png_byte green = p[1];
56 png_byte blue = p[2];
57
58 if (alpha != 0xff) {
59 red = multiply_alpha(alpha, red);
60 green = multiply_alpha(alpha, green);
61 blue = multiply_alpha(alpha, blue);
62 }
63 w = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
64 }
65
66 * (uint32_t *) p = w;
67 }
68}
69
70static void
71read_func(png_structp png, png_bytep data, png_size_t size)
72{
73 FILE *fp = png_get_io_ptr(png);
74
75 if (fread(data, 1, size, fp) < 0)
76 png_error(png, NULL);
77}
78
Kristian Høgsberg1c562182011-05-02 22:09:20 -040079WL_EXPORT uint32_t *
Kristian Høgsbergcb784472012-01-03 11:40:25 -050080weston_load_image(const char *filename,
81 int32_t *width_arg, int32_t *height_arg,
82 uint32_t *stride_arg)
Kristian Høgsbergb41d76c2011-04-23 15:03:15 -040083{
84 png_struct *png;
85 png_info *info;
86 png_byte *data;
87 png_byte **row_pointers = NULL;
88 png_uint_32 width, height;
89 int depth, color_type, interlace, stride;
90 unsigned int i;
91 FILE *fp;
92
93 fp = fopen(filename, "rb");
94 if (fp == NULL)
95 return NULL;
96
97 png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
98 NULL, NULL, NULL);
99 if (!png) {
100 fclose(fp);
101 return NULL;
102 }
103
104 info = png_create_info_struct(png);
105 if (!info) {
106 png_destroy_read_struct(&png, &info, NULL);
107 fclose(fp);
108 return NULL;
109 }
110
111 png_set_read_fn(png, fp, read_func);
112 png_read_info(png, info);
113 png_get_IHDR(png, info,
114 &width, &height, &depth,
115 &color_type, &interlace, NULL, NULL);
116
117 if (color_type == PNG_COLOR_TYPE_PALETTE)
118 png_set_palette_to_rgb(png);
119
120 if (color_type == PNG_COLOR_TYPE_GRAY)
121 png_set_expand_gray_1_2_4_to_8(png);
122
123 if (png_get_valid(png, info, PNG_INFO_tRNS))
124 png_set_tRNS_to_alpha(png);
125
126 if (depth == 16)
127 png_set_strip_16(png);
128
129 if (depth < 8)
130 png_set_packing(png);
131
132 if (color_type == PNG_COLOR_TYPE_GRAY ||
133 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
134 png_set_gray_to_rgb(png);
135
136 if (interlace != PNG_INTERLACE_NONE)
137 png_set_interlace_handling(png);
138
139 png_set_filler(png, 0xff, PNG_FILLER_AFTER);
140 png_set_read_user_transform_fn(png, premultiply_data);
141 png_read_update_info(png, info);
142 png_get_IHDR(png, info,
143 &width, &height, &depth,
144 &color_type, &interlace, NULL, NULL);
145
146 stride = width * 4;
147 data = malloc(stride * height);
148 if (!data) {
149 png_destroy_read_struct(&png, &info, NULL);
150 fclose(fp);
151 return NULL;
152 }
153
154 row_pointers = malloc(height * sizeof row_pointers[0]);
155 if (row_pointers == NULL) {
156 free(data);
157 png_destroy_read_struct(&png, &info, NULL);
158 fclose(fp);
159 return NULL;
160 }
161
162 for (i = 0; i < height; i++)
163 row_pointers[i] = &data[i * stride];
164
165 png_read_image(png, row_pointers);
166 png_read_end(png, info);
167
168 free(row_pointers);
169 png_destroy_read_struct(&png, &info, NULL);
170 fclose(fp);
171
172 *width_arg = width;
173 *height_arg = height;
174 *stride_arg = stride;
175
176 return (uint32_t *) data;
177}