Introduction
|
If you buy a
product from the above links (you can choose a different product
after opening Amazon.com web page,) I can earn some referral fee.
Please help maintain ysflight.com! |
From this page you can download a PNG decoder that
I've written for my fun. I've been using BMP file if I need to
include a picture in my program for both my job and my hobby.
However, it easily blows the total size of the project directory because
BMP format doesn't include any compression scheme. So, I wrote a PNG decoder. I suppose some of you have the same problem, so I
open the PNG decoder. It covers most practical bit depths although
not all of the bit depths are supported.
PNG is good for hand written pictures, and not as
efficient for photos as JPEG because it uses lossless compression
scheme. However, I figured that the compression rate heavily
depends on the program you use. For example,
Paint Shop Pro creates 20 to 30% smaller PNG of a photo than
Microsoft Photo Editor, which comes with MS Office. So, if you
need to put a picture in your program, why don't you use PNG?
By the way, YSFLIGHT project is running with marginal
budget. Please visit the following page, and help this project.
Thank you very much for your support!
http://supportysflight.en.ysflight.com
I have written PNG encoder when CMU was closed due to
heavy snow fall this February. I talked about my own PNG encoder
to my friend, and his immediate reaction was "Why don't you use libpng?"
50% of the reason was just because I just wanted to write my own PNG
encoder. The other 50% of the reason was I didn't want to waste
time to read license agreement of libpng. I am too scared to use a
code from the Internet for potential GPL contamination. If I am
told to download and use a code from the Internet for my work, I will do
so because it would be my employer's problem not my problem. But,
for writing my own hobby program, I try to write by myself as much as
possible. So far, I haven't used any code other than libraries
that comes with the compiler package for writing my own project.
This encoder is not very efficient in terms of speed
and compression ratio. But, according to [1],
although PNG specification itself is open, many patent on PNG-encoding
algorithms have been taken, and it would be dangerous unless I strictly
stick on the algorithm suggested in [1]. I
took that suggestion.
Disclaimer
The source codes you can download from this page --
files included in yspng.zip -- are free to use for any purposes.
You can use it in a free software or a commercial software, open-source
or proprietary. In any cases, you don't need to contact me for
permissions. You even don't have to mention about this web page,
but I'll be happy if you put a reference to this page.
However, I do not take any responsibility for
the consequence resulted by the use of these codes. Please use
these codes on your own risks.
Download
[Download] yspng.zip (including sample.cpp, yspng.h,
yspng.cpp, yspngenc.h, yspngenc.cpp, and encodersample.cpp)
Updates
06/25/2014 (R3021)
Support 4-bit Indexed Color.
03/23/2014 (R2813)
Fixed a bug based on a bug-report from a user. Sliding-window
was not populated while decoding an uncompressed block. Thank you
for the report! Also from this version is distributed on a BSD
license. [Download this version]
01/13/2012 (R958)
Fixed a bug based on a bug-report from a user. Thanks for the good
catch! [Download this version]
09/18/2010
Fixed a bug based on a bug-report from a viewer. Thanks for the
good catch! The transparency was not processed correctly in
interlaced 16-bit true-color mode.
[Download this version]
08/26/2010 21:54EDT
I realized my PNG encoder was not calculating CRC code if it was
compiled with a 64-bit C++ compiler. I have fixed the problem.
[Download this version]
08/26/2010
Added PNG encoder.
05/15/2005
An easy Linux (GLX) sample PNG viewer is added in the archive (yspng.zip).
[Download this version]
05/07/2005
An easy Win32 sample PNG viewer is added in the archive (yspng.zip).
04/08/2005
Started this page. Still, far from intensively-tested.
So, there can be loads of bugs in it.
Tested Compilers
I have tested this code with Visual C++ 2008 and
g++.
Supported Bit-Depths
PNG Decoder
|
Non-Interlace |
Interlace |
1bit Grayscale (B & W) |
OK |
Not Supported |
4bit Indexed Color |
OK |
Not Supported |
8bit Grayscale |
OK |
OK |
8bit Grayscale with Alpha |
OK |
OK |
8bit Indexed Color |
OK |
OK |
24bit True Color (*1) |
OK |
OK |
24bit True Color with Alpha (*1) |
OK |
OK |
48bit True Color (*2) |
OK |
OK |
PNG Encoder (formats that can be used)
|
Non-Interlace |
Interlace |
1bit Grayscale (B & W) |
OK |
Not Supported |
4bit Indexed Color |
Not Supported |
Not Supported |
8bit Grayscale |
OK |
Not Supported |
8bit Grayscale with Alpha |
OK |
Not Supported |
8bit Indexed Color |
Not Supported |
Not Supported |
24bit True Color (*1) |
OK |
Not Supported |
24bit True Color with Alpha (*1) |
OK |
Not Supported |
48bit True Color (*2) |
OK |
Not Supported |
(*1) The PNG specification describes 24bit true color as 8 bit true
color (8 bit per component). But, I think we commonly say "24bit
true color" for describing 8-bit-per-component color. So, I
describe it as 24 bit true color here.
(*2) Same as the logic of (*1) I describe 16bit-per-component color
as 48bit true color here.
Usage of PNG Decoder Classes
To use the PNG decoder classes, the source code that uses the classes
must include yspng.h, and yspng.cpp must be added to the project.
The source codes yspng.h and yspng.cpp include two
classes YsGenericPngDecoder and YsRawPngDecoder
YsGenericPngDecoder reads header information and decompress the
compressed bitmap data. However, it does not organize pixels into
a format that can directly be transferred to the screen.
YsRawPngDecoder class reads PNG file, and makes an
array of R, G, B, and A values, 8bit per component. The array can
be passed to a function like glDrawPixels directly to draw the bitmap
image. (But, if you use glDrawPixels will draw the picture
upside-down. So, you need to flip it before drawing. You can
do it by using Flip member function. Please see sample.cpp for
more details.) I suppose you only need YsRawPngDecoder for
practical purposes.
I describe a brief explanation of each class below.
Please see also sample.cpp for the usage.
[yspng.cpp, yspng.h]
YsGenericPngDecoder
YsGenericPngDecoder itself does nothing unless you
inherit the class and override the member functions -- PrepareOutput,
Output, and EndOutput. If you just need a quick and easy method
for getting an array of bitmap, please use YsRawPngDecoder class.
Functions
- void Initialize(void);
It initializes the content of the class variable.
- int Decode(const char fn[]);
It decodes a PNG file specified by fn.
- virtual int PrepareOutput(void);
Decode function first calls this function.
- virtual int Output(unsigned char dat);
Decode function passes a byte from the stream of bitmap as it is
uncompressed.
- virtual int EndOutput(void);
Decode function calls this function after reading all the content of
the PNG file.
Variables
- YsPngHeader hdr;
Header information. hdr.width and hdr.height will give the
number of pixels.
- YsPngPalette plt;
Palette information.
- YsPngTransparency trns;
Transparency information.
- unsigned int gamma;
Gamma value. Please read [1] for more details.
YsRawPngDecoder
YsRawPngDecoder class reads a PNG file and makes an array of pixels
with R, G, B, and A, 8bit per component. I think you only need
this class practically.
Functions
-
int Decode(const char fn[]);
It decodes a PNG file specified by fn, and stores the number of pixels
in member variables wid and hei, and a pointer to the
array of the bitmap in member variable rgba. If the
function succeeds, it returns a macro YSOK, otherwise it returns YSERR.
If your program needs to use the bitmap decoded by this function after
the lifetime of the YsRawPngDecoder variable, zero must be set to
member variable autoDeleteRgbaBuffer. Otherwise, the
class will automatically delete the array in the destructor.
-
void Flip(void);
It inverts the image upside-down. One of the purposes of this
class is to draw a PNG bitmap image with OpenGL, but glDrawPixels
itself draws a picture upside-down, so I added this function.
Variables
- int wid,hei;
The number of pixels of the decoded PNG file.
-
unsigned char *rgba;
A pointer to the array of bitmaps of the decoded PNG. Each pixel
consists of four components, R, G, B, and A (A is inverse of the
transparency.) Each of R, G, B, and A is 8bit (one unsigned
char.)
-
int autoDeleteRgbaBuffer;
If this variable is non-zero, the memory block that is pointed by rgba
is deleted in the destructor of YsRawPngDecoder class. If your
program needs to use the array of the bitmap of the decoded PNG, zero
must be set to this variable. In that case, the memory block
must be deleted by your program (like by delete [] rgba;), or the
memory block will be remain allocated as memory leak.
[yspngenc.cpp, yspngenc.h]
(* To use the encoder, you will also compile and link yspng.cpp)
YsGenericPngEncoder
This class itself does nothing useful. To do something useful,
you need to make a sub-class from YsGenericPngEncoder and override
StreamOut function. If you just need to write your bitmap to a PNG
file, you can use YsRawPngEncoder class instead.
Functions
YsRawPngEncoder
YsRawPngEncoder is a sub-class of YsGenericPngEncoder. It can
create a PNG file.
Function:
- int EncodeToFile(const char fn[],int width,int height,int
bitDepth,int colorType,unsigned char dat[]);
Create a PNG file. The file name is fn. Meaning of other
parameters are same as YsGenericPngEncoder::Encode.
References
[1] W3C, Portable Network Graphics (PNG) Specification (Second
Edition),
http://www.w3.org/TR/PNG/
<< |