Root/
Source at commit 3d3e0fa created 12 years 7 months ago. By Ayla, Read config file(s) present on both system and user-specific directories. | |
---|---|
1 | // Written by Maarten ter Huurne in 2011. |
2 | // Based on the libpng example.c source, with some additional inspiration |
3 | // from SDL_image and openMSX. |
4 | // License: GPL version 2 or later. |
5 | |
6 | |
7 | #include "imageio.h" |
8 | |
9 | #include "debug.h" |
10 | |
11 | #include <SDL.h> |
12 | #include <png.h> |
13 | #include <cassert> |
14 | |
15 | |
16 | SDL_Surface *loadPNG(const std::string &path) { |
17 | // Declare these with function scope and initialize them to NULL, |
18 | // so we can use a single cleanup block at the end of the function. |
19 | SDL_Surface *surface = NULL; |
20 | FILE *fp = NULL; |
21 | png_structp png = NULL; |
22 | png_infop info = NULL; |
23 | |
24 | // Create and initialize the top-level libpng struct. |
25 | png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); |
26 | if (!png) goto cleanup; |
27 | // Create and initialize the image information struct. |
28 | info = png_create_info_struct(png); |
29 | if (!info) goto cleanup; |
30 | // Setup error handling for errors detected by libpng. |
31 | if (setjmp(png_jmpbuf(png))) { |
32 | // Note: This gets executed when an error occurs. |
33 | if (surface) { |
34 | SDL_FreeSurface(surface); |
35 | surface = NULL; |
36 | } |
37 | goto cleanup; |
38 | } |
39 | |
40 | // Open input file. |
41 | fp = fopen(path.c_str(), "rb"); |
42 | if (!fp) goto cleanup; |
43 | // Set up the input control if you are using standard C streams. |
44 | png_init_io(png, fp); |
45 | |
46 | // The call to png_read_info() gives us all of the information from the |
47 | // PNG file before the first IDAT (image data chunk). |
48 | png_read_info(png, info); |
49 | png_uint_32 width, height; |
50 | int bitDepth, colorType; |
51 | png_get_IHDR( |
52 | png, info, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL); |
53 | |
54 | // Select ARGB pixel format: |
55 | // (ARGB is the native pixel format for the JZ47xx frame buffer in 24bpp) |
56 | // - strip 16 bit/color files down to 8 bits/color |
57 | png_set_strip_16(png); |
58 | // - convert 1/2/4 bpp to 8 bpp |
59 | png_set_packing(png); |
60 | // - expand paletted images to RGB |
61 | // - expand grayscale images of less than 8-bit depth to 8-bit depth |
62 | // - expand tRNS chunks to alpha channels |
63 | png_set_expand(png); |
64 | // - convert grayscale to RGB |
65 | png_set_gray_to_rgb(png); |
66 | // - add alpha channel |
67 | png_set_add_alpha(png, 0xFF, PNG_FILLER_AFTER); |
68 | // - convert RGBA to ARGB |
69 | if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { |
70 | png_set_swap_alpha(png); |
71 | } else { |
72 | png_set_bgr(png); // BGRA in memory becomes ARGB in register |
73 | } |
74 | |
75 | // Update the image info to the post-conversion state. |
76 | png_read_update_info(png, info); |
77 | png_get_IHDR( |
78 | png, info, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL); |
79 | assert(bitDepth == 8); |
80 | assert(colorType == PNG_COLOR_TYPE_RGB_ALPHA); |
81 | |
82 | // Refuse to load outrageously large images. |
83 | if (width > 65536) { |
84 | WARNING("Refusing to load image because it is too wide\n"); |
85 | goto cleanup; |
86 | } |
87 | if (height > 2048) { |
88 | WARNING("Refusing to load image because it is too high\n"); |
89 | goto cleanup; |
90 | } |
91 | |
92 | // Allocate ARGB surface to hold the image. |
93 | surface = SDL_CreateRGBSurface( |
94 | SDL_SWSURFACE | SDL_SRCALPHA, width, height, 32, |
95 | 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 |
96 | ); |
97 | if (!surface) { |
98 | // Failed to create surface, probably out of memory. |
99 | goto cleanup; |
100 | } |
101 | |
102 | // Compute row pointers. |
103 | png_bytep rowPointers[height]; |
104 | for (png_uint_32 y = 0; y < height; y++) { |
105 | rowPointers[y] = |
106 | static_cast<png_bytep>(surface->pixels) + y * surface->pitch; |
107 | } |
108 | |
109 | // Read the entire image in one go. |
110 | png_read_image(png, rowPointers); |
111 | |
112 | // Read rest of file, and get additional chunks in the info struct. |
113 | // Note: We got all we need, so skip this step. |
114 | //png_read_end(png, info); |
115 | |
116 | cleanup: |
117 | // Clean up. |
118 | png_destroy_read_struct(&png, &info, NULL); |
119 | if (fp) fclose(fp); |
120 | |
121 | return surface; |
122 | } |
123 |
Branches:
install_locations
master
opkrun
packages