iPXE
png.c File Reference

Portable Network Graphics (PNG) format. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/umalloc.h>
#include <ipxe/pixbuf.h>
#include <ipxe/deflate.h>
#include <ipxe/png.h>

Go to the source code of this file.

Data Structures

struct  png_context
 PNG context. More...
struct  png_interlace
 A PNG interlace pass. More...
struct  png_filter
 A PNG filter. More...
struct  png_chunk_handler
 A PNG chunk handler. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static const char * png_type_name (uint32_t type)
 Transcribe PNG chunk type name (for debugging).
static void png_interlace (struct png_context *png, unsigned int pass, struct png_interlace *interlace)
 Calculate PNG interlace pass parameters.
static unsigned int png_pixel_len (struct png_context *png)
 Calculate PNG pixel length.
static size_t png_scanline_len (struct png_context *png, struct png_interlace *interlace)
 Calculate PNG scanline length.
static int png_image_header (struct image *image, struct png_context *png, size_t len)
 Handle PNG image header chunk.
static int png_palette (struct image *image, struct png_context *png, size_t len)
 Handle PNG palette chunk.
static int png_image_data (struct image *image, struct png_context *png, size_t len)
 Handle PNG image data chunk.
static unsigned int png_unfilter_none (unsigned int current, unsigned int left __unused, unsigned int above __unused, unsigned int above_left __unused)
 Unfilter byte using the "None" filter.
static unsigned int png_unfilter_sub (unsigned int current, unsigned int left, unsigned int above __unused, unsigned int above_left __unused)
 Unfilter byte using the "Sub" filter.
static unsigned int png_unfilter_up (unsigned int current, unsigned int left __unused, unsigned int above, unsigned int above_left __unused)
 Unfilter byte using the "Up" filter.
static unsigned int png_unfilter_average (unsigned int current, unsigned int left, unsigned int above, unsigned int above_left __unused)
 Unfilter byte using the "Average" filter.
static unsigned int png_paeth_predictor (unsigned int a, unsigned int b, unsigned int c)
 Paeth predictor function (defined in RFC 2083).
static unsigned int png_unfilter_paeth (unsigned int current, unsigned int left, unsigned int above, unsigned int above_left)
 Unfilter byte using the "Paeth" filter.
static int png_unfilter_pass (struct image *image, struct png_context *png, struct png_interlace *interlace)
 Unfilter one interlace pass of PNG raw data.
static int png_unfilter (struct image *image, struct png_context *png)
 Unfilter PNG raw data.
static unsigned int png_pixel (unsigned int raw, unsigned int alpha, unsigned int max)
 Calculate PNG pixel component value.
static void png_pixels_pass (struct image *image, struct png_context *png, struct png_interlace *interlace)
 Fill one interlace pass of PNG pixels.
static void png_pixels (struct image *image, struct png_context *png)
 Fill PNG pixels.
static int png_image_end (struct image *image, struct png_context *png, size_t len)
 Handle PNG image end chunk.
static int png_chunk (struct image *image, struct png_context *png, uint32_t type, size_t len)
 Handle PNG chunk.
static int png_pixbuf (struct image *image, struct pixel_buffer **pixbuf)
 Convert PNG image to pixel buffer.
static int png_probe (struct image *image)
 Probe PNG image.
struct image_type png_image_type __image_type (PROBE_NORMAL)
 PNG image type.

Variables

static struct png_signature png_signature = PNG_SIGNATURE
 PNG file signature.
static uint8_t png_interlace_passes []
 Number of interlacing passes.
static struct png_filter png_filters []
 PNG filter types.
static struct png_chunk_handler png_chunk_handlers []
 PNG chunk handlers.

Detailed Description

Portable Network Graphics (PNG) format.

The PNG format is defined in RFC 2083.

Definition in file png.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ png_type_name()

const char * png_type_name ( uint32_t type)
static

Transcribe PNG chunk type name (for debugging).

Parameters
typeChunk type
Return values
nameChunk type name

Definition at line 102 of file png.c.

102 {
103 static union {
105 char name[ sizeof ( uint32_t ) + 1 /* NUL */ ];
106 } u;
107
108 u.type = type;
109 return u.name;
110}
unsigned int uint32_t
Definition stdint.h:12
const char * name
Definition ath9k_hw.c:1986
union @104331263140136355135267063077374276003064103115 u
uint32_t type
Operating system type.
Definition ena.h:1

References name, type, and u.

Referenced by png_chunk().

◆ png_interlace()

void png_interlace ( struct png_context * png,
unsigned int pass,
struct png_interlace * interlace )
static

Calculate PNG interlace pass parameters.

Parameters
pngPNG context
passPass number (0=first pass)
interlaceInterlace pass to fill in

Definition at line 119 of file png.c.

