2 * BMP2PNG Converter with libpng
3 * Copyright (C) 2018 MyungJoo Ham <myungjoo.ham@samsung.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
19 * @brief Simple bmp2png converter for testcases
20 * @see http://github.com/nnstreamer/nnstreamer
21 * @author MyungJoo Ham <myungjoo.ham@samsung.com>
22 * @bug No known bugs except for NYI items
24 * This converts bmp files created by gen24bBMP.py.
25 * This won't support general bmp files.
27 * Adopted code from https://www.lemoda.net/c/write-png/
28 * The author, "Ben Bullock <benkasminbullock@gmail.com>", has authorized
29 * to adopt the code as LGPL-2.1 on 2018-07-13
64 colorformat_t color_format;
68 * @brief Given "bitmap", this returns the pixel of bitmap at the point
72 pixel_at (bitmap_t * bitmap, int x, int y)
74 return bitmap->pixels + bitmap->width * y + x;
78 * @brief Write "bitmap" to a PNG file specified by "path"
79 * @return 0 on success, non-zero on error.
82 save_png_to_file (bitmap_t * bitmap, const char *path)
85 png_structp png_ptr = NULL;
86 png_infop info_ptr = NULL;
88 png_byte **row_pointers = NULL;
90 * "status" contains the return value of this function. At first
91 * it is set to a value which means 'failure'. When the routine
92 * has finished its work, it is set to a value which means
97 * The following number is set by trial and error only. I cannot
98 * see where it it is documented in the libpng manual.
104 if (bitmap->color_format == GRAY8) {
106 color_type = PNG_COLOR_TYPE_GRAY;
109 color_type = PNG_COLOR_TYPE_RGB;
112 fp = fopen (path, "wb");
117 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
118 if (png_ptr == NULL) {
119 goto png_create_write_struct_failed;
122 info_ptr = png_create_info_struct (png_ptr);
123 if (info_ptr == NULL) {
124 goto png_create_info_struct_failed;
127 /** Set up error handling. */
129 if (setjmp (png_jmpbuf (png_ptr))) {
133 /** Set image attributes. */
135 png_set_IHDR (png_ptr,
142 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
144 /** Initialize rows of PNG. */
145 row_pointers = png_malloc (png_ptr, bitmap->height * sizeof (png_byte *));
146 g_assert (row_pointers != NULL);
147 for (y = 0; y < bitmap->height; y++) {
149 png_malloc (png_ptr, sizeof (uint8_t) * bitmap->width * pixel_size);
150 g_assert (row != NULL);
151 row_pointers[y] = row;
152 for (x = 0; x < bitmap->width; x++) {
153 pixel_t *pixel = pixel_at (bitmap, x, y);
154 if (bitmap->color_format == GRAY8) {
155 *row++ = pixel->gray;
158 *row++ = pixel->green;
159 *row++ = pixel->blue;
164 /** Write the image data to "fp". */
166 png_init_io (png_ptr, fp);
167 png_set_rows (png_ptr, info_ptr, row_pointers);
168 png_write_png (png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
171 * The routine has successfully written the file, so we set
172 * "status" to a value which indicates success.
177 for (y = 0; y < bitmap->height; y++) {
178 png_free (png_ptr, row_pointers[y]);
180 png_free (png_ptr, row_pointers);
183 png_create_info_struct_failed:
184 png_destroy_write_struct (&png_ptr, &info_ptr);
185 png_create_write_struct_failed:
192 * @brief The main function, provide filename of a bmp file as the 1st argument.
195 main (int argc, char *argv[])
197 const char option_gray[] = "--GRAY8";
201 uint16_t width, height, *ptr16;
204 char header[26]; /** gen24bBMP.py gives you 24B headered bmp file */
209 /** Read the .bmp file (argv[1]) */
210 if (argc < 2 || argc > 3) {
211 printf ("Usage: %s BMPfilename [OPTION:--GRAY8]\n\n", argv[0]);
214 strn = strlen (argv[1]);
215 if (strn < 5 || argv[1][strn - 4] != '.' || argv[1][strn - 3] != 'b' ||
216 argv[1][strn - 2] != 'm' || argv[1][strn - 1] != 'p') {
217 printf ("The BMPfilename must be ending with \".bmp\"\n\n");
219 /** Check the option, --GRAY8 */
220 strn = strlen (option_gray);
221 if ((argc == 3) && (strlen (argv[2]) == strn)
222 && (!strncmp (option_gray, argv[2], strn))) {
223 bmp.color_format = GRAY8;
225 bmp.color_format = RGB;
228 bmpF = fopen (argv[1], "rb");
230 printf ("Cannot open the file: %s\n", argv[1]);
234 size = fread (header, 1, 26, bmpF);
236 printf ("Cannot read the header from the file: %s\n", argv[1]);
241 ptr16 = (uint16_t *) & (header[18]);
243 ptr16 = (uint16_t *) & (header[20]);
246 /** Let's not accept BMP files larger than 10000 x 10000 (Fix Covertify Issue #1029514) */
247 if (width > 10000 || height > 10000 || width < 4 || height < 4) {
249 ("We do not accept BMP files with height or width larger than 10000.\n");
256 bmp.pixels = calloc (bmp.width * bmp.height, sizeof (pixel_t));
258 for (y = (int) height - 1; y >= 0; y--) {
259 for (x = 0; x < (int) width; x++) {
260 pixel_t *pixel = pixel_at (&bmp, x, y);
261 if (bmp.color_format == GRAY8) {
263 size = fread (&gray, 1, 1, bmpF);
265 printf ("x = %d / y = %d / (%d,%d) / size = %zu\n", x, y, width,
272 size = fread (bgr, 1, 3, bmpF);
274 printf ("x = %d / y = %d / (%d,%d) / size = %zu\n", x, y, width,
279 pixel->green = bgr[1];
280 pixel->blue = bgr[0];
283 for (x = 0; x < (width * 3) % 4; x++) {
284 size = fread (&byte, 1, 1, bmpF);
285 /** Go through zero padding */
292 pngfilename = g_strdup (argv[1]);
294 /** Assume the last 4 characters are ".bmp" */
295 strncpy (pngfilename + strlen (argv[1]) - 4, ".png", 5);
296 ret = save_png_to_file (&bmp, pngfilename);
301 printf ("File read size error.\n");