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:50
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)

Definition at line 184 of file png.c.

185 {
186
187 return ( 1 /* Filter byte */ +
188 ( ( interlace->width * png->channels * png->depth ) + 7 ) / 8);
189}

References 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 199 of file png.c.

200 {
201 const struct png_image_header *ihdr;
202 struct png_interlace interlace;
203 unsigned int pass;
204
205 /* Sanity check */
206 if ( len != sizeof ( *ihdr ) ) {
207 DBGC ( image, "PNG %s invalid IHDR length %zd\n",
208 image->name, len );
209 return -EINVAL;
210 }
211 if ( png->pixbuf ) {
212 DBGC ( image, "PNG %s duplicate IHDR\n", image->name );
213 return -EINVAL;
214 }
215
216 /* Extract image header */
217 ihdr = ( image->data + png->offset );
218 DBGC ( image, "PNG %s %dx%d depth %d type %d compression %d filter %d "
219 "interlace %d\n", image->name, ntohl ( ihdr->width ),
220 ntohl ( ihdr->height ), ihdr->depth, ihdr->colour_type,
221 ihdr->compression, ihdr->filter, ihdr->interlace );
222
223 /* Sanity checks */
224 if ( ihdr->compression >= PNG_COMPRESSION_UNKNOWN ) {
225 DBGC ( image, "PNG %s unknown compression method %d\n",
226 image->name, ihdr->compression );
227 return -ENOTSUP;
228 }
229 if ( ihdr->filter >= PNG_FILTER_UNKNOWN ) {
230 DBGC ( image, "PNG %s unknown filter method %d\n",
231 image->name, ihdr->filter );
232 return -ENOTSUP;
233 }
234 if ( ihdr->interlace >= PNG_INTERLACE_UNKNOWN ) {
235 DBGC ( image, "PNG %s unknown interlace method %d\n",
236 image->name, ihdr->interlace );
237 return -ENOTSUP;
238 }
239
240 /* Allocate pixel buffer */
241 png->pixbuf = alloc_pixbuf ( ntohl ( ihdr->width ),
242 ntohl ( ihdr->height ) );
243 if ( ! png->pixbuf ) {
244 DBGC ( image, "PNG %s could not allocate pixel buffer\n",
245 image->name );
246 return -ENOMEM;
247 }
248
249 /* Extract bit depth */
250 png->depth = ihdr->depth;
251 if ( ( png->depth == 0 ) ||
252 ( ( png->depth & ( png->depth - 1 ) ) != 0 ) ) {
253 DBGC ( image, "PNG %s invalid depth %d\n",
254 image->name, png->depth );
255 return -EINVAL;
256 }
257
258 /* Calculate number of channels */
259 png->colour_type = ihdr->colour_type;
260 png->channels = 1;
261 if ( ! ( ihdr->colour_type & PNG_COLOUR_TYPE_PALETTE ) ) {
262 if ( ihdr->colour_type & PNG_COLOUR_TYPE_RGB )
263 png->channels += 2;
265 png->channels += 1;
266 }
267
268 /* Calculate number of interlace passes */
270
271 /* Calculate length of raw data buffer */
272 for ( pass = 0 ; pass < png->passes ; pass++ ) {
273 png_interlace ( png, pass, &interlace );
274 if ( interlace.width == 0 )
275 continue;
276 png->raw.len += ( interlace.height *
277 png_scanline_len ( png, &interlace ) );
278 }
279
280 /* Allocate raw data buffer */
281 png->raw.data = umalloc ( png->raw.len );
282 if ( ! png->raw.data ) {
283 DBGC ( image, "PNG %s could not allocate data buffer\n",
284 image->name );
285 return -ENOMEM;
286 }
287
288 return 0;
289}
ring len
Length.
Definition dwmac.h:226
#define DBGC(...)
Definition compiler.h:505
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#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, 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 299 of file png.c.