120 {
121 unsigned int grid_width_log2;
122 unsigned int grid_height_log2;
123 unsigned int x_indent;
124 unsigned int y_indent;
125 unsigned int x_stride_log2;
126 unsigned int y_stride_log2;
127 unsigned int x_stride;
128 unsigned int y_stride;
129 unsigned int width;
130 unsigned int height;
131
132 /* Sanity check */
133 assert ( png->passes > 0 );
134
135 /* Store pass number */
136 interlace->pass = pass;
137
138 /* Calculate interlace grid dimensions */
139 grid_width_log2 = ( png->passes / 2 );
140 grid_height_log2 = ( ( png->passes - 1 ) / 2 );
141
142 /* Calculate starting indents */
143 interlace->x_indent = x_indent =
144 ( ( pass & 1 ) ?
145 ( 1 << ( grid_width_log2 - ( pass / 2 ) - 1 ) ) : 0 );
146 interlace->y_indent = y_indent =
147 ( ( pass && ! ( pass & 1 ) ) ?
148 ( 1 << ( grid_height_log2 - ( ( pass - 1 ) / 2 ) - 1 ) ) : 0);
149
150 /* Calculate strides */
151 x_stride_log2 = ( grid_width_log2 - ( pass / 2 ) );
152 y_stride_log2 =
153 ( grid_height_log2 - ( pass ? ( ( pass - 1 ) / 2 ) : 0 ) );
154 interlace->x_stride = x_stride = ( 1 << x_stride_log2 );
155 interlace->y_stride = y_stride = ( 1 << y_stride_log2 );
156
157 /* Calculate pass dimensions */
158 width = png->pixbuf->width;
159 height = png->pixbuf->height;
160 interlace->width =
161 ( ( width - x_indent + x_stride - 1 ) >> x_stride_log2 );
162 interlace->height =
163 ( ( height - y_indent + y_stride - 1 ) >> y_stride_log2 );
164}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
unsigned int height
Height.
Definition pixbuf.h:23
unsigned int width
Width.
Definition pixbuf.h:21
struct pixel_buffer * pixbuf
Pixel buffer.
Definition png.c:50
unsigned int passes
Number of interlace passes.
Definition png.c:59
unsigned int x_stride
X stride.
Definition png.c:78
unsigned int height
Height.
Definition png.c:84
unsigned int width
Width.
Definition png.c:82
unsigned int y_stride
Y stride.
Definition png.c:80
unsigned int y_indent
Y starting indent.
Definition png.c:76
unsigned int x_indent
X starting indent.
Definition png.c:74
unsigned int pass
Pass number.
Definition png.c:72

References assert, pixel_buffer::height, png_interlace::height, png_interlace::pass, png_context::passes, png_context::pixbuf, pixel_buffer::width, png_interlace::width, png_interlace::x_indent, png_interlace::x_stride, png_interlace::y_indent, and png_interlace::y_stride.

Referenced by png_image_header(), png_pixels(), and png_unfilter().

◆ png_pixel_len()

unsigned int png_pixel_len ( struct png_context * png)
static

Calculate PNG pixel length.

Parameters
pngPNG context
Return values
pixel_lenPixel length

Definition at line 172 of file png.c.

172 {
173
174 return ( ( ( png->channels * png->depth ) + 7 ) / 8 );
175}
unsigned int channels
Number of channels.
Definition png.c:57
unsigned int depth
Bit depth.
Definition png.c:53

References png_context::channels, and png_context::depth.

Referenced by png_unfilter_pass().

◆ png_scanline_len()

size_t png_scanline_len ( struct png_context * png,
struct png_interlace * interlace )
static

Calculate PNG scanline length.

Parameters
pngPNG context
interlaceInterlace pass
Return values
scanline_lenScanline length (including filter byte), or 0 on error

Definition at line 184 of file png.c.

185 {
186 size_t bits;
187
188 /* Calculate bit count and check for overflow */
189 bits = ( interlace->width * png->channels * png->depth );
190 assert ( png->channels != 0 );
191 assert ( png->depth != 0 );
192 if ( ( ( bits / png->channels ) / png->depth ) != interlace->width )
193 return 0;
194
195 /* Calculate byte length (cannot overflow) */
196 return ( 1 /* Filter byte */ + ( bits / 8 ) + ( !! ( bits & 7 ) ) );
197}
static volatile void * bits
Definition bitops.h:28

References assert, bits, png_context::channels, png_context::depth, and png_interlace::width.

Referenced by png_image_header(), and png_unfilter_pass().

◆ png_image_header()

int png_image_header ( struct image * image,
struct png_context * png,
size_t len )
static

Handle PNG image header chunk.

Parameters
imagePNG image
pngPNG context
lenChunk length
Return values
rcReturn status code

Definition at line 207 of file png.c.

