Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
HardenedBSD
HardenedBSD
Commits
a70c2a23
Commit
a70c2a23
authored
Jan 02, 2021
by
Toomas Soome
Browse files
Initial import of vendor/pnglite
parents
Changes
4
Hide whitespace changes
Inline
Side-by-side
LICENSE
0 → 100644
View file @
a70c2a23
pnglite.h - Interface for pnglite library
Copyright (c) 2007 Daniel Karling
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
Daniel Karling
daniel.karling@gmail.com
README.md
0 → 100644
View file @
a70c2a23
pnglite
====
#### A pretty small png library
Currently all documentation resides in pnglite.h.
pnglite.c
0 → 100644
View file @
a70c2a23
/* pnglite.c - pnglite library
For conditions of distribution and use, see copyright notice in pnglite.h
*/
#define DO_CRC_CHECKS 1
#define USE_ZLIB 1
#if USE_ZLIB
#include <zlib.h>
#else
#include "zlite.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pnglite.h"
static
png_alloc_t
png_alloc
;
static
png_free_t
png_free
;
static
size_t
file_read
(
png_t
*
png
,
void
*
out
,
size_t
size
,
size_t
numel
)
{
size_t
result
;
if
(
png
->
read_fun
)
{
result
=
png
->
read_fun
(
out
,
size
,
numel
,
png
->
user_pointer
);
}
else
{
if
(
!
out
)
{
result
=
fseek
(
png
->
user_pointer
,
(
long
)(
size
*
numel
),
SEEK_CUR
);
}
else
{
result
=
fread
(
out
,
size
,
numel
,
png
->
user_pointer
);
}
}
return
result
;
}
static
size_t
file_write
(
png_t
*
png
,
void
*
p
,
size_t
size
,
size_t
numel
)
{
size_t
result
;
if
(
png
->
write_fun
)
{
result
=
png
->
write_fun
(
p
,
size
,
numel
,
png
->
user_pointer
);
}
else
{
result
=
fwrite
(
p
,
size
,
numel
,
png
->
user_pointer
);
}
return
result
;
}
static
int
file_read_ul
(
png_t
*
png
,
unsigned
*
out
)
{
unsigned
char
buf
[
4
];
if
(
file_read
(
png
,
buf
,
1
,
4
)
!=
4
)
return
PNG_FILE_ERROR
;
*
out
=
(
buf
[
0
]
<<
24
)
|
(
buf
[
1
]
<<
16
)
|
(
buf
[
2
]
<<
8
)
|
buf
[
3
];
return
PNG_NO_ERROR
;
}
static
int
file_write_ul
(
png_t
*
png
,
unsigned
in
)
{
unsigned
char
buf
[
4
];
buf
[
0
]
=
(
in
>>
24
)
&
0xff
;
buf
[
1
]
=
(
in
>>
16
)
&
0xff
;
buf
[
2
]
=
(
in
>>
8
)
&
0xff
;
buf
[
3
]
=
(
in
)
&
0xff
;
if
(
file_write
(
png
,
buf
,
1
,
4
)
!=
4
)
return
PNG_FILE_ERROR
;
return
PNG_NO_ERROR
;
}
static
unsigned
get_ul
(
unsigned
char
*
buf
)
{
unsigned
result
;
unsigned
char
foo
[
4
];
memcpy
(
foo
,
buf
,
4
);
result
=
(
foo
[
0
]
<<
24
)
|
(
foo
[
1
]
<<
16
)
|
(
foo
[
2
]
<<
8
)
|
foo
[
3
];
return
result
;
}
static
unsigned
set_ul
(
unsigned
char
*
buf
,
unsigned
in
)
{
buf
[
0
]
=
(
in
>>
24
)
&
0xff
;
buf
[
1
]
=
(
in
>>
16
)
&
0xff
;
buf
[
2
]
=
(
in
>>
8
)
&
0xff
;
buf
[
3
]
=
(
in
)
&
0xff
;
return
PNG_NO_ERROR
;
}
int
png_init
(
png_alloc_t
pngalloc
,
png_free_t
pngfree
)
{
if
(
pngalloc
)
png_alloc
=
pngalloc
;
else
png_alloc
=
&
malloc
;
if
(
pngfree
)
png_free
=
pngfree
;
else
png_free
=
&
free
;
return
PNG_NO_ERROR
;
}
static
int
png_get_bpp
(
png_t
*
png
)
{
int
bpp
;
switch
(
png
->
color_type
)
{
case
PNG_GREYSCALE
:
bpp
=
1
;
break
;
case
PNG_TRUECOLOR
:
bpp
=
3
;
break
;
case
PNG_INDEXED
:
bpp
=
1
;
break
;
case
PNG_GREYSCALE_ALPHA
:
bpp
=
2
;
break
;
case
PNG_TRUECOLOR_ALPHA
:
bpp
=
4
;
break
;
default:
return
PNG_FILE_ERROR
;
}
bpp
*=
png
->
depth
/
8
;
return
bpp
;
}
static
int
png_read_ihdr
(
png_t
*
png
)
{
unsigned
length
;
#if DO_CRC_CHECKS
unsigned
orig_crc
;
unsigned
calc_crc
;
#endif
unsigned
char
ihdr
[
13
+
4
];
/* length should be 13, make room for type (IHDR) */
file_read_ul
(
png
,
&
length
);
if
(
length
!=
13
)
{
printf
(
"%d
\n
"
,
length
);
return
PNG_CRC_ERROR
;
}
if
(
file_read
(
png
,
ihdr
,
1
,
13
+
4
)
!=
13
+
4
)
return
PNG_EOF_ERROR
;
#if DO_CRC_CHECKS
file_read_ul
(
png
,
&
orig_crc
);
calc_crc
=
crc32
(
0L
,
0
,
0
);
calc_crc
=
crc32
(
calc_crc
,
ihdr
,
13
+
4
);
if
(
orig_crc
!=
calc_crc
)
return
PNG_CRC_ERROR
;
#else
file_read_ul
(
png
);
#endif
png
->
width
=
get_ul
(
ihdr
+
4
);
png
->
height
=
get_ul
(
ihdr
+
8
);
png
->
depth
=
ihdr
[
12
];
png
->
color_type
=
ihdr
[
13
];
png
->
compression_method
=
ihdr
[
14
];
png
->
filter_method
=
ihdr
[
15
];
png
->
interlace_method
=
ihdr
[
16
];
if
(
png
->
color_type
==
PNG_INDEXED
)
return
PNG_NOT_SUPPORTED
;
if
(
png
->
depth
!=
8
&&
png
->
depth
!=
16
)
return
PNG_NOT_SUPPORTED
;
if
(
png
->
interlace_method
)
return
PNG_NOT_SUPPORTED
;
return
PNG_NO_ERROR
;
}
static
int
png_write_ihdr
(
png_t
*
png
)
{
unsigned
char
ihdr
[
13
+
4
];
unsigned
char
*
p
=
ihdr
;
unsigned
crc
;
file_write
(
png
,
"
\x89\x50\x4E\x47\x0D\x0A\x1A\x0A
"
,
1
,
8
);
file_write_ul
(
png
,
13
);
*
p
=
'I'
;
p
++
;
*
p
=
'H'
;
p
++
;
*
p
=
'D'
;
p
++
;
*
p
=
'R'
;
p
++
;
set_ul
(
p
,
png
->
width
);
p
+=
4
;
set_ul
(
p
,
png
->
height
);
p
+=
4
;
*
p
=
png
->
depth
;
p
++
;
*
p
=
png
->
color_type
;
p
++
;
*
p
=
0
;
p
++
;
*
p
=
0
;
p
++
;
*
p
=
0
;
p
++
;
file_write
(
png
,
ihdr
,
1
,
13
+
4
);
crc
=
crc32
(
0L
,
0
,
0
);
crc
=
crc32
(
crc
,
ihdr
,
13
+
4
);
file_write_ul
(
png
,
crc
);
return
PNG_NO_ERROR
;
}
void
png_print_info
(
png_t
*
png
)
{
printf
(
"PNG INFO:
\n
"
);
printf
(
"
\t
width:
\t\t
%d
\n
"
,
png
->
width
);
printf
(
"
\t
height:
\t\t
%d
\n
"
,
png
->
height
);
printf
(
"
\t
depth:
\t\t
%d
\n
"
,
png
->
depth
);
printf
(
"
\t
color:
\t\t
"
);
switch
(
png
->
color_type
)
{
case
PNG_GREYSCALE
:
printf
(
"greyscale
\n
"
);
break
;
case
PNG_TRUECOLOR
:
printf
(
"truecolor
\n
"
);
break
;
case
PNG_INDEXED
:
printf
(
"palette
\n
"
);
break
;
case
PNG_GREYSCALE_ALPHA
:
printf
(
"greyscale with alpha
\n
"
);
break
;
case
PNG_TRUECOLOR_ALPHA
:
printf
(
"truecolor with alpha
\n
"
);
break
;
default:
printf
(
"unknown, this is not good
\n
"
);
break
;
}
printf
(
"
\t
compression:
\t
%s
\n
"
,
png
->
compression_method
?
"unknown, this is not good"
:
"inflate/deflate"
);
printf
(
"
\t
filter:
\t\t
%s
\n
"
,
png
->
filter_method
?
"unknown, this is not good"
:
"adaptive"
);
printf
(
"
\t
interlace:
\t
%s
\n
"
,
png
->
interlace_method
?
"interlace"
:
"no interlace"
);
}
int
png_open_read
(
png_t
*
png
,
png_read_callback_t
read_fun
,
void
*
user_pointer
)
{
char
header
[
8
];
int
result
;
png
->
read_fun
=
read_fun
;
png
->
write_fun
=
0
;
png
->
user_pointer
=
user_pointer
;
if
(
!
read_fun
&&
!
user_pointer
)
return
PNG_WRONG_ARGUMENTS
;
if
(
file_read
(
png
,
header
,
1
,
8
)
!=
8
)
return
PNG_EOF_ERROR
;
if
(
memcmp
(
header
,
"
\x89\x50\x4E\x47\x0D\x0A\x1A\x0A
"
,
8
)
!=
0
)
return
PNG_HEADER_ERROR
;
result
=
png_read_ihdr
(
png
);
png
->
bpp
=
(
unsigned
char
)
png_get_bpp
(
png
);
return
result
;
}
int
png_open_write
(
png_t
*
png
,
png_write_callback_t
write_fun
,
void
*
user_pointer
)
{
png
->
write_fun
=
write_fun
;
png
->
read_fun
=
0
;
png
->
user_pointer
=
user_pointer
;
if
(
!
write_fun
&&
!
user_pointer
)
return
PNG_WRONG_ARGUMENTS
;
return
PNG_NO_ERROR
;
}
int
png_open
(
png_t
*
png
,
png_read_callback_t
read_fun
,
void
*
user_pointer
)
{
return
png_open_read
(
png
,
read_fun
,
user_pointer
);
}
int
png_open_file_read
(
png_t
*
png
,
const
char
*
filename
)
{
FILE
*
fp
=
fopen
(
filename
,
"rb"
);
if
(
!
fp
)
return
PNG_FILE_ERROR
;
return
png_open_read
(
png
,
0
,
fp
);
}
int
png_open_file_write
(
png_t
*
png
,
const
char
*
filename
)
{
FILE
*
fp
=
fopen
(
filename
,
"wb"
);
if
(
!
fp
)
return
PNG_FILE_ERROR
;
return
png_open_write
(
png
,
0
,
fp
);
}
int
png_open_file
(
png_t
*
png
,
const
char
*
filename
)
{
return
png_open_file_read
(
png
,
filename
);
}
int
png_close_file
(
png_t
*
png
)
{
fclose
(
png
->
user_pointer
);
return
PNG_NO_ERROR
;
}
static
int
png_init_deflate
(
png_t
*
png
,
unsigned
char
*
data
,
int
datalen
)
{
z_stream
*
stream
;
png
->
zs
=
png_alloc
(
sizeof
(
z_stream
));
stream
=
png
->
zs
;
if
(
!
stream
)
return
PNG_MEMORY_ERROR
;
memset
(
stream
,
0
,
sizeof
(
z_stream
));
if
(
deflateInit
(
stream
,
Z_DEFAULT_COMPRESSION
)
!=
Z_OK
)
return
PNG_ZLIB_ERROR
;
stream
->
next_in
=
data
;
stream
->
avail_in
=
datalen
;
return
PNG_NO_ERROR
;
}
static
int
png_init_inflate
(
png_t
*
png
)
{
#if USE_ZLIB
z_stream
*
stream
;
png
->
zs
=
png_alloc
(
sizeof
(
z_stream
));
#else
zl_stream
*
stream
;
png
->
zs
=
png_alloc
(
sizeof
(
zl_stream
));
#endif
stream
=
png
->
zs
;
if
(
!
stream
)
return
PNG_MEMORY_ERROR
;
#if USE_ZLIB
memset
(
stream
,
0
,
sizeof
(
z_stream
));
if
(
inflateInit
(
stream
)
!=
Z_OK
)
return
PNG_ZLIB_ERROR
;
#else
memset
(
stream
,
0
,
sizeof
(
zl_stream
));
if
(
z_inflateInit
(
stream
)
!=
Z_OK
)
return
PNG_ZLIB_ERROR
;
#endif
stream
->
next_out
=
png
->
png_data
;
stream
->
avail_out
=
png
->
png_datalen
;
return
PNG_NO_ERROR
;
}
static
int
png_end_deflate
(
png_t
*
png
)
{
z_stream
*
stream
=
png
->
zs
;
if
(
!
stream
)
return
PNG_MEMORY_ERROR
;
deflateEnd
(
stream
);
png_free
(
png
->
zs
);
return
PNG_NO_ERROR
;
}
static
int
png_end_inflate
(
png_t
*
png
)
{
#if USE_ZLIB
z_stream
*
stream
=
png
->
zs
;
#else
zl_stream
*
stream
=
png
->
zs
;
#endif
if
(
!
stream
)
return
PNG_MEMORY_ERROR
;
#if USE_ZLIB
if
(
inflateEnd
(
stream
)
!=
Z_OK
)
#else
if
(
z_inflateEnd
(
stream
)
!=
Z_OK
)
#endif
{
printf
(
"ZLIB says: %s
\n
"
,
stream
->
msg
);
return
PNG_ZLIB_ERROR
;
}
png_free
(
png
->
zs
);
return
PNG_NO_ERROR
;
}
static
int
png_inflate
(
png_t
*
png
,
unsigned
char
*
data
,
int
len
)
{
int
result
;
#if USE_ZLIB
z_stream
*
stream
=
png
->
zs
;
#else
zl_stream
*
stream
=
png
->
zs
;
#endif
if
(
!
stream
)
return
PNG_MEMORY_ERROR
;
stream
->
next_in
=
data
;
stream
->
avail_in
=
len
;
#if USE_ZLIB
result
=
inflate
(
stream
,
Z_SYNC_FLUSH
);
#else
result
=
z_inflate
(
stream
);
#endif
if
(
result
!=
Z_STREAM_END
&&
result
!=
Z_OK
)
{
printf
(
"%s
\n
"
,
stream
->
msg
);
return
PNG_ZLIB_ERROR
;
}
if
(
stream
->
avail_in
!=
0
)
return
PNG_ZLIB_ERROR
;
return
PNG_NO_ERROR
;
}
static
int
png_deflate
(
png_t
*
png
,
char
*
outdata
,
int
outlen
,
int
*
outwritten
)
{
int
result
;
z_stream
*
stream
=
png
->
zs
;
if
(
!
stream
)
return
PNG_MEMORY_ERROR
;
stream
->
next_out
=
(
unsigned
char
*
)
outdata
;
stream
->
avail_out
=
outlen
;
result
=
deflate
(
stream
,
Z_SYNC_FLUSH
);
*
outwritten
=
outlen
-
stream
->
avail_out
;
if
(
result
!=
Z_STREAM_END
&&
result
!=
Z_OK
)
{
printf
(
"%s
\n
"
,
stream
->
msg
);
return
PNG_ZLIB_ERROR
;
}
return
result
;
}
static
int
png_write_idats
(
png_t
*
png
,
unsigned
char
*
data
)
{
unsigned
char
*
chunk
;
unsigned
long
written
;
unsigned
long
crc
;
unsigned
size
=
png
->
width
*
png
->
height
*
png
->
bpp
+
png
->
height
;
unsigned
chunk_size
=
compressBound
(
size
);
(
void
)
png_init_deflate
;
(
void
)
png_end_deflate
;
(
void
)
png_deflate
;
chunk
=
png_alloc
(
chunk_size
+
4
);
memcpy
(
chunk
,
"IDAT"
,
4
);
written
=
chunk_size
;
compress
(
chunk
+
4
,
&
written
,
data
,
size
);
crc
=
crc32
(
0L
,
Z_NULL
,
0
);
crc
=
crc32
(
crc
,
chunk
,
written
+
4
);
set_ul
(
chunk
+
written
+
4
,
crc
);
file_write_ul
(
png
,
written
);
file_write
(
png
,
chunk
,
1
,
written
+
8
);
png_free
(
chunk
);
file_write_ul
(
png
,
0
);
file_write
(
png
,
"IEND"
,
1
,
4
);
crc
=
crc32
(
0L
,
(
const
unsigned
char
*
)
"IEND"
,
4
);
file_write_ul
(
png
,
crc
);
return
PNG_NO_ERROR
;
}
static
int
png_read_idat
(
png_t
*
png
,
unsigned
length
)
{
#if DO_CRC_CHECKS
unsigned
orig_crc
;
unsigned
calc_crc
;
#endif
if
(
!
png
->
readbuf
||
png
->
readbuflen
<
length
)
{
if
(
png
->
readbuf
)
{
png_free
(
png
->
readbuf
);
}
png
->
readbuf
=
png_alloc
(
length
);
png
->
readbuflen
=
length
;
}
if
(
!
png
->
readbuf
)
{
return
PNG_MEMORY_ERROR
;
}
if
(
file_read
(
png
,
png
->
readbuf
,
1
,
length
)
!=
length
)
{
return
PNG_FILE_ERROR
;
}
#if DO_CRC_CHECKS
calc_crc
=
crc32
(
0L
,
Z_NULL
,
0
);
calc_crc
=
crc32
(
calc_crc
,
(
unsigned
char
*
)
"IDAT"
,
4
);
calc_crc
=
crc32
(
calc_crc
,
(
unsigned
char
*
)
png
->
readbuf
,
length
);
file_read_ul
(
png
,
&
orig_crc
);
if
(
orig_crc
!=
calc_crc
)
{
return
PNG_CRC_ERROR
;
}
#else
file_read_ul
(
png
);
#endif
return
png_inflate
(
png
,
png
->
readbuf
,
length
);
}
static
int
png_process_chunk
(
png_t
*
png
)
{
int
result
=
PNG_NO_ERROR
;
unsigned
type
;
unsigned
length
;
file_read_ul
(
png
,
&
length
);
if
(
file_read
(
png
,
&
type
,
1
,
4
)
!=
4
)
return
PNG_FILE_ERROR
;
if
(
type
==
*
(
unsigned
int
*
)
"IDAT"
)
/* if we found an idat, all other idats should be followed with no other chunks in between */
{
if
(
!
png
->
png_data
)
/* first IDAT */
{
png
->
png_datalen
=
png
->
width
*
png
->
height
*
png
->
bpp
+
png
->
height
;
png
->
png_data
=
png_alloc
(
png
->
png_datalen
);
}
if
(
!
png
->
png_data
)
return
PNG_MEMORY_ERROR
;
if
(
!
png
->
zs
)
{
result
=
png_init_inflate
(
png
);
if
(
result
!=
PNG_NO_ERROR
)
return
result
;
}
return
png_read_idat
(
png
,
length
);
}
else
if
(
type
==
*
(
unsigned
int
*
)
"IEND"
)
{
return
PNG_DONE
;
}
else
{
file_read
(
png
,
0
,
1
,
length
+
4
);
/* unknown chunk */
}
return
result
;
}
static
void
png_filter_sub
(
int
stride
,
unsigned
char
*
in
,
unsigned
char
*
out
,
int
len
)
{
int
i
;