[go: up one dir, main page]

Menu

[r1]: / lodepng.h  Maximize  Restore  History

Download this file

1060 lines (823 with data), 48.1 kB

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
/*
LodePNG version 20070830
Copyright (c) 2005-2007 Lode Vandevenne
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.
*/
#ifndef LODEPNG_H
#define LODEPNG_H
#include <vector>
#include <string>
namespace LodeZlib
{
struct DecompressSettings
{
bool ignoreAdler32;
DecompressSettings();
};
const DecompressSettings defaultDecompressSettings;
struct CompressSettings
{
//LZ77 related settings
unsigned long btype; //the block type for LZ
bool useLZ77; //whether or not to use LZ77
unsigned long windowSize; //the maximum is 32768
CompressSettings();
};
const CompressSettings defaultCompressSettings;
int decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in, const DecompressSettings& settings = defaultDecompressSettings); //return value is the error
void compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in, const CompressSettings& settings = defaultCompressSettings);
} //end of namespace LodeZlib
namespace LodePNG
{
struct Info //information used for both raw and PNG images
{
//header (IHDR)
unsigned long colorType; //color type
unsigned long bitDepth; //bits per sample
//palette (PLTE)
std::vector<unsigned char> palette; //palette in RGBARGBA... order
//transparent color key (tRNS)
bool key_defined; //is a transparent color key given?
unsigned long key_r; //red component of color key
unsigned long key_g; //green component of color key
unsigned long key_b; //blue component of color key
//additional color info
unsigned long getBpp() const; //bits per pixel
unsigned long getChannels() const; //amount of channels
bool isGreyscaleType() const; //is it a greyscale type? (colorType 0 or 4)
bool isAlphaType() const; //has it an alpha channel? (colorType 2 or 6)
Info();
};
struct InfoPng : public Info //information about the PNG image
{
InfoPng();
//header (IHDR)
unsigned long width; //width of the image in pixels
unsigned long height; //height of the image in pixels
unsigned char compressionMethod; //compression method of the original file
unsigned char filterMethod; //filter method of the original file
unsigned char interlaceMethod; //interlace method of the original file
//suggested background color (bKGD)
bool background_defined; //is a suggested background color given?
unsigned long background_r; //red component of sugg. background color
unsigned long background_g; //green component of sugg. background color
unsigned long background_b; //blue component of sugg. background color
//text chunks (tEXt)
std::vector<std::string> text_keys; //the key word of a text chunk (e.g. "Comment")
std::vector<std::string> text_strings; //the actual text
void addText(const char* key, const char* str); //push back both texts at once
};
struct InfoRaw : public Info //contains user-chosen information about the raw image data, which is independent of the PNG image
{
};
class Decoder
{
public:
Decoder();
//decoding functions
void decode(std::vector<unsigned char>& out, const unsigned char* in, unsigned long size);
void decode(std::vector<unsigned char>& out, const std::vector<unsigned char>& in);
void inspect(const unsigned char* in, unsigned long size);
void inspect(const std::vector<unsigned char>& in);
//error checking after decoding
bool hasError() const;
int getError() const;
//get image size after decoding
unsigned long getWidth() const; //the width in pixels
unsigned long getHeight() const; //the height in pixels
struct Settings
{
bool color_convert;
bool readTextChunks;
bool ignoreCrc;
bool ignoreAdler32;
Settings();
};
void setSettings(const Settings& settings);
const Settings& getSettings() const;
Settings& getSettings();
//other image info after decoding
const InfoPng& getInfoPng() const;
void setInfoRaw(const InfoRaw& infoRaw);
const InfoRaw& getInfoRaw() const;
InfoRaw& getInfoRaw();
private:
InfoPng infoPng;
InfoRaw infoRaw;
Settings settings;
int error; //the error value of the decode attempt
void readPngHeader(const unsigned char* in, size_t inlength);
void unFilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, size_t bytewidth, unsigned char filterType, size_t length);
void adam7Pass(unsigned char* out, unsigned char* linen, unsigned char* lineo, const unsigned char* in, unsigned long w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, unsigned long bpp);
void resetParameters();
void decodeGeneric(std::vector<unsigned char>& out, const unsigned char* in, unsigned long size);
};
class Encoder
{
public:
struct Settings
{
bool autoLeaveOutAlphaChannel; //automatically use color type without alpha instead of given one, if given image is opaque
//LZ77 related settings
unsigned long btype; //the block type for LZ
bool useLZ77; //whether or not to use LZ77
unsigned long windowSize; //the maximum is 32768
bool force_palette; //force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). If colortype is 3, PLTE is _always_ created.
bool add_id;
Settings();
};
void encode(std::vector<unsigned char>& out, const unsigned char* image, unsigned long w, unsigned long h);
void encode(std::vector<unsigned char>& out, const std::vector<unsigned char>& image, unsigned long w, unsigned long h);
void setSettings(const Settings& settings);
const Settings& getSettings() const;
Settings& getSettings();
void setInfoPng(const InfoPng& info);
const InfoPng& getInfoPng() const;
InfoPng& getInfoPng(); //get and set the info
void setInfoRaw(const InfoRaw& infoRaw);
const InfoRaw& getInfoRaw() const;
InfoRaw& getInfoRaw();
bool hasError() const;
int getError() const;
Encoder();
private:
InfoPng user_infoPng; //the info specified by the user may not be changed by the encoder. The encoder will try to generate a PNG close to the given info.
InfoPng infoPng; //the info used by the encoder, generated out of user_infoPng
Settings settings; //the settings specified by the user may not be changed by the encoder
InfoRaw infoRaw;
int error;
void resetParameters();
void addChunk(std::vector<unsigned char>& out, const std::string& chunkName, unsigned char* data, unsigned long length);
void writeSignature(std::vector<unsigned char>& out);
void writeChunk_tEXt(std::vector<unsigned char>& out, const std::string& keyword, const std::string& textstring);
void writeChunk_IHDR(std::vector<unsigned char>& out, unsigned long w, unsigned long h, unsigned long bitDepth, unsigned long colorType);
void writeChunk_PLTE(std::vector<unsigned char>& out, const Info& info); //writes the palette that is in the given info
void writeChunk_tRNS(std::vector<unsigned char>& out, const Info& info); //writes colorkey or palette alpha channel depending on color type
void writeChunk_IDAT(std::vector<unsigned char>& out, const std::vector<unsigned char>& data);
void writeChunk_IEND(std::vector<unsigned char>& out);
void writeChunk_bKGD(std::vector<unsigned char>& out, const InfoPng& info);
void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, size_t length, size_t bytewidth, unsigned char filterType);
void filter(std::vector<unsigned char>& out, const unsigned char* image, unsigned long size, unsigned long w, unsigned long h); //will filter scanline per scanline and add filter type in front
void dontFilter(std::vector<unsigned char>& out, const unsigned char* image, unsigned long size, unsigned long w, unsigned long h);
};
//global functions allowing to load and save a file from/to harddisk
void loadFile(std::vector<unsigned char>& buffer, const std::string& filename);
void saveFile(const std::vector<unsigned char>& buffer, const std::string& filename);
//simple functions for encoding/decoding the PNG in one call (RAW image always 32-bit)
int decode(std::vector<unsigned char>& out, unsigned long& w, unsigned long& h, const unsigned char* in, unsigned long size, unsigned long colorType = 6, unsigned long bitDepth = 8);
int decode(std::vector<unsigned char>& out, unsigned long& w, unsigned long& h, const std::vector<unsigned char>& in, unsigned long colorType = 6, unsigned long bitDepth = 8);
int decode(std::vector<unsigned char>& out, unsigned long& w, unsigned long& h, const std::string& filename, unsigned long colorType = 6, unsigned long bitDepth = 8);
int encode(std::vector<unsigned char>& out, const unsigned char* in, unsigned long w, unsigned long h, unsigned long colorType = 6, unsigned long bitDepth = 8);
int encode(std::vector<unsigned char>& out, const std::vector<unsigned char>& in, unsigned long w, unsigned long h, unsigned long colorType = 6, unsigned long bitDepth = 8);
int encode(const std::string& filename, const unsigned char* in, unsigned long w, unsigned long h, unsigned long colorType = 6, unsigned long bitDepth = 8);
int encode(const std::string& filename, const std::vector<unsigned char>& in, unsigned long w, unsigned long h, unsigned long colorType = 6, unsigned long bitDepth = 8);
} //end of namespace LodePNG
/*
TODO:
[ ] LZ77 encoder more like the one described in zlib - to make sure it's patentfree
[ ] converting color to 16-bit types
[ ] read some other chunks, like gamma (but don't make them influence the RGB values)
[ ] add option to decoder to store ignored chunks in InfoPng, and let encoder include those in the result
[ ] encoding PNGs with Adam7 interlace
[ ] make sure encoder generates no chunks with size > (2^31)-1
[ ] partial decoding (stream processing)
[ ] let the "isFullyOpaque" function check color keys and transparent palettes too
[ ] better name for "codes", "codesD", "codelengthcodes", "clcl" and "lldl"
[ ] more consistency in types like "unsigned long", "size_t" and "int"
[ ] support zTXt chunks
[ ] support iTXt chunks
[ ] check compatibility with vareous compilers
[ ] don't stop decoding on errors like 69, 57, 58
*/
#endif
/*
LodePNG Documentation
---------------------
0. table of contents
--------------------
1. about
1.1. supported features
1.2. features not supported
2. simple functions
3. decoder
4. encoder
5. color conversions
6. info values
7. error values
8. file IO
9. compiler support
10. examples
10.1. decoder example
10.2. encoder example
11. changes
12. contact information
1. about
--------
PNG is a file format to store raster images losslessly with good compression,
supporting different color types. It can be implemented in a patent-free way.
LodePNG is a PNG codec according to the Portable Network Graphics (PNG)
Specification (Second Edition) - W3C Recommendation 10 November 2003.
The specifications used are:
*) Portable Network Graphics (PNG) Specification (Second Edition):
http://www.w3.org/TR/2003/REC-PNG-20031110
*) RFC 1950 ZLIB Compressed Data Format version 3.3:
http://www.gzip.org/zlib/rfc-zlib.html
*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3:
http://www.gzip.org/zlib/rfc-deflate.html
The most recent version of LodePNG can currently be found at
http://members.gamedev.net/lode/projects/LodePNG/
LodePNG exists out of the source code files lodepng.cpp and lodepng.h, and
optionally the examples lodepng_examples.cpp
LodePNG is simple but only supports the basic requirements. To achieve
simplicity, the following design choices were made: There are no dependencies
on any external library. To decode PNGs, there's a Decoder class that can
convert any PNG file data into an RGBA image buffer with a single function call.
To encode PNGs, there's an Encoder class that can convert image data into PNG
file data with a single function call. To read and write files, two simple
functions were added.
This all makes LodePNG suitable for loading textures in games, raytracers,
intros, or for loading images into programs that require them only for simple
usage. It's less suitable for full fledged image editors, loading PNGs over
network (since this decoder requires all the image data to be available before
the decoding can begin), life-critical systems, ... Even though it contains
a conformant decoder and encoder, it's still not a conformant editor,
because unknown chunks are discarded.
1.1. supported features
-----------------------
The following features are supported by the decoder:
*) decoding of PNGs with any color type, bit depth and interlace mode
*) (auto) conversion of color types, from any color type, to 24-bit, 32-bit, ...
*) loading the image from harddisk or decoding it from a buffer
*) support for translucent PNG's, including translucent palettes and color key
*) zlib decompression (inflate)
*) encoding of PNGs, with 24-bit, 32-bit color or greyscale
*) zlib compression (deflate), not really fast
*) the following chunks are supported by both encoder and decoder:
IHDR (header information)
PLTE (color palette)
IDAT (pixel data)
IEND (the final chunk)
tRNS (transparency for palettized images)
bKGD (suggested background color)
tEXt (textual information)
1.2. features not supported
---------------------------
The following features are _not_ supported:
*) editing a PNG image (unless you use the decoder, then edit it, then use the
encoder, but ignored chunks will then be gone from the original image)
*) partial loading. All data must be available and is processed in one call.
*) The following optional chunks are ignored and discarded by the decoder:
cHRM, gAMA, iCCP, sRGB, sBIT, zTXt, iTXt, hIST, pHYs, sPLT, tIME
2. Simple Functions
-------------------
For the most simple usage cases, there are currently 7 simple functions that do
everything in 1 call (instead of you having to declare a class).
For decoding a PNG there are:
int decode(std::vector<unsigned char>& out, unsigned long& w, unsigned long& h, const unsigned char* in, unsigned long size);
int decode(std::vector<unsigned char>& out, unsigned long& w, unsigned long& h, const std::vector<unsigned char>& in);
int decode(std::vector<unsigned char>& out, unsigned long& w, unsigned long& h, const std::string& filename);
These store the pixel data as 32-bit RGBA color in the out vector, and the width
and height of the image in w and h.
The 3 functions each have a different input type: The first as unsigned char
buffer, the second as std::vector buffer, and the third allows you to give the
filename in case you want to load the PNG from disk instead of from a buffer.
For encoding a PNG there are:
int encode(std::vector<unsigned char>& out, const unsigned char* in, unsigned long w, unsigned long h);
int encode(std::vector<unsigned char>& out, const std::vector<unsigned char>& in, unsigned long w, unsigned long h);
int encode(const std::string& filename, const std::vector<unsigned char>& in, unsigned long w, unsigned long h);
int encode(const std::string& filename, const unsigned char* in, unsigned long w, unsigned long h);
Specify the width and height of the input image with w and h.
You can choose to get the output in an std::vector or stored in a file, and
the input can come from an std::vector or an unsigned char* buffer. The input
buffer must be in RGBA format and the size must be w * h * 4 bytes.
The first two functions append to the out buffer, they don't clear it, clear it
first before encoding into a buffer that you expect to only contain this result.
On the other hand, the functions that encode to a file will completely overwrite
the original file without warning if it exists.
3. Decoder
----------
The Decoder class can be used to convert a PNG image to a raw image.
You have to give the decoder the contents of a PNG file, as an unsigned char*
buffer. The result is stored in a given std::vector.
The parameters of the decode function are:
*) out: this vector will be filled with the raw image pixels
*) in: pointer to the PNG image data or vector with the data
*) size: the size of the PNG image data (not needed for vector version)
There's also a function "inspect". It has the same parameters as decode except
the "out" parameter. This function will read _only_ the header chunk of the PNG
image, and store the information from it in the InfoPng (see below). This allows
knowing information about the image without decoding it. Only the header (IHDR)
information is read by this, not text chunks, not the palette, ...
During the decoding it's possible that an error can happen, for example if the
PNG image was corrupted. To check if an error happened during the last decoding,
use hasError(). To get the value of the error, use getError(). The error codes
are explained in another section.
The Decoder contains 3 components:
*) InfoPng: it stores information about the PNG (the input) in an InfoPng struct
*) Settings: you can specify a few other settings for the decoder to use
*) InfoRaw: here you can say what type of raw image (the output) you want to get
Each of these 3 components can be set and gotten with getters and setters,
except InfoPng which, in the case of the Decoder, can only be read from.
=InfoPng=
This contains information such as the original color type of the PNG image, text
comments, suggested background color, etc... More details about the InfoPng struct
are in another section. Because the dimensions of the image are important, there
are shortcuts to get them: use getWidth() and getHeight(), or the width and
height properties of the InfoPng struct.
=InfoRaw=
In the InfoRaw struct of the Decoder, you can specify which color type you want
the resulting raw image to be. If this is different from the colorType of the
PNG, then the decoder will automatically convert the result to your InfoRaw
settings. Currently the following options are supported to convert to:
-colorType 6, bitDepth 8: 32-bit RGBA
-colorType 2, bitDepth 8: 24-bit RGB
-other color types if it's exactly the same as that in the PNG image
Palette of InfoRaw isn't used by the Decoder, when converting from palette color
to palette color, the values of the pixels are left untouched so that the colors
will change if the palette is different. Color key of InfoRaw is not used by the
Decoder. If setting color_convert is false then InfoRaw is completely ignored.
By default, 32-bit color is used for the result.
=Settings=
The Settings can be used to ignore the errors created by invalid CRC and Adler32
chunks, and to disable the decoding of tEXt chunks.
There's also a setting color_convert, true by default. If false, no conversion
is done, the resulting data will be as it was in the PNG (after decompression)
and you'll have to puzzle the colors of the pixels together yourself using the
color type information in the InfoPng.
4. Encoder
----------
The Encoder class can be used to convert raw image data into a PNG image.
The PNG part of the encoder is working good, the zlib compression part is
becoming quite fine but not as good as the official zlib yet, because it's not
as fast and doesn't provide an as high compression ratio.
The raw image given to the encoder is an unsigned char* buffer. You also have to
specify the width and height of the raw image. The result is stored in a given
std::vector.
The parameters of the encode function are:
*) out: in this vector the PNG file data will be stored (it will be appended)
*) in: vector of or pointer to a buffer containing the raw image
*) w and h: the width and height of the raw image in pixels
Make sure that the in buffer you provide, is big enough to contain w * h pixels
of the color type specified by the InfoRaw.
The encoder generates some errors but not for everything, because, unlike when
decoding a PNG, when encoding one there aren't so much parameters of the input
that can be corrupted. It's the responsibility of the user to make sure that all
preconditions are satesfied, such as giving a correct window size, giving an
existing btype, making sure the given buffer is large enough to contain an image
with the given width and height and colortype, ... The encoder can generate
some errors, see the section with the explanations of errors for those.
Like the Decoder, the Encoder has 3 components:
*) InfoRaw: here you say what color type of the raw image (the input) has
*) Settings: you can specify a few settings for the encoder to use
*) InfoPng: the same InfoPng struct as created by the Decoder. For the encoder,
with this you specify how you want the PNG (the output) to be.
Each of these can be gotten and set with getters and setters.
=InfoPng=
The Decoder class stores information about the PNG image in an InfoPng object. With
the Encoder you can do the opposite: you give it an InfoPng object, and it'll try
to match the InfoPng you give as close as possible in the PNG it encodes. For
example in the InfoPng you can specify the color type you want to use, possible
tEXt chunks you want the PNG to contain, etc... For an explanation of all the
values in InfoPng see a further section. Not all PNG color types are supported
by the Encoder.
Note that the encoder will only TRY to match the InfoPng struct you give. A lot
of things are ignored by the encoder. The width and height of InfoPng are
ignored as well, because instead the width and height of the raw image you give
in the input are used In fact the encoder currently uses only the following
settings from it:
-colorType: the ones it supports
-text chunks, that you can add to the InfoPng with "addText"
-the color key, if applicable for the given color type
-the palette, if you encode to a PNG with colorType 3
-the background color: it'll add a bKGD chunk to the PNG if one is given
When encoding to a PNG with colorType 3, the encoder will generate a PLTE chunk.
If the palette contains any colors for which the alpha channel is not 255 (so
there are translucent colors in the palette), it'll add a tRNS chunk.
=InfoRaw=
You specify the color type of the raw image that you give to the input here,
including a possible transparent color key and palette you happen to be using in
your raw image data.
By default, 32-bit color is assumed, meaning your input has to be in RGBA
format with 4 bytes (unsigned chars) per pixel.
=Settings=
The following settings are supported:
*) autoLeaveOutAlphaChannel: when this option is enabled, when you specify a PNG
color type with alpha channel (not to be confused with the color type of the raw
image you specify!!), but the encoder detects that all pixels of the given image
are opaque, then it'll automatically use the corresponding type without alpha
channel, resulting in a smaller PNG image.
*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree, 2 = dynamic huffman tree (best compression)
*) useLZ77: whether or not to use LZ77 for compressed block types
*) windowSize: the window size used by the LZ77 encoder (1 - 32768)
*) force_palette: if colorType is 2 or 6, you can make the encoder write a PLTE
chunk if force_palette is true. This can used as suggested palette to convert
to by viewers that don't support more than 256 colors (if those still exist)
*) add_id: add text chunk "Encoder: LodePNG <version>" to the image.
5. color conversions
--------------------
For trickier usage of LodePNG, you need to understand about PNG color types and
about how and when LodePNG uses the settings in InfoPng, InfoRaw and Settings.
=PNG color types=
A PNG image can have many color types, ranging from 1-bit color to 64-bit color,
as well as palettized color modes. After the zlib decompression and unfiltering
in the PNG image is done, the raw pixel data will have that color type and thus
a certain amount of bits per pixel. If you want the output raw image after
decoding to have another color type, a conversion is done by LodePNG.
The PNG specification mentions the following color types:
0: greyscale, bit depths 1, 2, 4, 8, 16
2: RGB, bit depths 8 and 16
3: palette, bit depths 1, 2, 4 and 8
4: greyscale with alpha, bit depths 8 and 16
6: RGBA, bit depths 8 and 16
Bit depth is the amount of bits per color channel.
=Default Behaviour=
By default, the Decoder will convert the data from the PNG to 32-bit RGBA color,
no matter what color type the PNG has, so that the result can be used directly
as a texture in OpenGL etc... without worries about what color type the original
image has.
The Encoder assumes by default that the raw input you give it is a 32-bit RGBA
buffer and will store the PNG as either 32 bit or 24 bit depending on whether
or not any translucent pixels were detected in it.
To get the default behaviour, don't change the values of InfoRaw and InfoPng of
the encoder, and don't change the values of InfoRaw of the decoder.
=Color Conversions=
As explained in the sections about the Encoder and Decoder, you can specify
color types and bit depths in InfoPng and InfoRaw, to change the default behaviour
explained above. (for the Decoder you can only specify the InfoRaw, because the
InfoPng contains what the PNG file has).
To avoid some confusion:
-the Decoder converts from PNG to raw image
-the Encoder converts from raw image to PNG
-the color type and bit depth in InfoRaw, are those of the raw image
-the color type and bit depth in InfoPng, are those of the PNG
-if the color type of the InfoRaw and PNG image aren't the same, a conversion
between the color types is done if the color types are supported
Supported color types:
-Both encoder and decoder use the same converter. So both encoder and decoder
suport the same color types at the input and the output. So the decoder supports
any type of PNG image and can convert it to certain types of raw image, while the
encoder supports any type of raw data but only certain color types for the output PNG.
-The converter can convert from _any_ input color type, to 24-bit RGB or 32-bit RGBA
-The converter can convert from greyscale input color type, to 8-bit greyscale or greyscale with alpha
-If both color types are the same, conversion from anything to anything is possible
-Color types that are invalid according to the PNG specification are not allowed
-When converting from a type with alpha channel to one without, the alpha channel information is discarded
-When converting from a type without alpha channel to one with, the result will be opaque except pixels that have the same color as the color key of the input if one was given
-When converting from 16-bit bitDepth to 8-bit bitDepth, the 16-bit precision information is lost, only the most significant byte is kept
-Converting from color to greyscale is not supported on purpose: choosing what kind of color to greyscale conversion to do is not a decision a PNG codec should make
-Converting from/to a palette type, only keeps the indices, it ignores the colors defined in the palette
No conversion needed...:
-If the color type of the PNG image and raw image are the same, then no
conversion is done, and all color types are supported.
-In the encoder, you can make it save a PNG with any color by giving the
InfoRaw and InfoPng the same color type.
-In the decoder, you can make it store the pixel data in the same color type
as the PNG has, by setting the color_convert setting to false. Settings in
infoRaw are then ignored.
6. info values
--------------
Both the encoder and decoder use a variables of type InfoPng and InfoRaw. Here's
a list of each of the values stored in them:
*) info from the PNG header:
width: width of the image in pixels
height: height of the image in pixels
colorType: color type of the original PNG file
bitDepth: bits per sample
compressionMethod: compression method of the original file. Always 0.
filterMethod: filter method of the original file. Always 0.
interlaceMethod: interlace method of the original file. 0 is no interlace, 1 is adam7 interlace.
Note: width and height are only used as information of a decoded PNG image. When encoding one, you don't have
to specify width and height in an Info struct, but you give them as parameters of the encode function.
*) palette:
This is an std::vector with the colors of the palette. The number of values in the std::vector must always be
4 times the amount of colors. This because there are 4 values per color: R, G, B and A. Even if less color
channels are used, the palette is always in RGBA format, in the order RGBARGBARGBA.....
Note that the palette information from the tRNS chunk is also already included in this palette vector.
If you encode an image with palette, don't forget that you have to set the alpha channels of the palette
too, set them to 255 for an opaque palette. If you leave them at zero, the image will be encoded as
fully invisible. This both for the palette in the infoRaw and the infoPng if the png is to have a palette.
*) transparent color key
color_key_defined: is a transparent color key given?
color_key_r: red/greyscale component of color key
color_key_g: green component of color key
color_key_b: blue component of color key
For greyscale PNGs, r, g and b will all 3 be set to the same.
This color is 8-bit for 8-bit PNGs, 16-bit for 16-bit per channel PNGs.
*) suggested background color
background_defined: is a suggested background color given?
background_r: red component of sugg. background color
background_g: green component of sugg. background color
background_b: blue component of sugg. background color
This color is 8-bit for 8-bit PNGs, 16-bit for 16-bit PNGs
For greyscale PNGs, r, g and b will all 3 be set to the same. When encoding
the encoder writes the red one away.
For palette PNGs: When decoding, the RGB value will be stored, no a palette
index. But when encoding, specify the index of the palette in background_r,
the other two are then ignored.
The decoder pretty much ignores this background color, after all if you make a
PNG translucent normally you intend it to be used against any background, on
websites, as translucent textures in games, ... But you can get the color this
way if needed.
*) text chunks
text_keys: an std::vector of std::strings containing the keywords (see below)
text_strings: an std::vector of std::strings containing the texts (see below)
addText: this function can be used to push back a keyword and text at the same time
The size of text_keys and text_strings must always be the same, as a text
and its key always come in pairs.
Each text chunk in a PNG image has a key and a string. Both the key and the
string are text, but the key can be used to specify the type of information that
is placed in the string. There are a few standard standard keywords recognised
by many programs: Title, Author, Description, Copyright, Creation Time,
Software, Disclaimer, Warning, Source, Comment. It's allowed to use other keys.
The keyword is minimum 1 character and maximum 79 characters long. It's
discouraged to use a single line length longer than 79 characters for texts.
LodePNG currently only supports tEXt chunks, no iTXt or zTXt chunks.
*) additional color info
getBpp(): bits per pixel of the PNG image
getChannels(): amount of color channels of the PNG image
isGreyscaleType(): it's color type 0 or 4
isAlphaType(): it's color type 2 or 6
These values are calculated out of color type and bit depth.
The difference between bits per pixel and bit depth is that bit depth is the
number of bits per color channel, while a pixel can have multiple channels.
7. error values
---------------
The meanings of the LodePNG error values (encoder and decoder errors mixed
through each other):
*) 0: no error, everything went ok
*) 1: the Encoder/Decoder has done nothing yet, so error checking makes no sense yet
*) 10: while huffman decoding: end of input memory reached without endcode
*) 11: while huffman decoding: error in code tree made it jump outside of tree
*) 13: problem while processing dynamic deflate block
*) 14: problem while processing dynamic deflate block
*) 15: problem while processing dynamic deflate block
*) 16: unexisting code while processing dynamic deflate block
*) 17: while inflating: end of out buffer memory reached
*) 18: while inflating: invalid distance code
*) 19: while inflating: end of out buffer memory reached
*) 20: invalid deflate block BTYPE encountered
*) 21: NLEN is not ones complement of LEN in a deflate block
*) 22: while inflating: end of out buffer memory reached.
This can happen if the inflated deflate data is longer than the amount of bytes required to fill up
all the pixels of the image, given the color depth and image dimensions. Something that doesn't
happen in a normal, well encoded, PNG image.
*) 23: while inflating: end of in buffer memory reached
*) 24: invalid FCHECK in zlib header
*) 25: invalid compression method in zlib header
*) 26: FDICT encountered in zlib header while it's not used for PNG
*) 27: PNG file is smaller than a PNG header
*) 28: incorrect PNG signature (the first 8 bytes of the PNG file)
Maybe it's not a PNG, or a PNG file that got corrupted so that the header indicates the corruption.
*) 29: first chunk is not the header chunk
*) 30: chunk length too large, chunk broken off at end of file
*) 31: illegal PNG color type
*) 32: illegal PNG compression method
*) 33: illegal PNG filter method
*) 34: illegal PNG interlace method
*) 35: chunk length of a chunk is too large or the chunk too small
*) 36: illegal PNG filter type encountered
*) 37: illegal bit depth for this color type given
*) 38: the palette is too big (more than 256 colors)
*) 39: more palette alpha values given in tRNS, than there are colors in the palette
*) 40: tRNS chunk has wrong size for greyscale image
*) 41: tRNS chunk has wrong size for RGB image
*) 42: tRNS chunk appeared while it was not allowed for this color type
*) 43: bKGD chunk has wrong size for palette image
*) 44: bKGD chunk has wrong size for greyscale image
*) 45: bKGD chunk has wrong size for RGB image
*) 46: value encountered in indexed image is larger than the palette size (bitdepth == 8). Is the palette too small?
*) 47: value encountered in indexed image is larger than the palette size (bitdepth < 8). Is the palette too small?
*) 48: the input data is empty. Maybe a PNG file you tried to load doesn't exist or is in the wrong path.
*) 49: jumped past memory while generating dynamic huffman tree
*) 50: jumped past memory while generating dynamic huffman tree
*) 51: jumped past memory while inflating huffman block
*) 52: jumped past memory while inflating
*) 53: size of zlib data too small
*) 55: jumped past tree while generating huffman tree, this could be when the
tree will have more leaves than symbols after generating it out of the
given lenghts. They call this an over-subscribed set of lenghts in zlib.
*) 56: given output image colorType or bitDepth not supported for color conversion
*) 57: invalid CRC encountered (checking CRC can be disabled)
*) 58: invalid ADLER32 encountered (checking ADLER32 can be disabled)
*) 59: conversion to unexisting or unsupported color type or bit depth requested by encoder or decoder
*) 60: invalid window size given in the settings of the encoder (must be 0-32768)
*) 61: invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)
*) 62: conversion from non-greyscale color to greyscale color requested by encoder or decoder. LodePNG
leaves the choice of RGB to greyscale conversion formula to the user.
*) 63: length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk (2^31-1)
*) 64: the length of the "end" symbol 256 in the Huffman tree is 0, resulting in the inability of a deflated
block to ever contain an end code, making it impossible to decode in a proper way that follows the
specification.
*) 65: the amount of text_keys and text_strings given to the encoder settings isn't equal. It must be equal.
*) 66: the length of a text chunk keyword given to the encoder is longer than the maximum 79 bytes.
*) 67: the length of a text chunk keyword given to the encoder is smaller than the minimum 1 byte.
*) 68: tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors
*) 69: unknown chunk type with "critical" flag encountered by the decoder
8. file IO
----------
For cases where you want to load the PNG image from a file, you can use your own
file loading code, or the file loading and saving functions provided with
LodePNG. These use the same unsigned char format used by the Decoder and Encoder.
The loadFile function fills the given std::vector up with the file from harddisk
with the given name.
The saveFile function saves the contents of the given buffer to the file
with given name. Warning: this overwrites the contents that were previously in
the file if it already existed, without warning.
Note that you don't have to decode a PNG image from a file, you can as well
retrieve the buffer another way in your code, because the decode function takes
a buffer as parameter, not a filename.
9. compiler support
-------------------
No libraries other than the current standard C++ library are needed to compile
LodePNG. Add the files lodepng.cpp and lodepng.h to your project, include
lodepng.h where needed, and your program can read/write PNG files.
Use optimization! For both the encoder and decoder, compiling with the best
optimizations makes a large difference.
Make sure that LodePNG is compiled with the same compiler of the same version
and with the same settings as the rest of the program, or the interfaces with
std::vectors and std::strings can be incompatible resulting in bad things.
CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets.
*) g++
LodePNG is developed in g++ so this compiler is natively supported. It gives no
warnings with compiler options "-W -Wall -Wextra -pedantic -ansi", with gcc
version 4.1.2 on Linux.
*) Visual Studio 2005 and Visual C++ 2005 Express Edition
As of 4 june 2007 (version 20070604), all Visual Studio 2005 level 3 warnings
are removed, and all crashes related to getting the address of the first
element of an std::vector with size 0, are fixed.
It's hard to guarantee that there will always be 0 warnings in future versions
of LodePNG, because the compiler I use (g++) has a different set of warnings.
*) Visual Studio 6.0
Visual Studio 6.0 deviates too much from the current C++ standard, I can't
support it without making the code less nice, I don't plan to do that.
*) Comeau C/C++
Compiles without problems on the Comeau C/C++ Online Test Drive at
http://www.comeaucomputing.com/tryitout
*) Compilers on Macintosh
I'd love to support Macintosh but don't have one available to test it on.
If it doesn't work with your compiler, maybe it can be gotten to work with the
g++ compiler for Macintosh. Someone reported that it doesn't work well at all
for Macintosh. All information on attempts to get it to work on Mac is welcome.
*) Other Compilers
If you encounter problems on other compilers, I'm happy to help out make LodePNG
support the compiler if it supports the C++ standard well enough. If the
required modification to support the compiler requires using non standard,
lesser or deprecated C++ code or headers, I won't support it.
10. examples
-----------
The decoder and encoder example show the most basic usage of LodePNG (using the
classes, not the simple functions, which would be trivial)
More complex examples can be found in lodepng_examples.cpp
10.1. decoder example
--------------------
////////////////////////////////////////////////////////////////////////////////
#include "lodepng.h"
#include <iostream>
int main(int argc, char *argv[])
{
const char* filename = argc > 1 ? argv[1] : "test.png";
//load and decode
std::vector<unsigned char> buffer, image;
LodePNG::loadFile(buffer, filename); //load the image file with given filename
LodePNG::Decoder decoder;
decoder.decode(image, buffer.size() ? &buffer[0] : 0, (unsigned long)buffer.size()); //decode the png
//if there's an error, display it
if(decoder.hasError()) std::cout << "error: " << decoder.getError() << std::endl;
//the pixels are now in the vector "image", use it as texture, draw it, ...
}
//alternative version using the "simple" function
int main(int argc, char *argv[])
{
const char* filename = argc > 1 ? argv[1] : "test.png";
//load and decode
std::vector<unsigned char> image;
unsigned long w, h;
int error = LodePNG::decode(image, w, h, filename);
//if there's an error, display it
if(error != 0) std::cout << "error: " << error << std::endl;
//the pixels are now in the vector "image", use it as texture, draw it, ...
}
////////////////////////////////////////////////////////////////////////////////
10.2 encoder example
-------------------
////////////////////////////////////////////////////////////////////////////////
#include "lodepng.h"
#include <iostream>
int main(int argc, char *argv[])
{
//check if user gave a filename
if(argc <= 1)
{
std::cout << "please provide a filename to save to\n";
return 0;
}
//generate some image
std::vector<unsigned char> image;
image.resize(512 * 512 * 4);
for(int y = 0; y < 512; y++)
for(int x = 0; x < 512; x++)
{
image[4 * 512 * y + 4 * x + 0] = 255 * !(x & y);
image[4 * 512 * y + 4 * x + 1] = x ^ y;
image[4 * 512 * y + 4 * x + 2] = x | y;
image[4 * 512 * y + 4 * x + 3] = 255;
}
//encode and save
std::vector<unsigned char> buffer;
LodePNG::Encoder encoder;
encoder.encode(buffer, image, 512, 512);
LodePNG::saveFile(buffer, argv[1]);
//the same as the 4 lines of code above, but in 1 call:
//LodePNG::encode(argv[1], image, 512, 512);
}
////////////////////////////////////////////////////////////////////////////////
11. changes
-----------
The version number of LodePNG is the date of the change given in the format
yyyymmdd.
Some changes aren't backwards compatible. Those are indicated with a (!)
symbol.
*) 30 aug 2007: bug fixed which makes this Borland C++ compatible
*) 09 aug 2007: some VS2005 warnings removed again
*) 21 jul 2007: deflate code placed in new namespace separate from zlib code
*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images
*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing
invalid std::vector element [0] fixed, and level 3 and 4 warnings removed
*) 02 jun 2007: made the encoder add a tag with version by default
*) 27 may 2007: zlib and png code separated (but still in the same file),
simple encoder/decoder functions added for more simple usage cases
*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69),
moved some examples from here to lodepng_examples.cpp
*) 12 may 2007: palette decoding bug fixed
*) 24 apr 2007: changed the license from BSD to the zlib license
*) 11 mar 2007: very simple addition: ability to encode bKGD chunks.
*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding
palettized PNG images. Plus little interface change with palette and texts.
*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes.
Fixed a bug where the end code of a block had length 0 in the Huffman tree.
*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented
and supported by the encoder, resulting in smaller PNGs at the output.
*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone.
*) 24 jan 2007: gave encoder an error interface. Added color conversion from any
greyscale type to 8-bit greyscale with or without alpha.
*) 21 jan 2007: (!) Totally changed the interface. It allows more color types
to convert to and is more uniform. See the manual for how it works now.
*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days:
encode/decode custom tEXt chunks, separate classes for zlib & deflate, and
at last made the decoder give errors for incorrect Adler32 or Crc.
*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel.
*) 29 dec 2006: Added support for encoding images without alpha channel, and
cleaned out code as well as making certain parts faster.
*) 28 dec 2006: Added "Settings" to the encoder.
*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now.
Removed some code duplication in the decoder. Fixed little bug in an example.
*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter.
Fixed a bug of the decoder with 16-bit per color.
*) 15 okt 2006: Changed documentation structure
*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the
given image buffer, however for now it's not compressed.
*) 08 sep 2006: (!) Changed to interface with a Decoder class
*) 30 jul 2006: (!) InfoPng , width and height are now retrieved in different
way. Renamed decodePNG to decodePNGGeneric.
*) 29 jul 2006: (!) Changed the interface: image info is now returned as a
struct of type LodePNG::Info, instead of a vector, which was a bit clumsy.
*) 28 jul 2006: Cleaned the code and added new error checks.
Corrected terminology "deflate" into "inflate".
*) 23 jun 2006: Added SDL example in the documentation in the header, this
example allows easy debugging by displaying the PNG and its transparency.
*) 22 jun 2006: (!) Changed way to obtain error value. Added
loadFile function for convenience. Made decodePNG32 faster.
*) 21 jun 2006: (!) Changed type of info vector to unsigned long.
Changed position of palette in info vector. Fixed an important bug that
happened on PNGs with an uncompressed block.
*) 16 jun 2006: Internally changed int into unsigned long where
needed, and performed some optimizations.
*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them
in LodePNG namespace. Changed the order of the parameters. Rewrote the
documentation in the header. Renamed files to lodepng.cpp and lodepng.h
*) 22 apr 2006: Optimized and improved some code
*) 07 sep 2005: (!) Changed to std::vector interface
*) 12 aug 2005: Initial release
12. contact information
-----------------------
Feel free to contact me with suggestions, problems, comments, ... concerning
LodePNG. If you encounter a PNG image that doesn't work properly with this
decoder, feel free to send it and I'll use it to find and fix the problem.
My email address is (puzzle the account and domain together with an @ symbol):
Domain: gmail dot com.
Account: lode dot vandevenne.
Copyright (c) 2005-2007 Lode Vandevenne
*/