208 {
209 const struct png_image_header *ihdr;
210 struct png_interlace interlace;
211 size_t scanline_len;
212 size_t pass_len;
213 unsigned int pass;
214
215 /* Sanity check */
216 if ( len != sizeof ( *ihdr ) ) {
217 DBGC ( image, "PNG %s invalid IHDR length %zd\n",
218 image->name, len );
219 return -EINVAL;
220 }
221 if ( png->pixbuf ) {
222 DBGC ( image, "PNG %s duplicate IHDR\n", image->name );
223 return -EINVAL;
224 }
225
226 /* Extract image header */
227 ihdr = ( image->data + png->offset );
228 DBGC ( image, "PNG %s %dx%d depth %d type %d compression %d filter %d "
229 "interlace %d\n", image->name, ntohl ( ihdr->width ),
230 ntohl ( ihdr->height ), ihdr->depth, ihdr->colour_type,
231 ihdr->compression, ihdr->filter, ihdr->interlace );
232
233 /* Sanity checks */
234 if ( ihdr->compression >= PNG_COMPRESSION_UNKNOWN ) {
235 DBGC ( image, "PNG %s unknown compression method %d\n",
236 image->name, ihdr->compression );
237 return -ENOTSUP;
238 }
239 if ( ihdr->filter >= PNG_FILTER_UNKNOWN ) {
240 DBGC ( image, "PNG %s unknown filter method %d\n",
241 image->name, ihdr->filter );
242 return -ENOTSUP;
243 }
244 if ( ihdr->interlace >= PNG_INTERLACE_UNKNOWN ) {
245 DBGC ( image, "PNG %s unknown interlace method %d\n",
246 image->name, ihdr->interlace );
247 return -ENOTSUP;
248 }
249
250 /* Allocate pixel buffer */
251 png->pixbuf = alloc_pixbuf ( ntohl ( ihdr->width ),
252 ntohl ( ihdr->height ) );
253 if ( ! png->pixbuf ) {
254 DBGC ( image, "PNG %s could not allocate pixel buffer\n",
255 image->name );
256 return -ENOMEM;
257 }
258
259 /* Extract bit depth */
260 png->depth = ihdr->depth;
261 if ( ( png->depth == 0 ) ||
262 ( ( png->depth & ( png->depth - 1 ) ) != 0 ) ) {
263 DBGC ( image, "PNG %s invalid depth %d\n",
264 image->name, png->depth );
265 return -EINVAL;
266 }
267
268 /* Calculate number of channels */
269 png->colour_type = ihdr->colour_type;
270 png->channels = 1;
271 if ( ! ( ihdr->colour_type & PNG_COLOUR_TYPE_PALETTE ) ) {
272 if ( ihdr->colour_type & PNG_COLOUR_TYPE_RGB )
273 png->channels += 2;
275 png->channels += 1;
276 }
277
278 /* Calculate number of interlace passes */
280
281 /* Calculate length of raw data buffer */
282 for ( pass = 0 ; pass < png->passes ; pass++ ) {
283 png_interlace ( png, pass, &interlace );
284 if ( interlace.width == 0 )
285 continue;
286 scanline_len = png_scanline_len ( png, &interlace );
287 if ( ! scanline_len )
288 return -ERANGE;
289 pass_len = ( interlace.height * scanline_len );
290 if ( ( pass_len / scanline_len ) != interlace.height )
291 return -ERANGE;
292 png->raw.len += pass_len;
293 if ( png->raw.len < pass_len )
294 return -ERANGE;
295 }
296
297 /* Allocate raw data buffer */
298 png->raw.data = umalloc ( png->raw.len );
299 if ( ! png->raw.data ) {
300 DBGC ( image, "PNG %s could not allocate data buffer\n",
301 image->name );
302 return -ENOMEM;
303 }
304
305 return 0;
306}
ring len
Length.
Definition dwmac.h:226
#define DBGC(...)
Definition compiler.h:530
#define EINVAL
Invalid argument.
Definition errno.h:472
#define ENOMEM
Not enough space.
Definition errno.h:578
#define ENOTSUP
Operation not supported.
Definition errno.h:633
#define ERANGE
Result too large.
Definition errno.h:683
#define ntohl(value)
Definition byteswap.h:135
static __always_inline void * umalloc(size_t size)
Allocate external memory.
Definition umalloc.h:57
struct pixel_buffer * alloc_pixbuf(unsigned int width, unsigned int height)
Allocate pixel buffer.
Definition pixbuf.c:60
static uint8_t png_interlace_passes[]
Number of interlacing passes.
Definition png.c:91
static size_t png_scanline_len(struct png_context *png, struct png_interlace *interlace)
Calculate PNG scanline length.
Definition png.c:184
static void png_interlace(struct png_context *png, unsigned int pass, struct png_interlace *interlace)
Calculate PNG interlace pass parameters.
Definition png.c:119
@ PNG_FILTER_UNKNOWN
First unknown filter method.
Definition png.h:123
@ PNG_INTERLACE_UNKNOWN
First unknown interlace method.
Definition png.h:133
@ PNG_COLOUR_TYPE_ALPHA
Alpha channel is used.
Definition png.h:104
@ PNG_COLOUR_TYPE_PALETTE
Palette is used.
Definition png.h:100
@ PNG_COLOUR_TYPE_RGB
RGB colour is used.
Definition png.h:102
@ PNG_COMPRESSION_UNKNOWN
First unknown compression method.
Definition png.h:115
void * data
Data.
Definition deflate.h:248
size_t len
Length of data.
Definition deflate.h:252
An executable image.
Definition image.h:24
const void * data
Read-only data.
Definition image.h:51
char * name
Name.
Definition image.h:38
size_t offset
Offset within image.
Definition png.c:47
struct deflate_chunk raw
Decompression buffer for raw PNG data.
Definition png.c:64
unsigned int colour_type
Colour type.
Definition png.c:55
A PNG image header.
Definition png.h:80
uint8_t filter
Filter method.
Definition png.h:92
uint8_t colour_type
Colour type.
Definition png.h:88
uint8_t depth
Bit depth.
Definition png.h:86
uint8_t compression
Compression method.
Definition png.h:90
uint32_t height
Height.
Definition png.h:84
uint32_t width
Width.
Definition png.h:82
uint8_t interlace
Interlace method.
Definition png.h:94
A PNG interlace pass.
Definition png.c:70

References alloc_pixbuf(), png_context::channels, png_context::colour_type, png_image_header::colour_type, png_image_header::compression, deflate_chunk::data, image::data, DBGC, png_context::depth, png_image_header::depth, EINVAL, ENOMEM, ENOTSUP, ERANGE, png_image_header::filter, png_image_header::height, png_interlace::height, png_image_header::interlace, deflate_chunk::len, len, image::name, ntohl, png_context::offset, png_interlace::pass, png_context::passes, png_context::pixbuf, PNG_COLOUR_TYPE_ALPHA, PNG_COLOUR_TYPE_PALETTE, PNG_COLOUR_TYPE_RGB, PNG_COMPRESSION_UNKNOWN, PNG_FILTER_UNKNOWN, png_interlace(), png_interlace_passes, PNG_INTERLACE_UNKNOWN, png_scanline_len(), png_context::raw, umalloc(), png_image_header::width, and png_interlace::width.

◆ png_palette()

int png_palette ( struct image * image,
struct png_context * png,
size_t len )
static

Handle PNG palette chunk.

Parameters
imagePNG image
pngPNG context
lenChunk length
Return values
rcReturn status code

Definition at line 316 of file png.c.

317 {
318 const struct png_palette_entry *palette;
319 unsigned int i;
320
321 /* Populate palette */
322 palette = ( image->data + png->offset );
323 for ( i = 0 ; i < ( sizeof ( png->palette ) /
324 sizeof ( png->palette[0] ) ) ; i++ ) {
325
326 /* Stop when we run out of palette data */
327 if ( len < sizeof ( *palette ) )
328 break;
329
330 /* Extract palette entry */
331 png->palette[i] = ( ( palette->red << 16 ) |
332 ( palette->green << 8 ) |
333 ( palette->blue << 0 ) );
334 DBGC2 ( image, "PNG %s palette entry %d is %#06x\n",
335 image->name, i, png->palette[i] );
336
337 /* Move to next entry */
338 palette++;
339 len -= sizeof ( *palette );
340 }
341
342 return 0;
343}
#define DBGC2(...)
Definition compiler.h:547
uint32_t palette[PNG_PALETTE_COUNT]
Palette, in iPXE's pixel buffer format.
Definition png.c:61
A PNG palette entry.
Definition png.h:140
uint8_t red
Red.
Definition png.h:142
uint8_t green
Green.
Definition png.h:144
uint8_t blue
Blue.
Definition png.h:146