300 {
301 const struct png_palette_entry *palette;
302 unsigned int i;
303
304 /* Populate palette */
305 palette = ( image->data + png->offset );
306 for ( i = 0 ; i < ( sizeof ( png->palette ) /
307 sizeof ( png->palette[0] ) ) ; i++ ) {
308
309 /* Stop when we run out of palette data */
310 if ( len < sizeof ( *palette ) )
311 break;
312
313 /* Extract palette entry */
314 png->palette[i] = ( ( palette->red << 16 ) |
315 ( palette->green << 8 ) |
316 ( palette->blue << 0 ) );
317 DBGC2 ( image, "PNG %s palette entry %d is %#06x\n",
318 image->name, i, png->palette[i] );
319
320 /* Move to next entry */
321 palette++;
322 len -= sizeof ( *palette );
323 }
324
325 return 0;
326}
#define DBGC2(...)
Definition compiler.h:522
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 336 of file png.c.

337 {
338 int rc;
339
340 /* Deflate this chunk */
341 if ( ( rc = deflate_inflate ( &png->deflate,
342 ( image->data + png->offset ),
343 len, &png->raw ) ) != 0 ) {
344 DBGC ( image, "PNG %s could not decompress: %s\n",
345 image->name, strerror ( rc ) );
346 return rc;
347 }
348
349 return 0;
350}
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 361 of file png.c.

364 {
365
366 return current;
367}

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 378 of file png.c.

381 {
382
383 return ( current + left );
384}

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 395 of file png.c.

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

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 412 of file png.c.

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

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 428 of file png.c.

429 {
430 unsigned int p;
431 unsigned int pa;
432 unsigned int pb;
433 unsigned int pc;
434
435 /* Algorithm as defined in RFC 2083 section 6.6 */
436 p = ( a + b - c );
437 pa = abs ( p - a );
438 pb = abs ( p - b );
439 pc = abs ( p - c );
440 if ( ( pa <= pb ) && ( pa <= pc ) ) {
441 return a;
442 } else if ( pb <= pc ) {
443 return b;
444 } else {
445 return c;
446 }
447}
#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 458 of file png.c.

461 {
462
463 return ( current + png_paeth_predictor ( left, above, above_left ) );
464}
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:428

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 503 of file png.c.

504 {
505 size_t pixel_len = png_pixel_len ( png );
506 size_t scanline_len = png_scanline_len ( png, interlace );
507 uint8_t *data = ( png->raw.data + png->raw.offset );
508 struct png_filter *filter;
509 unsigned int scanline;
510 unsigned int byte;
511 unsigned int filter_type;
512 unsigned int left;
513 unsigned int above;
514 unsigned int above_left;
515
516 /* On the first scanline of a pass, above bytes are assumed to
517 * be zero.
518 */
519 above = 0;
520
521 /* Iterate over each scanline in turn */
522 for ( scanline = 0 ; scanline < interlace->height ; scanline++ ) {
523
524 /* Extract filter byte and determine filter type */
525 filter_type = *(data++);
526 if ( filter_type >= ( sizeof ( png_filters ) /
527 sizeof ( png_filters[0] ) ) ) {
528 DBGC ( image, "PNG %s unknown filter type %d\n",
529 image->name, filter_type );
530 return -ENOTSUP;
531 }
532 filter = &png_filters[filter_type];
533 assert ( filter->unfilter != NULL );
534 DBGC2 ( image, "PNG %s pass %d scanline %d filter type %d\n",
535 image->name, interlace->pass, scanline, filter_type );
536
537 /* At the start of a line, both above-left and left
538 * bytes are taken to be zero.
539 */
540 left = 0;
541 above_left = 0;
542
543 /* Iterate over each byte (not pixel) in turn */
544 for ( byte = 0 ; byte < ( scanline_len - 1 ) ; byte++ ) {
545
546 /* Extract predictor bytes, if applicable */
547 if ( byte >= pixel_len )
548 left = *( data - pixel_len );
549 if ( scanline > 0 )
550 above = *( data - scanline_len );
551 if ( ( scanline > 0 ) && ( byte >= pixel_len ) ) {
552 above_left = *( data - scanline_len -
553 pixel_len );
554 }
555
556 /* Unfilter current byte */
557 *data = filter->unfilter ( *data, left, above,
558 above_left );
559 data++;
560 }
561 }
562
563 /* Update offset */
564 png->raw.offset = ( ( ( void * ) data ) - png->raw.data );
565
566 return 0;
567}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
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:484
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:467

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 579 of file png.c.

