• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 DENSO 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 #include "bitmap.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdlib.h>
26 #include <stdbool.h>
27 #include <arpa/inet.h>
28 #include <endian.h>
29 #include "ivi-wm-client-protocol.h"
30 
31 struct __attribute__ ((__packed__)) BITMAPFILEHEADER {
32     char bfType[2];
33     uint32_t bfSize;
34     uint16_t bfReserved1;
35     uint16_t bfReserved2;
36     uint32_t bfOffBits;
37 };
38 
39 struct __attribute__ ((__packed__)) BITMAPINFOHEADER {
40     uint32_t biSize;
41     uint32_t biWidth;
42     uint32_t biHeight;
43     uint16_t biPlanes;
44     uint16_t biBitCount;
45     uint32_t biCompression;
46     uint32_t biSizeImage;
47     uint32_t biXPixPerMeter;
48     uint32_t biYPixPerMeter;
49     uint32_t biClrUsed;
50     uint32_t biClrImporant;
51 };
52 
53 static void
create_file_header(struct BITMAPFILEHEADER * file_header,int32_t image_size)54 create_file_header(struct BITMAPFILEHEADER *file_header, int32_t image_size)
55 {
56     file_header->bfType[0] = 'B';
57     file_header->bfType[1] = 'M';
58     file_header->bfSize    = htole32(sizeof(struct BITMAPFILEHEADER) +
59                                      sizeof(struct BITMAPINFOHEADER) +
60                                      image_size);
61     file_header->bfOffBits = htole32(sizeof(struct BITMAPFILEHEADER) +
62                                      sizeof(struct BITMAPINFOHEADER));
63 }
64 
65 static void
create_info_header(struct BITMAPINFOHEADER * info_header,int32_t image_size,int32_t width,int32_t height,int16_t bpp)66 create_info_header(struct BITMAPINFOHEADER *info_header, int32_t image_size, int32_t width, int32_t height, int16_t bpp)
67 {
68     info_header->biSize      = htole32(sizeof(struct BITMAPINFOHEADER));
69     info_header->biWidth     = htole32(width);
70     info_header->biHeight    = htole32(height);
71     info_header->biPlanes    = htole16(1);
72     info_header->biBitCount  = htole16(bpp);
73     info_header->biSizeImage = htole32(image_size);
74 }
75 
76 static int
write_bitmap(const char * filename,const struct BITMAPFILEHEADER * file_header,const struct BITMAPINFOHEADER * info_header,const char * buffer)77 write_bitmap(const char *filename,
78              const struct BITMAPFILEHEADER *file_header,
79              const struct BITMAPINFOHEADER *info_header,
80              const char *buffer)
81 {
82     FILE *fp = fopen(filename, "w");
83     if (fp == NULL) {
84         return -1;
85     }
86 
87     fwrite(file_header, sizeof(struct BITMAPFILEHEADER), 1, fp);
88     fwrite(info_header, sizeof(struct BITMAPINFOHEADER), 1, fp);
89     fwrite(buffer, info_header->biSizeImage, 1, fp);
90 
91     fclose(fp);
92     return 0;
93 }
94 
95 int
save_as_bitmap(const char * filename,const char * buffer,int32_t width,int32_t height,uint32_t format)96 save_as_bitmap(const char *filename,
97                const char *buffer,
98                int32_t width,
99                int32_t height,
100                uint32_t format)
101 {
102     int32_t image_stride = 0;
103     int32_t image_size = 0;
104     char *image_buffer = NULL;
105     int32_t row = 0;
106     int32_t col = 0;
107     int32_t image_offset = 0;
108     int32_t offset = 0;
109     int32_t i = 0;
110     int32_t j = 0;
111     int bytes_per_pixel;
112     bool flip_order;
113     bool has_alpha;
114 
115     if ((filename == NULL) || (buffer == NULL)) {
116         return -1;
117     }
118 
119     switch (format) {
120     case WL_SHM_FORMAT_ARGB8888:
121         flip_order = true;
122         has_alpha = true;
123         break;
124     case WL_SHM_FORMAT_XRGB8888:
125         flip_order = true;
126         has_alpha = false;
127         break;
128     case WL_SHM_FORMAT_ABGR8888:
129         flip_order = false;
130         has_alpha = true;
131         break;
132     case WL_SHM_FORMAT_XBGR8888:
133         flip_order = false;
134         has_alpha = false;
135         break;
136     default:
137         fprintf(stderr, "unsupported pixelformat 0x%x\n", format);
138         return -1;
139     }
140 
141     bytes_per_pixel = has_alpha ? 4 : 3;
142     image_stride = (((width * bytes_per_pixel) + 3) & ~3);
143     image_size = image_stride * height;
144 
145     image_buffer = malloc(image_size);
146     if (image_buffer == NULL) {
147         fprintf(stderr, "failed to allocate %d bytes for image buffer: %m\n",
148                 image_size);
149         return -1;
150     }
151 
152     // Store the image in image_buffer in the follwing order B, G, R, [A](B at the lowest address)
153     for (row = 0; row < height; ++row) {
154         for (col = 0; col < width; ++col) {
155             offset = (height - row - 1) * width + col;
156             uint32_t pixel = htonl(((uint32_t*)buffer)[offset]);
157             char * pixel_p = (char*) &pixel;
158             image_offset = row * image_stride + col * bytes_per_pixel;
159             for (i = 0; i < 3; ++i) {
160                 j = flip_order ? 2 - i : i;
161                 image_buffer[image_offset + i] = pixel_p[1 + j];
162             }
163             if (has_alpha) {
164                 image_buffer[image_offset + 3] = pixel_p[0];
165             }
166         }
167     }
168 
169     struct BITMAPFILEHEADER file_header = {};
170     struct BITMAPINFOHEADER info_header = {};
171 
172     create_file_header(&file_header, image_size);
173     create_info_header(&info_header, image_size, width, height, bytes_per_pixel * 8);
174     if (write_bitmap(filename, &file_header, &info_header, image_buffer) != 0) {
175         free(image_buffer);
176         return -1;
177     }
178 
179     free(image_buffer);
180     return 0;
181 }
182