References png_palette_entry::blue, image::data, DBGC2, png_palette_entry::green, len, image::name, png_context::offset, png_context::palette, and png_palette_entry::red.

◆ png_image_data()

int png_image_data ( struct image * image,
struct png_context * png,
size_t len )
static

Handle PNG image data chunk.

Parameters
imagePNG image
pngPNG context
lenChunk length
Return values
rcReturn status code

Definition at line 353 of file png.c.

354 {
355 int rc;
356
357 /* Deflate this chunk */
358 if ( ( rc = deflate_inflate ( &png->deflate,
359 ( image->data + png->offset ),
360 len, &png->raw ) ) != 0 ) {
361 DBGC ( image, "PNG %s could not decompress: %s\n",
362 image->name, strerror ( rc ) );
363 return rc;
364 }
365
366 return 0;
367}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
int deflate_inflate(struct deflate *deflate, const void *data, size_t len, struct deflate_chunk *out)
Inflate compressed data.
Definition deflate.c:484
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
struct deflate deflate
Decompressor.
Definition png.c:66

References image::data, DBGC, png_context::deflate, deflate_inflate(), len, image::name, png_context::offset, png_context::raw, rc, and strerror().

◆ png_unfilter_none()

unsigned int png_unfilter_none ( unsigned int current,
unsigned int left __unused,
unsigned int above __unused,
unsigned int above_left __unused )
static

Unfilter byte using the "None" filter.

Parameters
currentFiltered current byte
leftUnfiltered left byte
aboveUnfiltered above byte
above_leftUnfiltered above-left byte
Return values
currentUnfiltered current byte

Definition at line 378 of file png.c.

381 {
382
383 return current;
384}

References __unused.

◆ png_unfilter_sub()

unsigned int png_unfilter_sub ( unsigned int current,
unsigned int left,
unsigned int above __unused,
unsigned int above_left __unused )
static

Unfilter byte using the "Sub" filter.

Parameters
currentFiltered current byte
leftUnfiltered left byte
aboveUnfiltered above byte
above_leftUnfiltered above-left byte
Return values
currentUnfiltered current byte

Definition at line 395 of file png.c.

398 {
399
400 return ( current + left );
401}

References __unused.

◆ png_unfilter_up()

unsigned int png_unfilter_up ( unsigned int current,
unsigned int left __unused,
unsigned int above,
unsigned int above_left __unused )
static

Unfilter byte using the "Up" filter.

Parameters
currentFiltered current byte
leftUnfiltered left byte
aboveUnfiltered above byte
above_leftUnfiltered above-left byte
Return values
currentUnfiltered current byte

Definition at line 412 of file png.c.

415 {
416
417 return ( current + above );
418}

References __unused.

◆ png_unfilter_average()

unsigned int png_unfilter_average ( unsigned int current,
unsigned int left,
unsigned int above,
unsigned int above_left __unused )
static

Unfilter byte using the "Average" filter.

Parameters
currentFiltered current byte
leftUnfiltered left byte
aboveUnfiltered above byte
above_leftUnfiltered above-left byte
Return values
currentUnfiltered current byte

Definition at line 429 of file png.c.

432 {
433
434 return ( current + ( ( above + left ) >> 1 ) );
435}

References __unused.

◆ png_paeth_predictor()

unsigned int png_paeth_predictor ( unsigned int a,
unsigned int b,
unsigned int c )
static

Paeth predictor function (defined in RFC 2083).

Parameters
aPixel A
bPixel B
cPixel C
Return values
predictorPredictor pixel

Definition at line 445 of file png.c.

446 {
447 unsigned int p;
448 unsigned int pa;
449 unsigned int pb;
450 unsigned int pc;
451
452 /* Algorithm as defined in RFC 2083 section 6.6 */
453 p = ( a + b - c );
454 pa = abs ( p - a );
455 pb = abs ( p - b );
456 pc = abs ( p - c );
457 if ( ( pa <= pb ) && ( pa <= pc ) ) {
458 return a;
459 } else if ( pb <= pc ) {
460 return b;
461 } else {
462 return c;
463 }
464}
#define abs(x)
Definition ath.h:46

References abs.

Referenced by png_unfilter_paeth().

◆ png_unfilter_paeth()

unsigned int png_unfilter_paeth ( unsigned int current,
unsigned int left,
unsigned int above,
unsigned int above_left )
static

Unfilter byte using the "Paeth" filter.

Parameters
currentFiltered current byte
above_leftUnfiltered above-left byte
aboveUnfiltered above byte
leftUnfiltered left byte
Return values
currentUnfiltered current byte

Definition at line 475 of file png.c.

478 {
479
480 return ( current + png_paeth_predictor ( left, above, above_left ) );
481}
static unsigned int png_paeth_predictor(unsigned int a, unsigned int b, unsigned int c)
Paeth predictor function (defined in RFC 2083).
Definition png.c:445

References png_paeth_predictor().

◆ png_unfilter_pass()

int png_unfilter_pass ( struct image * image,
struct png_context * png,
struct png_interlace * interlace )
static

Unfilter one interlace pass of PNG raw data.

Parameters
imagePNG image
pngPNG context
interlaceInterlace pass
Return values
rcReturn status code

This routine may assume that it is impossible to overrun the raw data buffer, since the size is determined by the image dimensions.

Definition at line 520 of file png.c.