579 {
580 struct png_interlace interlace;
581 unsigned int pass;
582 int rc;
583
584 /* Process each interlace pass */
585 png->raw.offset = 0;
586 for ( pass = 0 ; pass < png->passes ; pass++ ) {
587
588 /* Calculate interlace pass parameters */
589 png_interlace ( png, pass, &interlace );
590
591 /* Skip zero-width rows (which have no filter bytes) */
592 if ( interlace.width == 0 )
593 continue;
594
595 /* Unfilter this pass */
596 if ( ( rc = png_unfilter_pass ( image, png,
597 &interlace ) ) != 0 )
598 return rc;
599 }
600 assert ( png->raw.offset == png->raw.len );
601
602 return 0;
603}
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:503

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 613 of file png.c.

614 {
615
616 /* The basic calculation is 255*(raw/max)*(value/max). We use
617 * fixed-point arithmetic (scaling up to the maximum range for
618 * a 32-bit integer), in order to get the same results for
619 * alpha blending as the test cases (produced using
620 * ImageMagick).
621 */
622 return ( ( ( ( ( 0xff00 * raw * alpha ) / max ) / max ) + 0x80 ) >> 8 );
623}
__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 636 of file png.c.

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

752 {
753 struct png_interlace interlace;
754 unsigned int pass;
755
756 /* Process each interlace pass */
757 png->raw.offset = 0;
758 for ( pass = 0 ; pass < png->passes ; pass++ ) {
759
760 /* Calculate interlace pass parameters */
761 png_interlace ( png, pass, &interlace );
762
763 /* Skip zero-width rows (which have no filter bytes) */
764 if ( interlace.width == 0 )
765 continue;
766
767 /* Unfilter this pass */
768 png_pixels_pass ( image, png, &interlace );
769 }
770 assert ( png->raw.offset == png->raw.len );
771}
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:636

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 781 of file png.c.

782 {
783 int rc;
784
785 /* Sanity checks */
786 if ( len != 0 ) {
787 DBGC ( image, "PNG %s invalid IEND length %zd\n",
788 image->name, len );
789 return -EINVAL;
790 }
791 if ( ! png->pixbuf ) {
792 DBGC ( image, "PNG %s missing pixel buffer (no IHDR?)\n",
793 image->name );
794 return -EINVAL;
795 }
796 if ( ! deflate_finished ( &png->deflate ) ) {
797 DBGC ( image, "PNG %s decompression not complete\n",
798 image->name );
799 return -EINVAL;
800 }
801 if ( png->raw.offset != png->raw.len ) {
802 DBGC ( image, "PNG %s incorrect decompressed length (expected "
803 "%zd, got %zd)\n", image->name, png->raw.len,
804 png->raw.offset );
805 return -EINVAL;
806 }
807
808 /* Unfilter raw data */
809 if ( ( rc = png_unfilter ( image, png ) ) != 0 )
810 return rc;
811
812 /* Fill pixel buffer */
813 png_pixels ( image, png );
814
815 return 0;
816}
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:579
static void png_pixels(struct image *image, struct png_context *png)
Fill PNG pixels.
Definition png.c:752

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 851 of file png.c.