521 {
522 size_t pixel_len = png_pixel_len ( png );
523 size_t scanline_len = png_scanline_len ( png, interlace );
524 uint8_t *data = ( png->raw.data + png->raw.offset );
525 struct png_filter *filter;
526 unsigned int scanline;
527 unsigned int byte;
528 unsigned int filter_type;
529 unsigned int left;
530 unsigned int above;
531 unsigned int above_left;
532
533 /* On the first scanline of a pass, above bytes are assumed to
534 * be zero.
535 */
536 above = 0;
537
538 /* Iterate over each scanline in turn */
539 for ( scanline = 0 ; scanline < interlace->height ; scanline++ ) {
540
541 /* Extract filter byte and determine filter type */
542 filter_type = *(data++);
543 if ( filter_type >= ( sizeof ( png_filters ) /
544 sizeof ( png_filters[0] ) ) ) {
545 DBGC ( image, "PNG %s unknown filter type %d\n",
546 image->name, filter_type );
547 return -ENOTSUP;
548 }
549 filter = &png_filters[filter_type];
550 assert ( filter->unfilter != NULL );
551 DBGC2 ( image, "PNG %s pass %d scanline %d filter type %d\n",
552 image->name, interlace->pass, scanline, filter_type );
553
554 /* At the start of a line, both above-left and left
555 * bytes are taken to be zero.
556 */
557 left = 0;
558 above_left = 0;
559
560 /* Iterate over each byte (not pixel) in turn */
561 for ( byte = 0 ; byte < ( scanline_len - 1 ) ; byte++ ) {
562
563 /* Extract predictor bytes, if applicable */
564 if ( byte >= pixel_len )
565 left = *( data - pixel_len );
566 if ( scanline > 0 )
567 above = *( data - scanline_len );
568 if ( ( scanline > 0 ) && ( byte >= pixel_len ) ) {
569 above_left = *( data - scanline_len -
570 pixel_len );
571 }
572
573 /* Unfilter current byte */
574 *data = filter->unfilter ( *data, left, above,
575 above_left );
576 data++;
577 }
578 }
579
580 /* Update offset */
581 png->raw.offset = ( ( ( void * ) data ) - png->raw.data );
582
583 return 0;
584}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
unsigned char uint8_t
Definition stdint.h:10
uint8_t data[48]
Additional event data.
Definition ena.h:11
static unsigned int png_pixel_len(struct png_context *png)
Calculate PNG pixel length.
Definition png.c:172
static struct png_filter png_filters[]
PNG filter types.
Definition png.c:501
UINT8_t filter
Receive packet filter.
Definition pxe_api.h:11
unsigned char byte
Definition smc9000.h:38
size_t offset
Current offset.
Definition deflate.h:250
A PNG filter.
Definition png.c:484

References assert, data, deflate_chunk::data, DBGC, DBGC2, ENOTSUP, filter, png_interlace::height, image::name, NULL, deflate_chunk::offset, png_interlace::pass, png_filters, png_pixel_len(), png_scanline_len(), and png_context::raw.

Referenced by png_unfilter().

◆ png_unfilter()

int png_unfilter ( struct image * image,
struct png_context * png )
static

Unfilter PNG raw data.

Parameters
imagePNG image
pngPNG context
Return values
rcReturn status code

This routine may assume that it is impossible to overrun the raw data buffer, since the size is determined by the image dimensions.

Definition at line 596 of file png.c.

596 {
597 struct png_interlace interlace;
598 unsigned int pass;
599 int rc;
600
601 /* Process each interlace pass */
602 png->raw.offset = 0;
603 for ( pass = 0 ; pass < png->passes ; pass++ ) {
604
605 /* Calculate interlace pass parameters */
606 png_interlace ( png, pass, &interlace );
607
608 /* Skip zero-width rows (which have no filter bytes) */
609 if ( interlace.width == 0 )
610 continue;
611
612 /* Unfilter this pass */
613 if ( ( rc = png_unfilter_pass ( image, png,
614 &interlace ) ) != 0 )
615 return rc;
616 }
617 assert ( png->raw.offset == png->raw.len );
618
619 return 0;
620}
static int png_unfilter_pass(struct image *image, struct png_context *png, struct png_interlace *interlace)
Unfilter one interlace pass of PNG raw data.
Definition png.c:520

References assert, deflate_chunk::len, deflate_chunk::offset, png_interlace::pass, png_context::passes, png_interlace(), png_unfilter_pass(), png_context::raw, rc, and png_interlace::width.

Referenced by png_image_end().

◆ png_pixel()

unsigned int png_pixel ( unsigned int raw,
unsigned int alpha,
unsigned int max )
inlinestatic

Calculate PNG pixel component value.

Parameters
rawRaw component value
alphaAlpha value
maxMaximum raw/alpha value
Return values
valueComponent value in range 0-255

Definition at line 630 of file png.c.

631 {
632
633 /* The basic calculation is 255*(raw/max)*(value/max). We use
634 * fixed-point arithmetic (scaling up to the maximum range for
635 * a 32-bit integer), in order to get the same results for
636 * alpha blending as the test cases (produced using
637 * ImageMagick).
638 */
639 return ( ( ( ( ( 0xff00 * raw * alpha ) / max ) / max ) + 0x80 ) >> 8 );
640}
__be32 raw[7]
Definition CIB_PRM.h:0
#define max(x, y)
Definition ath.h:41

References max, and raw.

Referenced by png_pixels_pass().

◆ png_pixels_pass()

void png_pixels_pass ( struct image * image,
struct png_context * png,
struct png_interlace * interlace )
static

Fill one interlace pass of PNG pixels.

Parameters
imagePNG image
pngPNG context
interlaceInterlace pass

This routine may assume that it is impossible to overrun either the raw data buffer or the pixel buffer, since the sizes of both are determined by the image dimensions.

Definition at line 653 of file png.c.

655 {
657 int is_indexed = ( png->colour_type & PNG_COLOUR_TYPE_PALETTE );
658 int is_rgb = ( png->colour_type & PNG_COLOUR_TYPE_RGB );
659 int has_alpha = ( png->colour_type & PNG_COLOUR_TYPE_ALPHA );
660 const uint8_t *data = ( png->raw.data + png->raw.offset );
661 size_t data_stride;
662 unsigned int pixbuf_y_index;
663 unsigned int pixbuf_index;
664 unsigned int pixbuf_x_stride;
665 unsigned int pixbuf_y_stride;
666 unsigned int y;
667 unsigned int x;
668 unsigned int c;
669 unsigned int bits;
670 unsigned int depth;
671 unsigned int max;
672 unsigned int alpha;
673 unsigned int raw;
674 unsigned int value;
675 uint8_t current = 0;
676 uint32_t pixel;
677
678 /* We only ever use the top byte of 16-bit pixels. Model this
679 * as a bit depth of 8 with a stride of more than one.
680 */
681 depth = png->depth;
682 data_stride = ( ( depth + 7 ) / 8 );
683 if ( depth > 8 )
684 depth = 8;
685 max = ( ( 1 << depth ) - 1 );
686
687 /* Calculate pixel buffer offset and strides */
688 pixbuf_y_index = ( ( ( interlace->y_indent * png->pixbuf->width ) +
689 interlace->x_indent ) );
690 pixbuf_x_stride = interlace->x_stride;
691 pixbuf_y_stride = ( interlace->y_stride * png->pixbuf->width );
692 DBGC2 ( image, "PNG %s pass %d %dx%d at (%d,%d) stride (%d,%d)\n",
693 image->name, interlace->pass, interlace->width,
694 interlace->height, interlace->x_indent, interlace->y_indent,
695 interlace->x_stride, interlace->y_stride );
696
697 /* Iterate over each scanline in turn */
698 for ( y = 0 ; y < interlace->height ; y++ ) {
699
700 /* Skip filter byte */
701 data++;
702
703 /* Iterate over each pixel in turn */
704 bits = depth;
705 pixbuf_index = pixbuf_y_index;
706 for ( x = 0 ; x < interlace->width ; x++ ) {
707
708 /* Extract sample value */
709 for ( c = 0 ; c < png->channels ; c++ ) {
710
711 /* Get sample value into high bits of current */
712 current <<= depth;
713 bits -= depth;
714 if ( ! bits ) {
715 current = *data;
716 data += data_stride;
717 bits = 8;
718 }
719
720 /* Extract sample value */
721 channel[c] = ( current >> ( 8 - depth ) );
722 }
723
724 /* Convert to native pixel format */
725 if ( is_indexed ) {
726
727 /* Indexed */
728 pixel = png->palette[channel[0]];
729
730 } else {
731
732 /* Determine alpha value */
733 alpha = ( has_alpha ?
734 channel[ png->channels - 1 ] : max );
735
736 /* Convert to RGB value */
737 pixel = 0;
738 for ( c = 0 ; c < 3 ; c++ ) {
739 raw = channel[ is_rgb ? c : 0 ];
740 value = png_pixel ( raw, alpha, max );
741 assert ( value <= 255 );
742 pixel = ( ( pixel << 8 ) | value );
743 }
744 }
745
746 /* Store pixel */
747 png->pixbuf->data[pixbuf_index] = pixel;
748 pixbuf_index += pixbuf_x_stride;
749 }
750
751 /* Move to next output row */
752 pixbuf_y_index += pixbuf_y_stride;
753 }
754
755 /* Update offset */
756 png->raw.offset = ( ( ( const void * ) data ) - png->raw.data );
757}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
uint32_t channel
RNDIS channel.
Definition netvsc.h:3
static unsigned int unsigned int y
Definition pixbuf.h:63
static unsigned int x
Definition pixbuf.h:63
static unsigned int png_pixel(unsigned int raw, unsigned int alpha, unsigned int max)
Calculate PNG pixel component value.
Definition png.c:630
uint32_t * data
32-bit (8:8:8:8) xRGB pixel data, in host-endian order
Definition pixbuf.h:25

References assert, bits, channel, png_context::channels, png_context::colour_type, data, deflate_chunk::data, pixel_buffer::data, DBGC2, png_context::depth, png_interlace::height, max, image::name, deflate_chunk::offset, png_context::palette, png_interlace::pass, png_context::pixbuf, PNG_COLOUR_TYPE_ALPHA, PNG_COLOUR_TYPE_PALETTE, PNG_COLOUR_TYPE_RGB, png_pixel(), png_context::raw, raw, value, pixel_buffer::width, png_interlace::width, x, png_interlace::x_indent, png_interlace::x_stride, y, png_interlace::y_indent, and png_interlace::y_stride.

Referenced by png_pixels().

◆ png_pixels()

void png_pixels ( struct image * image,
struct png_context * png )
static

Fill PNG pixels.

Parameters
imagePNG image
pngPNG context

This routine may assume that it is impossible to overrun either the raw data buffer or the pixel buffer, since the sizes of both are determined by the image dimensions.

Definition at line 769 of file png.c.

769 {
770 struct png_interlace interlace;
771 unsigned int pass;
772
773 /* Process each interlace pass */
774 png->raw.offset = 0;
775 for ( pass = 0 ; pass < png->passes ; pass++ ) {
776
777 /* Calculate interlace pass parameters */
778 png_interlace ( png, pass, &interlace );
779
780 /* Skip zero-width rows (which have no filter bytes) */
781 if ( interlace.width == 0 )
782 continue;
783
784 /* Unfilter this pass */
785 png_pixels_pass ( image, png, &interlace );
786 }
787 assert ( png->raw.offset == png->raw.len );
788}
static void png_pixels_pass(struct image *image, struct png_context *png, struct png_interlace *interlace)
Fill one interlace pass of PNG pixels.
Definition png.c:653

References assert, deflate_chunk::len, deflate_chunk::offset, png_interlace::pass, png_context::passes, png_interlace(), png_pixels_pass(), png_context::raw, and png_interlace::width.

Referenced by png_image_end().

◆ png_image_end()

int png_image_end ( struct image * image,
struct png_context * png,
size_t len )
static