852 {
853 struct png_chunk_handler *handler;
854 unsigned int i;
855
856 DBGC ( image, "PNG %s chunk type %s offset %zd length %zd\n",
857 image->name, png_type_name ( type ), png->offset, len );
858
859 /* Handle according to chunk type */
860 for ( i = 0 ; i < ( sizeof ( png_chunk_handlers ) /
861 sizeof ( png_chunk_handlers[0] ) ) ; i++ ) {
862 handler = &png_chunk_handlers[i];
863 if ( handler->type == type )
864 return handler->handle ( image, png, len );
865 }
866
867 /* Fail if unknown chunk type is critical */
868 if ( ! ( type & htonl ( PNG_CHUNK_ANCILLARY ) ) ) {
869 DBGC ( image, "PNG %s unknown critical chunk type %s\n",
871 return -ENOTSUP;
872 }
873
874 /* Ignore non-critical unknown chunk types */
875 return 0;
876}
#define htonl(value)
Definition byteswap.h:134
static struct png_chunk_handler png_chunk_handlers[]
PNG chunk handlers.
Definition png.c:835
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:819
uint32_t type
Chunk type.
Definition png.c:821
int(* handle)(struct image *image, struct png_context *png, size_t len)
Handle chunk.
Definition png.c:830

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 885 of file png.c.

885 {
886 struct png_context *png;
887 const struct png_chunk_header *header;
888 const struct png_chunk_footer *footer;
889 size_t remaining;
890 size_t chunk_len;
891 int rc;
892
893 /* Allocate and initialise context */
894 png = zalloc ( sizeof ( *png ) );
895 if ( ! png ) {
896 rc = -ENOMEM;
897 goto err_alloc;
898 }
899 png->offset = sizeof ( struct png_signature );
901
902 /* Process chunks */
903 do {
904
905 /* Extract chunk header */
906 remaining = ( image->len - png->offset );
907 if ( remaining < ( sizeof ( *header ) + sizeof ( *footer ) ) ){
908 DBGC ( image, "PNG %s truncated chunk header/footer "
909 "at offset %zd\n", image->name, png->offset );
910 rc = -EINVAL;
911 goto err_truncated;
912 }
913 header = ( image->data + png->offset );
914 png->offset += sizeof ( *header );
915
916 /* Validate chunk length */
917 chunk_len = ntohl ( header->len );
918 if ( chunk_len > ( remaining - sizeof ( *header ) -
919 sizeof ( *footer ) ) ) {
920 DBGC ( image, "PNG %s truncated chunk data at offset "
921 "%zd\n", image->name, png->offset );
922 rc = -EINVAL;
923 goto err_truncated;
924 }
925
926 /* Handle chunk */
927 if ( ( rc = png_chunk ( image, png, header->type,
928 chunk_len ) ) != 0 )
929 goto err_chunk;
930
931 /* Move to next chunk */
932 png->offset += ( chunk_len + sizeof ( *footer ) );
933
934 } while ( png->offset < image->len );
935
936 /* Check that we finished with an IEND chunk */
937 if ( header->type != htonl ( PNG_TYPE_IEND ) ) {
938 DBGC ( image, "PNG %s did not finish with IEND\n",
939 image->name );
940 rc = -EINVAL;
941 goto err_iend;
942 }
943
944 /* Return pixel buffer */
945 *pixbuf = pixbuf_get ( png->pixbuf );
946
947 /* Success */
948 rc = 0;
949
950 err_iend:
951 err_chunk:
952 err_truncated:
953 pixbuf_put ( png->pixbuf );
954 ufree ( png->raw.data );
955 free ( png );
956 err_alloc:
957 return rc;
958}
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:662
static int png_chunk(struct image *image, struct png_context *png, uint32_t type, size_t len)
Handle PNG chunk.
Definition png.c:851
#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:56
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 966 of file png.c.

966 {
967 const struct png_signature *signature;
968
969 /* Sanity check */
970 if ( image->len < sizeof ( *signature ) ) {
971 DBGC ( image, "PNG %s is too short\n", image->name );
972 return -ENOEXEC;
973 }
974
975 /* Check signature */
977 if ( memcmp ( signature, &png_signature, sizeof ( *signature ) ) != 0 ){
978 DBGC ( image, "PNG %s has invalid signature\n", image->name );
979 return -ENOEXEC;
980 }
981
982 return 0;
983}
u8 signature
CPU signature.
Definition CIB_PRM.h:7
#define ENOEXEC
Exec format error.
Definition errno.h:520
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:412
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:361
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:378
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:395
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:458
@ 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 484 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:336
static int png_image_end(struct image *image, struct png_context *png, size_t len)
Handle PNG image end chunk.
Definition png.c:781
#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 835 of file png.c.

Referenced by png_chunk().