Handle PNG image end chunk.

Parameters
imagePNG image
pngPNG context
lenChunk length
Return values
rcReturn status code

Definition at line 798 of file png.c.

799 {
800 int rc;
801
802 /* Sanity checks */
803 if ( len != 0 ) {
804 DBGC ( image, "PNG %s invalid IEND length %zd\n",
805 image->name, len );
806 return -EINVAL;
807 }
808 if ( ! png->pixbuf ) {
809 DBGC ( image, "PNG %s missing pixel buffer (no IHDR?)\n",
810 image->name );
811 return -EINVAL;
812 }
813 if ( ! deflate_finished ( &png->deflate ) ) {
814 DBGC ( image, "PNG %s decompression not complete\n",
815 image->name );
816 return -EINVAL;
817 }
818 if ( png->raw.offset != png->raw.len ) {
819 DBGC ( image, "PNG %s incorrect decompressed length (expected "
820 "%zd, got %zd)\n", image->name, png->raw.len,
821 png->raw.offset );
822 return -EINVAL;
823 }
824
825 /* Unfilter raw data */
826 if ( ( rc = png_unfilter ( image, png ) ) != 0 )
827 return rc;
828
829 /* Fill pixel buffer */
830 png_pixels ( image, png );
831
832 return 0;
833}
static int deflate_finished(struct deflate *deflate)
Check if decompression has finished.
Definition deflate.h:278
static int png_unfilter(struct image *image, struct png_context *png)
Unfilter PNG raw data.
Definition png.c:596
static void png_pixels(struct image *image, struct png_context *png)
Fill PNG pixels.
Definition png.c:769

References DBGC, png_context::deflate, deflate_finished(), EINVAL, deflate_chunk::len, len, image::name, deflate_chunk::offset, png_context::pixbuf, png_pixels(), png_unfilter(), png_context::raw, and rc.

◆ png_chunk()

int png_chunk ( struct image * image,
struct png_context * png,
uint32_t type,
size_t len )
static

Handle PNG chunk.

Parameters
imagePNG image
pngPNG context
typeChunk type
lenChunk length
Return values
rcReturn status code

Definition at line 868 of file png.c.

869 {
870 struct png_chunk_handler *handler;
871 unsigned int i;
872
873 DBGC ( image, "PNG %s chunk type %s offset %zd length %zd\n",
874 image->name, png_type_name ( type ), png->offset, len );
875
876 /* Handle according to chunk type */
877 for ( i = 0 ; i < ( sizeof ( png_chunk_handlers ) /
878 sizeof ( png_chunk_handlers[0] ) ) ; i++ ) {
879 handler = &png_chunk_handlers[i];
880 if ( handler->type == type )
881 return handler->handle ( image, png, len );
882 }
883
884 /* Fail if unknown chunk type is critical */
885 if ( ! ( type & htonl ( PNG_CHUNK_ANCILLARY ) ) ) {
886 DBGC ( image, "PNG %s unknown critical chunk type %s\n",
888 return -ENOTSUP;
889 }
890
891 /* Ignore non-critical unknown chunk types */
892 return 0;
893}
#define htonl(value)
Definition byteswap.h:134
static struct png_chunk_handler png_chunk_handlers[]
PNG chunk handlers.
Definition png.c:852
static const char * png_type_name(uint32_t type)
Transcribe PNG chunk type name (for debugging).
Definition png.c:102
@ PNG_CHUNK_ANCILLARY
Chunk is ancillary.
Definition png.h:43
A PNG chunk handler.
Definition png.c:836
uint32_t type
Chunk type.
Definition png.c:838
int(* handle)(struct image *image, struct png_context *png, size_t len)
Handle chunk.
Definition png.c:847

References DBGC, ENOTSUP, png_chunk_handler::handle, htonl, len, image::name, png_context::offset, PNG_CHUNK_ANCILLARY, png_chunk_handlers, png_type_name(), png_chunk_handler::type, and type.

Referenced by png_pixbuf().

◆ png_pixbuf()

int png_pixbuf ( struct image * image,
struct pixel_buffer ** pixbuf )
static

Convert PNG image to pixel buffer.

Parameters
imagePNG image
pixbufPixel buffer to fill in
Return values
rcReturn status code

Definition at line 902 of file png.c.

902 {
903 struct png_context *png;
904 const struct png_chunk_header *header;
905 const struct png_chunk_footer *footer;
906 size_t remaining;
907 size_t chunk_len;
908 int rc;
909
910 /* Allocate and initialise context */
911 png = zalloc ( sizeof ( *png ) );
912 if ( ! png ) {
913 rc = -ENOMEM;
914 goto err_alloc;
915 }
916 png->offset = sizeof ( struct png_signature );
918
919 /* Process chunks */
920 do {
921
922 /* Extract chunk header */
923 remaining = ( image->len - png->offset );
924 if ( remaining < ( sizeof ( *header ) + sizeof ( *footer ) ) ){
925 DBGC ( image, "PNG %s truncated chunk header/footer "
926 "at offset %zd\n", image->name, png->offset );
927 rc = -EINVAL;
928 goto err_truncated;
929 }
930 header = ( image->data + png->offset );
931 png->offset += sizeof ( *header );
932
933 /* Validate chunk length */
934 chunk_len = ntohl ( header->len );
935 if ( chunk_len > ( remaining - sizeof ( *header ) -
936 sizeof ( *footer ) ) ) {
937 DBGC ( image, "PNG %s truncated chunk data at offset "
938 "%zd\n", image->name, png->offset );
939 rc = -EINVAL;
940 goto err_truncated;
941 }
942
943 /* Handle chunk */
944 if ( ( rc = png_chunk ( image, png, header->type,
945 chunk_len ) ) != 0 )
946 goto err_chunk;
947
948 /* Move to next chunk */
949 png->offset += ( chunk_len + sizeof ( *footer ) );
950
951 } while ( png->offset < image->len );
952
953 /* Check that we finished with an IEND chunk */
954 if ( header->type != htonl ( PNG_TYPE_IEND ) ) {
955 DBGC ( image, "PNG %s did not finish with IEND\n",
956 image->name );
957 rc = -EINVAL;
958 goto err_iend;
959 }
960
961 /* Return pixel buffer */
962 *pixbuf = pixbuf_get ( png->pixbuf );
963
964 /* Success */
965 rc = 0;
966
967 err_iend:
968 err_chunk:
969 err_truncated:
970 pixbuf_put ( png->pixbuf );
971 ufree ( png->raw.data );
972 free ( png );
973 err_alloc:
974 return rc;
975}
void deflate_init(struct deflate *deflate, enum deflate_format format)
Initialise decompressor.
Definition deflate.c:992
@ DEFLATE_ZLIB
ZLIB header and footer.
Definition deflate.h:21
struct ena_llq_option header
Header locations.
Definition ena.h:5
static __always_inline void ufree(void *ptr)
Free external memory.
Definition umalloc.h:68
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
static int png_chunk(struct image *image, struct png_context *png, uint32_t type, size_t len)
Handle PNG chunk.
Definition png.c:868
#define PNG_TYPE_IEND
PNG image end chunk type.
Definition png.h:176
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
size_t len
Length of raw file image.
Definition image.h:63
A PNG chunk header.
Definition png.h:27
PNG context.
Definition png.c:45
A PNG file signature.
Definition png.h:18

References deflate_chunk::data, image::data, DBGC, png_context::deflate, deflate_init(), DEFLATE_ZLIB, EINVAL, ENOMEM, free, header, htonl, image::len, image::name, ntohl, png_context::offset, png_context::pixbuf, png_chunk(), PNG_TYPE_IEND, png_context::raw, rc, ufree(), and zalloc().

Referenced by __image_type().

◆ png_probe()

int png_probe ( struct image * image)
static

Probe PNG image.

Parameters
imagePNG image
Return values
rcReturn status code

Definition at line 983 of file png.c.

983 {
984 const struct png_signature *signature;
985
986 /* Sanity check */
987 if ( image->len < sizeof ( *signature ) ) {
988 DBGC ( image, "PNG %s is too short\n", image->name );
989 return -ENOEXEC;
990 }
991
992 /* Check signature */
994 if ( memcmp ( signature, &png_signature, sizeof ( *signature ) ) != 0 ){
995 DBGC ( image, "PNG %s has invalid signature\n", image->name );
996 return -ENOEXEC;
997 }
998
999 return 0;
1000}
u8 signature
CPU signature.
Definition CIB_PRM.h:7
#define ENOEXEC
Exec format error.
Definition errno.h:563
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115

References image::data, DBGC, ENOEXEC, image::len, memcmp(), image::name, and signature.

Referenced by __image_type().

◆ __image_type()

struct image_type png_image_type __image_type ( PROBE_NORMAL )

PNG image type.

References __image_type, png_pixbuf(), png_probe(), and PROBE_NORMAL.

Variable Documentation

◆ png_signature

struct png_signature png_signature = PNG_SIGNATURE
static

PNG file signature.

Definition at line 88 of file png.c.

◆ png_interlace_passes

uint8_t png_interlace_passes[]
static
Initial value:
= {
}
@ PNG_INTERLACE_NONE
No interlacing.
Definition png.h:129
@ PNG_INTERLACE_ADAM7
Adam7 interlacing.
Definition png.h:131

Number of interlacing passes.

Definition at line 91 of file png.c.

91 {
94};

Referenced by png_image_header().

◆ png_filters

struct png_filter png_filters[]
static
Initial value:
= {
}
static unsigned int png_unfilter_average(unsigned int current, unsigned int left, unsigned int above, unsigned int above_left __unused)
Unfilter byte using the "Average" filter.
Definition png.c:429
static unsigned int png_unfilter_none(unsigned int current, unsigned int left __unused, unsigned int above __unused, unsigned int above_left __unused)
Unfilter byte using the "None" filter.
Definition png.c:378
static unsigned int png_unfilter_sub(unsigned int current, unsigned int left, unsigned int above __unused, unsigned int above_left __unused)
Unfilter byte using the "Sub" filter.
Definition png.c:395
static unsigned int png_unfilter_up(unsigned int current, unsigned int left __unused, unsigned int above, unsigned int above_left __unused)
Unfilter byte using the "Up" filter.
Definition png.c:412
static unsigned int png_unfilter_paeth(unsigned int current, unsigned int left, unsigned int above, unsigned int above_left)
Unfilter byte using the "Paeth" filter.
Definition png.c:475
@ PNG_FILTER_BASIC_SUB
Left byte used as predictor.
Definition png.h:166
@ PNG_FILTER_BASIC_UP
Above byte used as predictor.
Definition png.h:168
@ PNG_FILTER_BASIC_PAETH
Paeth filter.
Definition png.h:172
@ PNG_FILTER_BASIC_AVERAGE
Above and left bytes used as predictors.
Definition png.h:170
@ PNG_FILTER_BASIC_NONE
No filtering.
Definition png.h:164

PNG filter types.

Definition at line 501 of file png.c.

Referenced by png_unfilter_pass().

◆ png_chunk_handlers

struct png_chunk_handler png_chunk_handlers[]
static
Initial value:
= {
}
static int png_image_data(struct image *image, struct png_context *png, size_t len)
Handle PNG image data chunk.
Definition png.c:353
static int png_image_end(struct image *image, struct png_context *png, size_t len)
Handle PNG image end chunk.
Definition png.c:798
#define PNG_TYPE_IDAT
PNG image data chunk type.
Definition png.h:159
#define PNG_TYPE_IHDR
PNG image header chunk type.
Definition png.h:77
#define PNG_TYPE_PLTE
PNG palette chunk type.
Definition png.h:137
A PNG palette chunk.
Definition png.h:150

PNG chunk handlers.

Definition at line 852 of file png.c.

Referenced by png_chunk().