basic example using sapi

This commit is contained in:
Andrei Medar 2020-08-07 11:01:41 +00:00
parent 8633f22185
commit d63ada79cf
39 changed files with 24846 additions and 0 deletions

View File

@ -0,0 +1,86 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.16)
project(lodepng_sapi CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED 17)
add_subdirectory(lodepng-master)
# unsandboxed main
add_executable(lodepng_normal main.cc)
target_link_libraries(lodepng_normal PRIVATE lodepng)
# sandboxed main
set(SAPI_ROOT "/usr/local/google/home/amedar/internship/sandboxed-api" CACHE PATH "Path to the Sandboxed API source tree")
#set(SAPI_ENABLE_EXAMPLES OFF CACHE BOOL "")
#set(SAPI_ENABLE_TESTS ON CACHE BOOL "")
add_subdirectory("${SAPI_ROOT}"
"${CMAKE_BINARY_DIR}/sandboxed-api-build"
# Omit this to have the full Sandboxed API in IDE
EXCLUDE_FROM_ALL)
add_sapi_library(
lodepng_sapi
FUNCTIONS lodepng_decode32_file lodepng_encode32_file
INPUTS lodepng-master/lodepng.h
LIBRARY lodepng
LIBRARY_NAME Lodepng
NAMESPACE ""
)
target_include_directories(lodepng_sapi INTERFACE
"${PROJECT_BINARY_DIR}" # To find the generated SAPI header
)
add_executable(lodepng_sandboxed main_sandboxed.cc sandbox.h)
target_link_libraries(lodepng_sandboxed PRIVATE
lodepng_sapi
sapi::sapi
sapi::vars
sapi::status
glog::glog
)
# gtest
include(GoogleTest)
enable_testing()
add_executable(main_unit_test
main_unit_test.cc
)
target_link_libraries(main_unit_test PRIVATE
lodepng_sapi
absl::memory
absl::strings
absl::time
glog::glog
sapi::flags
sapi::sapi
sapi::status
sapi::test_main
sapi::vars
)
gtest_discover_tests(main_unit_test)

View File

@ -0,0 +1,11 @@
TODO
- check return value of functions
- integrate unit testing
- add more functions
- this readme
- remove path from CMakeLists.txt
- include abseil flags for unit testing
- improve tests (images, generating images etc.)
- clear redundant includes
- check if security policy can be stricter

View File

@ -0,0 +1 @@
/usr/local/google/home/amedar/internship/sandboxed-api/build

View File

@ -0,0 +1,15 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_library(lodepng STATIC lodepng.cpp lodepng.h)

View File

@ -0,0 +1,21 @@
Copyright (c) 2005-2018 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.

View File

@ -0,0 +1,34 @@
# This makefile only makes the unit test, benchmark and pngdetail and showpng
# utilities. It does not make the PNG codec itself as shared or static library.
# That is because:
# LodePNG itself has only 1 source file (lodepng.cpp, can be renamed to
# lodepng.c) and is intended to be included as source file in other projects and
# their build system directly.
CC ?= gcc
CXX ?= g++
override CFLAGS := -W -Wall -Wextra -ansi -pedantic -O3 -Wno-unused-function $(CFLAGS)
override CXXFLAGS := -W -Wall -Wextra -ansi -pedantic -O3 $(CXXFLAGS)
all: unittest benchmark pngdetail showpng
%.o: %.cpp
@mkdir -p `dirname $@`
$(CXX) -I ./ $(CXXFLAGS) -c $< -o $@
unittest: lodepng.o lodepng_util.o lodepng_unittest.o
$(CXX) $^ $(CXXFLAGS) -o $@
benchmark: lodepng.o lodepng_benchmark.o
$(CXX) $^ $(CXXFLAGS) -lSDL -o $@
pngdetail: lodepng.o lodepng_util.o pngdetail.o
$(CXX) $^ $(CXXFLAGS) -o $@
showpng: lodepng.o examples/example_sdl.o
$(CXX) -I ./ $^ $(CXXFLAGS) -lSDL -o $@
clean:
rm -f unittest benchmark pngdetail showpng lodepng_unittest.o lodepng_benchmark.o lodepng.o lodepng_util.o pngdetail.o examples/example_sdl.o

View File

@ -0,0 +1,75 @@
LodePNG
-------
PNG encoder and decoder in C and C++, without dependencies
Home page: http://lodev.org/lodepng/
### Documentation
Detailed documentation is included in a large comment in the second half of the
header file `lodepng.h`.
Source code examples using LodePNG can be found in the examples directory.
An FAQ can be found on http://lodev.org/lodepng/
### Building
Only two files are needed to encode and decode PNGs:
* `lodepng.cpp` (or renamed to `lodepng.c`)
* `lodepng.h`
All other files are just source code examples, tests, misc utilities, etc...,
which are normally not needed in projects using this.
You can include the files directly in your project's source tree and its
makefile, IDE project file, or other build system. No library is necessary.
In addition to C++, LodePNG also supports ANSI C (C89), with all the same
functionality: C++ only adds extra convenience API.
For C, rename `lodepng.cpp` to `lodepng.c`.
Consider using git submodules to include LodePNG in your project.
### Compiling in C++
If you have a hypothetical `your_program.cpp` that #includes and uses `lodepng.h`,
you can build as follows:
`g++ your_program.cpp lodepng.cpp -Wall -Wextra -pedantic -ansi -O3`
or:
`clang++ your_program.cpp lodepng.cpp -Wall -Wextra -pedantic -ansi -O3`
This shows compiler flags it was designed for, but normally one would use the
compiler or build system of their project instead of those commands, and other
C++ compilers are supported.
### Compiling in C
Rename `lodepng.cpp` to `lodepng.c` for this.
If you have a hypothetical your_program.c that #includes and uses lodepng.h,
you can build as follows:
`gcc your_program.c lodepng.c -ansi -pedantic -Wall -Wextra -O3`
or
`clang your_program.c lodepng.c -ansi -pedantic -Wall -Wextra -O3`
This shows compiler flags it was designed for, but normally one would use the
compiler or build system of their project instead of those commands, and other
C compilers are supported.
### Makefile
There is a Makefile, but this is not intended for using LodePNG itself since the
way to use that one is to include its source files in your program. The Makefile
only builds development and testing utilities. It can be used as follows:
`make -j`

View File

@ -0,0 +1,101 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
//g++ lodepng.cpp example_4bit_palette.cpp -ansi -pedantic -Wall -Wextra -O3
/*
LodePNG 4-bit palette example.
This example encodes a 511x511 PNG with a 4-bit palette.
Both image and palette contain sine waves, resulting in a sort of plasma.
The 511 (rather than power of two 512) size is of course chosen on purpose to
confirm that scanlines not filling up an entire byte size are working.
NOTE: a PNG image with a translucent palette is perfectly valid. However there
exist some programs that cannot correctly read those, including, surprisingly,
Gimp 2.8 image editor (until you set mode to RGB).
*/
#include <cmath>
#include <iostream>
#include "lodepng.h"
int main(int argc, char *argv[]) {
//check if user gave a filename
if(argc < 2) {
std::cout << "please provide a filename to save to" << std::endl;
return 0;
}
//create encoder and set settings and info (optional)
lodepng::State state;
//generate palette
for(int i = 0; i < 16; i++) {
unsigned char r = 127 * (1 + std::sin(5 * i * 6.28318531 / 16));
unsigned char g = 127 * (1 + std::sin(2 * i * 6.28318531 / 16));
unsigned char b = 127 * (1 + std::sin(3 * i * 6.28318531 / 16));
unsigned char a = 63 * (1 + std::sin(8 * i * 6.28318531 / 16)) + 128; /*alpha channel of the palette (tRNS chunk)*/
//palette must be added both to input and output color mode, because in this
//sample both the raw image and the expected PNG image use that palette.
lodepng_palette_add(&state.info_png.color, r, g, b, a);
lodepng_palette_add(&state.info_raw, r, g, b, a);
}
//both the raw image and the encoded image must get colorType 3 (palette)
state.info_png.color.colortype = LCT_PALETTE; //if you comment this line, and create the above palette in info_raw instead, then you get the same image in a RGBA PNG.
state.info_png.color.bitdepth = 4;
state.info_raw.colortype = LCT_PALETTE;
state.info_raw.bitdepth = 4;
state.encoder.auto_convert = 0; //we specify ourselves exactly what output PNG color mode we want
//generate some image
const unsigned w = 511;
const unsigned h = 511;
std::vector<unsigned char> image;
image.resize((w * h * 4 + 7) / 8, 0);
for(unsigned y = 0; y < h; y++)
for(unsigned x = 0; x < w; x++) {
size_t byte_index = (y * w + x) / 2;
bool byte_half = (y * w + x) % 2 == 1;
int color = (int)(4 * ((1 + std::sin(2.0 * 6.28318531 * x / (double)w))
+ (1 + std::sin(2.0 * 6.28318531 * y / (double)h))) );
image[byte_index] |= (unsigned char)(color << (byte_half ? 0 : 4));
}
//encode and save
std::vector<unsigned char> buffer;
unsigned error = lodepng::encode(buffer, image.empty() ? 0 : &image[0], w, h, state);
if(error) {
std::cout << "encoder error " << error << ": "<< lodepng_error_text(error) << std::endl;
return 0;
}
lodepng::save_file(buffer, argv[1]);
}

View File

@ -0,0 +1,125 @@
/*
LodePNG Examples
Copyright (c) 2005-2010 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.
*/
/*
Load a BMP image and convert it to a PNG image. This example also shows how
to use other data with the same memory structure as BMP, such as the image
format native to win32, GDI (HBITMAP, BITMAPINFO, ...) often encountered if
you're programming for Windows in Visual Studio.
This example only supports uncompressed 24-bit RGB or 32-bit RGBA bitmaps.
For other types of BMP's, use a full fledged BMP decoder, or convert the
bitmap to 24-bit or 32-bit format.
NOTE: it overwrites the output file without warning if it exists!
*/
//g++ lodepng.cpp example_bmp2png.cpp -ansi -pedantic -Wall -Wextra -O3
#include "lodepng.h"
#include <iostream>
//returns 0 if all went ok, non-0 if error
//output image is always given in RGBA (with alpha channel), even if it's a BMP without alpha channel
unsigned decodeBMP(std::vector<unsigned char>& image, unsigned& w, unsigned& h, const std::vector<unsigned char>& bmp) {
static const unsigned MINHEADER = 54; //minimum BMP header size
if(bmp.size() < MINHEADER) return -1;
if(bmp[0] != 'B' || bmp[1] != 'M') return 1; //It's not a BMP file if it doesn't start with marker 'BM'
unsigned pixeloffset = bmp[10] + 256 * bmp[11]; //where the pixel data starts
//read width and height from BMP header
w = bmp[18] + bmp[19] * 256;
h = bmp[22] + bmp[23] * 256;
//read number of channels from BMP header
if(bmp[28] != 24 && bmp[28] != 32) return 2; //only 24-bit and 32-bit BMPs are supported.
unsigned numChannels = bmp[28] / 8;
//The amount of scanline bytes is width of image times channels, with extra bytes added if needed
//to make it a multiple of 4 bytes.
unsigned scanlineBytes = w * numChannels;
if(scanlineBytes % 4 != 0) scanlineBytes = (scanlineBytes / 4) * 4 + 4;
unsigned dataSize = scanlineBytes * h;
if(bmp.size() < dataSize + pixeloffset) return 3; //BMP file too small to contain all pixels
image.resize(w * h * 4);
/*
There are 3 differences between BMP and the raw image buffer for LodePNG:
-it's upside down
-it's in BGR instead of RGB format (or BRGA instead of RGBA)
-each scanline has padding bytes to make it a multiple of 4 if needed
The 2D for loop below does all these 3 conversions at once.
*/
for(unsigned y = 0; y < h; y++)
for(unsigned x = 0; x < w; x++) {
//pixel start byte position in the BMP
unsigned bmpos = pixeloffset + (h - y - 1) * scanlineBytes + numChannels * x;
//pixel start byte position in the new raw image
unsigned newpos = 4 * y * w + 4 * x;
if(numChannels == 3) {
image[newpos + 0] = bmp[bmpos + 2]; //R
image[newpos + 1] = bmp[bmpos + 1]; //G
image[newpos + 2] = bmp[bmpos + 0]; //B
image[newpos + 3] = 255; //A
} else {
image[newpos + 0] = bmp[bmpos + 2]; //R
image[newpos + 1] = bmp[bmpos + 1]; //G
image[newpos + 2] = bmp[bmpos + 0]; //B
image[newpos + 3] = bmp[bmpos + 3]; //A
}
}
return 0;
}
int main(int argc, char *argv[]) {
if(argc < 3) {
std::cout << "Please provice input PNG and output BMP file names" << std::endl;
return 0;
}
std::vector<unsigned char> bmp;
lodepng::load_file(bmp, argv[1]);
std::vector<unsigned char> image;
unsigned w, h;
unsigned error = decodeBMP(image, w, h, bmp);
if(error) {
std::cout << "BMP decoding error " << error << std::endl;
return 0;
}
std::vector<unsigned char> png;
error = lodepng::encode(png, image, w, h);
if(error) {
std::cout << "PNG encoding error " << error << ": " << lodepng_error_text(error) << std::endl;
return 0;
}
lodepng::save_file(png, argv[2]);
}

View File

@ -0,0 +1,109 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
#include "lodepng.h"
#include <stdio.h>
#include <stdlib.h>
/*
3 ways to decode a PNG from a file to RGBA pixel data (and 2 in-memory ways).
*/
/*
Example 1
Decode from disk to raw pixels with a single function call
*/
void decodeOneStep(const char* filename) {
unsigned error;
unsigned char* image = 0;
unsigned width, height;
error = lodepng_decode32_file(&image, &width, &height, filename);
if(error) printf("error %u: %s\n", error, lodepng_error_text(error));
/*use image here*/
free(image);
}
/*
Example 2
Load PNG file from disk to memory first, then decode to raw pixels in memory.
*/
void decodeTwoSteps(const char* filename) {
unsigned error;
unsigned char* image = 0;
unsigned width, height;
unsigned char* png = 0;
size_t pngsize;
error = lodepng_load_file(&png, &pngsize, filename);
if(!error) error = lodepng_decode32(&image, &width, &height, png, pngsize);
if(error) printf("error %u: %s\n", error, lodepng_error_text(error));
free(png);
/*use image here*/
free(image);
}
/*
Example 3
Load PNG file from disk using a State, normally needed for more advanced usage.
*/
void decodeWithState(const char* filename) {
unsigned error;
unsigned char* image = 0;
unsigned width, height;
unsigned char* png = 0;
size_t pngsize;
LodePNGState state;
lodepng_state_init(&state);
/*optionally customize the state*/
error = lodepng_load_file(&png, &pngsize, filename);
if(!error) error = lodepng_decode(&image, &width, &height, &state, png, pngsize);
if(error) printf("error %u: %s\n", error, lodepng_error_text(error));
free(png);
/*use image here*/
/*state contains extra information about the PNG such as text chunks, ...*/
lodepng_state_cleanup(&state);
free(image);
}
int main(int argc, char *argv[]) {
const char* filename = argc > 1 ? argv[1] : "test.png";
decodeOneStep(filename);
return 0;
}

View File

@ -0,0 +1,91 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
#include "lodepng.h"
#include <iostream>
/*
3 ways to decode a PNG from a file to RGBA pixel data (and 2 in-memory ways).
*/
//g++ lodepng.cpp example_decode.cpp -ansi -pedantic -Wall -Wextra -O3
//Example 1
//Decode from disk to raw pixels with a single function call
void decodeOneStep(const char* filename) {
std::vector<unsigned char> image; //the raw pixels
unsigned width, height;
//decode
unsigned error = lodepng::decode(image, width, height, filename);
//if there's an error, display it
if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
//the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ...
}
//Example 2
//Load PNG file from disk to memory first, then decode to raw pixels in memory.
void decodeTwoSteps(const char* filename) {
std::vector<unsigned char> png;
std::vector<unsigned char> image; //the raw pixels
unsigned width, height;
//load and decode
unsigned error = lodepng::load_file(png, filename);
if(!error) error = lodepng::decode(image, width, height, png);
//if there's an error, display it
if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
//the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ...
}
//Example 3
//Load PNG file from disk using a State, normally needed for more advanced usage.
void decodeWithState(const char* filename) {
std::vector<unsigned char> png;
std::vector<unsigned char> image; //the raw pixels
unsigned width, height;
lodepng::State state; //optionally customize this one
unsigned error = lodepng::load_file(png, filename); //load the image file with given filename
if(!error) error = lodepng::decode(image, width, height, state, png);
//if there's an error, display it
if(error) std::cout << "decoder error " << error << ": "<< lodepng_error_text(error) << std::endl;
//the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ...
//State state contains extra information about the PNG such as text chunks, ...
}
int main(int argc, char *argv[]) {
const char* filename = argc > 1 ? argv[1] : "test.png";
decodeOneStep(filename);
}

View File

@ -0,0 +1,111 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
#include "lodepng.h"
#include <stdio.h>
#include <stdlib.h>
/*
3 ways to encode a PNG from RGBA pixel data to a file (and 2 in-memory ways).
NOTE: this samples overwrite the file or test.png without warning!
*/
/*
Example 1
Encode from raw pixels to disk with a single function call
The image argument has width * height RGBA pixels or width * height * 4 bytes
*/
void encodeOneStep(const char* filename, const unsigned char* image, unsigned width, unsigned height) {
/*Encode the image*/
unsigned error = lodepng_encode32_file(filename, image, width, height);
/*if there's an error, display it*/
if(error) printf("error %u: %s\n", error, lodepng_error_text(error));
}
/*
Example 2
Encode from raw pixels to an in-memory PNG file first, then write it to disk
The image argument has width * height RGBA pixels or width * height * 4 bytes
*/
void encodeTwoSteps(const char* filename, const unsigned char* image, unsigned width, unsigned height) {
unsigned char* png;
size_t pngsize;
unsigned error = lodepng_encode32(&png, &pngsize, image, width, height);
if(!error) lodepng_save_file(png, pngsize, filename);
/*if there's an error, display it*/
if(error) printf("error %u: %s\n", error, lodepng_error_text(error));
free(png);
}
/*
Example 3
Save a PNG file to disk using a State, normally needed for more advanced usage.
The image argument has width * height RGBA pixels or width * height * 4 bytes
*/
void encodeWithState(const char* filename, const unsigned char* image, unsigned width, unsigned height) {
unsigned error;
unsigned char* png;
size_t pngsize;
LodePNGState state;
lodepng_state_init(&state);
/*optionally customize the state*/
error = lodepng_encode(&png, &pngsize, image, width, height, &state);
if(!error) lodepng_save_file(png, pngsize, filename);
/*if there's an error, display it*/
if(error) printf("error %u: %s\n", error, lodepng_error_text(error));
lodepng_state_cleanup(&state);
free(png);
}
int main(int argc, char *argv[]) {
const char* filename = argc > 1 ? argv[1] : "test.png";
/*generate some image*/
unsigned width = 512, height = 512;
unsigned char* image = malloc(width * height * 4);
unsigned x, y;
for(y = 0; y < height; y++)
for(x = 0; x < width; x++) {
image[4 * width * y + 4 * x + 0] = 255 * !(x & y);
image[4 * width * y + 4 * x + 1] = x ^ y;
image[4 * width * y + 4 * x + 2] = x | y;
image[4 * width * y + 4 * x + 3] = 255;
}
/*run an example*/
encodeOneStep(filename, image, width, height);
free(image);
return 0;
}

View File

@ -0,0 +1,92 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
#include "lodepng.h"
#include <iostream>
/*
3 ways to encode a PNG from RGBA pixel data to a file (and 2 in-memory ways).
NOTE: this samples overwrite the file or test.png without warning!
*/
//g++ lodepng.cpp examples/example_encode.cpp -I./ -ansi -pedantic -Wall -Wextra -O3
//Example 1
//Encode from raw pixels to disk with a single function call
//The image argument has width * height RGBA pixels or width * height * 4 bytes
void encodeOneStep(const char* filename, std::vector<unsigned char>& image, unsigned width, unsigned height) {
//Encode the image
unsigned error = lodepng::encode(filename, image, width, height);
//if there's an error, display it
if(error) std::cout << "encoder error " << error << ": "<< lodepng_error_text(error) << std::endl;
}
//Example 2
//Encode from raw pixels to an in-memory PNG file first, then write it to disk
//The image argument has width * height RGBA pixels or width * height * 4 bytes
void encodeTwoSteps(const char* filename, std::vector<unsigned char>& image, unsigned width, unsigned height) {
std::vector<unsigned char> png;
unsigned error = lodepng::encode(png, image, width, height);
if(!error) lodepng::save_file(png, filename);
//if there's an error, display it
if(error) std::cout << "encoder error " << error << ": "<< lodepng_error_text(error) << std::endl;
}
//Example 3
//Save a PNG file to disk using a State, normally needed for more advanced usage.
//The image argument has width * height RGBA pixels or width * height * 4 bytes
void encodeWithState(const char* filename, std::vector<unsigned char>& image, unsigned width, unsigned height) {
std::vector<unsigned char> png;
lodepng::State state; //optionally customize this one
unsigned error = lodepng::encode(png, image, width, height, state);
if(!error) lodepng::save_file(png, filename);
//if there's an error, display it
if(error) std::cout << "encoder error " << error << ": "<< lodepng_error_text(error) << std::endl;
}
//saves image to filename given as argument. Warning, this overwrites the file without warning!
int main(int argc, char *argv[]) {
//NOTE: this sample will overwrite the file or test.png without warning!
const char* filename = argc > 1 ? argv[1] : "test.png";
//generate some image
unsigned width = 512, height = 512;
std::vector<unsigned char> image;
image.resize(width * height * 4);
for(unsigned y = 0; y < height; y++)
for(unsigned x = 0; x < width; x++) {
image[4 * width * y + 4 * x + 0] = 255 * !(x & y);
image[4 * width * y + 4 * x + 1] = x ^ y;
image[4 * width * y + 4 * x + 2] = x | y;
image[4 * width * y + 4 * x + 3] = 255;
}
encodeOneStep(filename, image, width, height);
}

View File

@ -0,0 +1,76 @@
/*
LodePNG Examples
Copyright (c) 2005-2015 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.
*/
//g++ -I ./ lodepng.cpp examples/example_encode_type.cpp -ansi -pedantic -Wall -Wextra -O3
/*
This example shows how to enforce a certain color type of the PNG image when
encoding a PNG (because by default, LodePNG automatically chooses an optimal
color type, no matter what your raw data's color type is)
*/
#include <cmath>
#include <iostream>
#include "lodepng.h"
int main(int argc, char *argv[]) {
//check if user gave a filename
if(argc < 2) {
std::cout << "please provide a filename to save to" << std::endl;
return 0;
}
//generate some image
const unsigned w = 256;
const unsigned h = 256;
std::vector<unsigned char> image(w * h * 4);
for(unsigned y = 0; y < h; y++)
for(unsigned x = 0; x < w; x++) {
int index = y * w * 4 + x * 4;
image[index + 0] = 0;
image[index + 1] = 0;
image[index + 2] = 0;
image[index + 3] = 255;
}
// we're going to encode with a state rather than a convenient function, because enforcing a color type requires setting options
lodepng::State state;
// input color type
state.info_raw.colortype = LCT_RGBA;
state.info_raw.bitdepth = 8;
// output color type
state.info_png.color.colortype = LCT_RGBA;
state.info_png.color.bitdepth = 8;
state.encoder.auto_convert = 0; // without this, it would ignore the output color type specified above and choose an optimal one instead
//encode and save
std::vector<unsigned char> buffer;
unsigned error = lodepng::encode(buffer, &image[0], w, h, state);
if(error) std::cout << "encoder error " << error << ": "<< lodepng_error_text(error) << std::endl;
else lodepng::save_file(buffer, argv[1]);
}

View File

@ -0,0 +1,91 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
#include "lodepng.h"
#include <iostream>
#include <stdlib.h>
/*
Encodes given file as a gzip file.
See also the gzip specification, RFC 1952: http://www.gzip.org/zlib/rfc-gzip.html
*/
//g++ lodepng.cpp example_gzip.cpp -ansi -pedantic -Wall -Wextra -O3
//saves image to filename given as argument. Warning, this overwrites the file without warning!
int main(int argc, char *argv[]) {
if(argc < 2) {
std::cout << "Please provide input filename (output is input with .gz)" << std::endl;
return 0;
}
//NOTE: this sample will overwrite the output file without warning!
std::string infilename = argv[1];
std::string outfilename = infilename + ".gz";
std::vector<unsigned char> in;
lodepng::load_file(in, infilename);
size_t outsize = 10;
unsigned char* out = (unsigned char*)malloc(outsize);
out[0] = 31; //ID1
out[1] = 139; //ID2
out[2] = 8; //CM
out[3] = 0; //FLG
//MTIME
out[4] = 0;
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 2; //2 = slow, 4 = fast compression
out[9] = 255; //OS unknown
lodepng_deflate(&out, &outsize, &in[0], in.size(), &lodepng_default_compress_settings);
unsigned crc = lodepng_crc32(&in[0], in.size());
size_t footer = outsize;
outsize += 8;
out = (unsigned char*)realloc(out, outsize);
//CRC
out[footer + 0] = crc % 256;
out[footer + 1] = (crc >> 8) % 256;
out[footer + 2] = (crc >> 16) % 256;
out[footer + 3] = (crc >> 24) % 256;
//ISIZE
out[footer + 4] = in.size() % 256;
out[footer + 5] = (in.size() >> 8) % 256;
out[footer + 6] = (in.size() >> 16) % 256;
out[footer + 7] = (in.size() >> 24) % 256;
lodepng_save_file(out, outsize, outfilename.c_str());
free(out);
}

View File

@ -0,0 +1,153 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
//Compile command for Linux:
//g++ lodepng.cpp example_opengl.cpp -lSDL -lGL -O3
/*
LodePNG OpenGL example. Decodes a PNG and shows it in OpenGL. PNG filename
should be given as a command line parameter.
It's written for the most basic old OpenGL version, and a correction for non
power of two textures had to be added.
Only very few lines on the sample are about loading the PNG. Most of the
sample lines show a way to render a texture in 2D in OpenGL.
No fancy 3D graphics are shown, it only shows the image statically. The sample
shows LodePNG can be used to load PNG images as textures in OpenGL.
*/
#include "lodepng.h"
#include <iostream>
#include <SDL/SDL.h>
#include <GL/gl.h>
int main(int argc, char *argv[]) {
if(argc < 2) {
std::cout << "Please provide a filename." << std::endl;
return 1;
}
const char* filename = argv[1];
// Load file and decode image.
std::vector<unsigned char> image;
unsigned width, height;
unsigned error = lodepng::decode(image, width, height, filename);
// If there's an error, display it.
if(error != 0) {
std::cout << "error " << error << ": " << lodepng_error_text(error) << std::endl;
return 1;
}
// Here the PNG is loaded in "image". All the rest of the code is SDL and OpenGL stuff.
int screenw = width;
if(screenw > 1024) screenw = 1024;
int screenh = height;
if(screenh > 768) screenw = 768;
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << "Error: Unable to init SDL: " << SDL_GetError() << std::endl;
return 1;
}
SDL_Surface* scr = SDL_SetVideoMode(screenw, screenh, 32, SDL_OPENGL);
if(scr == 0) {
std::cout << "Error: Unable to set video. SDL error message: " << SDL_GetError() << std::endl;
return 1;
}
// The official code for "Setting Your Raster Position to a Pixel Location" (i.e. set up a camera for 2D screen)
glViewport(0, 0, screenw, screenh);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, screenw, screenh, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Make some OpenGL properties better for 2D and enable alpha channel.
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
if(glGetError() != GL_NO_ERROR) {
std::cout << "Error initing GL" << std::endl;
return 1;
}
// Texture size must be power of two for the primitive OpenGL version this is written for. Find next power of two.
size_t u2 = 1; while(u2 < width) u2 *= 2;
size_t v2 = 1; while(v2 < height) v2 *= 2;
// Ratio for power of two version compared to actual version, to render the non power of two image with proper size.
double u3 = (double)width / u2;
double v3 = (double)height / v2;
// Make power of two version of the image.
std::vector<unsigned char> image2(u2 * v2 * 4);
for(size_t y = 0; y < height; y++)
for(size_t x = 0; x < width; x++)
for(size_t c = 0; c < 4; c++) {
image2[4 * u2 * y + 4 * x + c] = image[4 * width * y + 4 * x + c];
}
// Enable the texture for OpenGL.
glEnable(GL_TEXTURE_2D);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //GL_NEAREST = no smoothing
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 4, u2, v2, 0, GL_RGBA, GL_UNSIGNED_BYTE, &image2[0]);
bool done = false;
SDL_Event event = {0};
glColor4ub(255, 255, 255, 255);
while(!done) {
// Quit the loop when receiving quit event.
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT) done = 1;
}
// Draw the texture on a quad, using u3 and v3 to correct non power of two texture size.
glBegin(GL_QUADS);
glTexCoord2d( 0, 0); glVertex2f( 0, 0);
glTexCoord2d(u3, 0); glVertex2f(width, 0);
glTexCoord2d(u3, v3); glVertex2f(width, height);
glTexCoord2d( 0, v3); glVertex2f( 0, height);
glEnd();
// Redraw and clear screen.
SDL_GL_SwapBuffers();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Limit frames per second, to not heat up the CPU and GPU too much.
SDL_Delay(16);
}
}

View File

@ -0,0 +1,129 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
/*
This example saves the PNG with the best compression LodePNG can do, and with
unnecessary chunks removed. It tries out several combinations of settings and
keeps the smallest one.
NOTE: This is not as good as a true PNG optimizer like optipng or pngcrush.
*/
//g++ lodepng.cpp example_optimize_png.cpp -ansi -pedantic -Wall -Wextra -O3
#include "lodepng.h"
#include <iostream>
int main(int argc, char *argv[]) {
std::vector<unsigned char> image;
unsigned w, h;
std::vector<unsigned char> buffer;
unsigned error;
//check if user gave a filename
if(argc < 3) {
std::cout << "please provide in and out filename" << std::endl;
return 0;
}
lodepng::load_file(buffer, argv[1]);
error = lodepng::decode(image, w, h, buffer);
if(error) {
std::cout << "decoding error " << error << ": " << lodepng_error_text(error) << std::endl;
return 0;
}
size_t origsize = buffer.size();
std::cout << "Original size: " << origsize << " (" << (origsize / 1024) << "K)" << std::endl;
buffer.clear();
//Now encode as hard as possible with several filter types and window sizes
lodepng::State state;
state.encoder.filter_palette_zero = 0; //We try several filter types, including zero, allow trying them all on palette images too.
state.encoder.add_id = false; //Don't add LodePNG version chunk to save more bytes
state.encoder.text_compression = 1; //Not needed because we don't add text chunks, but this demonstrates another optimization setting
state.encoder.zlibsettings.nicematch = 258; //Set this to the max possible, otherwise it can hurt compression
state.encoder.zlibsettings.lazymatching = 1; //Definitely use lazy matching for better compression
state.encoder.zlibsettings.windowsize = 32768; //Use maximum possible window size for best compression
size_t bestsize = 0;
bool inited = false;
int beststrategy = 0;
LodePNGFilterStrategy strategies[4] = { LFS_ZERO, LFS_MINSUM, LFS_ENTROPY, LFS_BRUTE_FORCE };
std::string strategynames[4] = { "LFS_ZERO", "LFS_MINSUM", "LFS_ENTROPY", "LFS_BRUTE_FORCE" };
// min match 3 allows all deflate lengths. min match 6 is similar to "Z_FILTERED" of zlib.
int minmatches[2] = { 3, 6 };
int bestminmatch = 0;
int autoconverts[2] = { 0, 1 };
std::string autoconvertnames[2] = { "0", "1" };
int bestautoconvert = 0;
int bestblocktype = 0;
// Try out all combinations of everything
for(int i = 0; i < 4; i++) //filter strategy
for(int j = 0; j < 2; j++) //min match
for(int k = 0; k < 2; k++) //block type (for small images only)
for(int l = 0; l < 2; l++) { //color convert strategy
if(bestsize > 3000 && (k > 0 || l > 0)) continue; /* these only make sense on small images */
std::vector<unsigned char> temp;
state.encoder.filter_strategy = strategies[i];
state.encoder.zlibsettings.minmatch = minmatches[j];
state.encoder.zlibsettings.btype = k == 0 ? 2 : 1;
state.encoder.auto_convert = autoconverts[l];
error = lodepng::encode(temp, image, w, h, state);
if(error)
{
std::cout << "encoding error " << error << ": " << lodepng_error_text(error) << std::endl;
return 0;
}
if(!inited || temp.size() < bestsize)
{
bestsize = temp.size();
beststrategy = i;
bestminmatch = state.encoder.zlibsettings.minmatch;
bestautoconvert = l;
bestblocktype = state.encoder.zlibsettings.btype;
temp.swap(buffer);
inited = true;
}
}
std::cout << "Chosen filter strategy: " << strategynames[beststrategy] << std::endl;
std::cout << "Chosen min match: " << bestminmatch << std::endl;
std::cout << "Chosen block type: " << bestblocktype << std::endl;
std::cout << "Chosen auto convert: " << autoconvertnames[bestautoconvert] << std::endl;
lodepng::save_file(buffer, argv[2]);
std::cout << "New size: " << buffer.size() << " (" << (buffer.size() / 1024) << "K)" << std::endl;
}

View File

@ -0,0 +1,125 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
#include "lodepng.h"
#include <iostream>
/*
This example converts a PNG file to a BMP file.
NOTE: it overwrites the output file without warning if it exists!
Give the PNG and the BMP file names as command line arguments.
*/
/*
g++ lodepng.cpp example_png2bmp.cpp -Wall -Wextra -pedantic -ansi -lSDL -O3
*/
//Input image must be RGB buffer (3 bytes per pixel), but you can easily make it
//support RGBA input and output by changing the inputChannels and/or outputChannels
//in the function to 4.
void encodeBMP(std::vector<unsigned char>& bmp, const unsigned char* image, int w, int h) {
//3 bytes per pixel used for both input and output.
int inputChannels = 3;
int outputChannels = 3;
//bytes 0-13
bmp.push_back('B'); bmp.push_back('M'); //0: bfType
bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); //2: bfSize; size not yet known for now, filled in later.
bmp.push_back(0); bmp.push_back(0); //6: bfReserved1
bmp.push_back(0); bmp.push_back(0); //8: bfReserved2
bmp.push_back(54 % 256); bmp.push_back(54 / 256); bmp.push_back(0); bmp.push_back(0); //10: bfOffBits (54 header bytes)
//bytes 14-53
bmp.push_back(40); bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); //14: biSize
bmp.push_back(w % 256); bmp.push_back(w / 256); bmp.push_back(0); bmp.push_back(0); //18: biWidth
bmp.push_back(h % 256); bmp.push_back(h / 256); bmp.push_back(0); bmp.push_back(0); //22: biHeight
bmp.push_back(1); bmp.push_back(0); //26: biPlanes
bmp.push_back(outputChannels * 8); bmp.push_back(0); //28: biBitCount
bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); //30: biCompression
bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); //34: biSizeImage
bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); //38: biXPelsPerMeter
bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); //42: biYPelsPerMeter
bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); //46: biClrUsed
bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); bmp.push_back(0); //50: biClrImportant
/*
Convert the input RGBRGBRGB pixel buffer to the BMP pixel buffer format. There are 3 differences with the input buffer:
-BMP stores the rows inversed, from bottom to top
-BMP stores the color channels in BGR instead of RGB order
-BMP requires each row to have a multiple of 4 bytes, so sometimes padding bytes are added between rows
*/
int imagerowbytes = outputChannels * w;
imagerowbytes = imagerowbytes % 4 == 0 ? imagerowbytes : imagerowbytes + (4 - imagerowbytes % 4); //must be multiple of 4
for(int y = h - 1; y >= 0; y--) { //the rows are stored inversed in bmp
int c = 0;
for(int x = 0; x < imagerowbytes; x++) {
if(x < w * outputChannels) {
int inc = c;
//Convert RGB(A) into BGR(A)
if(c == 0) inc = 2;
else if(c == 2) inc = 0;
bmp.push_back(image[inputChannels * (w * y + x / outputChannels) + inc]);
}
else bmp.push_back(0);
c++;
if(c >= outputChannels) c = 0;
}
}
// Fill in the size
bmp[2] = bmp.size() % 256;
bmp[3] = (bmp.size() / 256) % 256;
bmp[4] = (bmp.size() / 65536) % 256;
bmp[5] = bmp.size() / 16777216;
}
int main(int argc, char *argv[]) {
if(argc < 3) {
std::cout << "Please provice input PNG and output BMP file names" << std::endl;
return 0;
}
const char* infile = argv[1];
const char* outfile = argv[2];
std::vector<unsigned char> image; //the raw pixels
unsigned width, height;
unsigned error = lodepng::decode(image, width, height, infile, LCT_RGB, 8);
if(error) {
std::cout << "error " << error << ": " << lodepng_error_text(error) << std::endl;
return 0;
}
std::vector<unsigned char> bmp;
encodeBMP(bmp, &image[0], width, height);
lodepng::save_file(bmp, outfile);
}

View File

@ -0,0 +1,313 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
//g++ lodepng.cpp example_png_info.cpp -ansi -pedantic -Wall -Wextra -lSDL -O3
/*
This sample shows a lot of information in the console about a PNG file,
including color type, text chunks, the names of all chunks in the image,
etc...
*/
#include "lodepng.h"
#include <iostream>
/*
Display general info about the PNG.
*/
void displayPNGInfo(const LodePNGInfo& info) {
const LodePNGColorMode& color = info.color;
std::cout << "Compression method: " << info.compression_method << std::endl;
std::cout << "Filter method: " << info.filter_method << std::endl;
std::cout << "Interlace method: " << info.interlace_method << std::endl;
std::cout << "Color type: " << color.colortype << std::endl;
std::cout << "Bit depth: " << color.bitdepth << std::endl;
std::cout << "Bits per pixel: " << lodepng_get_bpp(&color) << std::endl;
std::cout << "Channels per pixel: " << lodepng_get_channels(&color) << std::endl;
std::cout << "Is greyscale type: " << lodepng_is_greyscale_type(&color) << std::endl;
std::cout << "Can have alpha: " << lodepng_can_have_alpha(&color) << std::endl;
std::cout << "Palette size: " << color.palettesize << std::endl;
std::cout << "Has color key: " << color.key_defined << std::endl;
if(color.key_defined) {
std::cout << "Color key r: " << color.key_r << std::endl;
std::cout << "Color key g: " << color.key_g << std::endl;
std::cout << "Color key b: " << color.key_b << std::endl;
}
std::cout << "Texts: " << info.text_num << std::endl;
for(size_t i = 0; i < info.text_num; i++) {
std::cout << "Text: " << info.text_keys[i] << ": " << info.text_strings[i] << std::endl << std::endl;
}
std::cout << "International texts: " << info.itext_num << std::endl;
for(size_t i = 0; i < info.itext_num; i++) {
std::cout << "Text: "
<< info.itext_keys[i] << ", "
<< info.itext_langtags[i] << ", "
<< info.itext_transkeys[i] << ": "
<< info.itext_strings[i] << std::endl << std::endl;
}
std::cout << "Time defined: " << info.time_defined << std::endl;
if(info.time_defined) {
const LodePNGTime& time = info.time;
std::cout << "year: " << time.year << std::endl;
std::cout << "month: " << time.month << std::endl;
std::cout << "day: " << time.day << std::endl;
std::cout << "hour: " << time.hour << std::endl;
std::cout << "minute: " << time.minute << std::endl;
std::cout << "second: " << time.second << std::endl;
}
std::cout << "Physics defined: " << info.phys_defined << std::endl;
if(info.phys_defined) {
std::cout << "physics X: " << info.phys_x << std::endl;
std::cout << "physics Y: " << info.phys_y << std::endl;
std::cout << "physics unit: " << info.phys_unit << std::endl;
}
}
/*
Display the names and sizes of all chunks in the PNG file.
*/
void displayChunkNames(const std::vector<unsigned char>& buffer) {
// Listing chunks is based on the original file, not the decoded png info.
const unsigned char *chunk, *end;
end = &buffer.back() + 1;
chunk = &buffer.front() + 8;
std::cout << std::endl << "Chunks:" << std::endl;
std::cout << " type: length(s)";
std::string last_type;
while(chunk < end && end - chunk >= 8) {
char type[5];
lodepng_chunk_type(type, chunk);
if(std::string(type).size() != 4) {
std::cout << "this is probably not a PNG" << std::endl;
return;
}
if(last_type != type) {
std::cout << std::endl;
std::cout << " " << type << ": ";
}
last_type = type;
std::cout << lodepng_chunk_length(chunk) << ", ";
chunk = lodepng_chunk_next_const(chunk, end);
}
std::cout << std::endl;
}
/*
Show ASCII art preview of the image
*/
void displayAsciiArt(const std::vector<unsigned char>& image, unsigned w, unsigned h) {
if(w > 0 && h > 0) {
std::cout << std::endl << "ASCII Art Preview: " << std::endl;
unsigned w2 = 48;
if(w < w2) w2 = w;
unsigned h2 = h * w2 / w;
h2 = (h2 * 2) / 3; //compensate for non-square characters in terminal
if(h2 > (w2 * 2)) h2 = w2 * 2; //avoid too large output
std::cout << '+';
for(unsigned x = 0; x < w2; x++) std::cout << '-';
std::cout << '+' << std::endl;
for(unsigned y = 0; y < h2; y++) {
std::cout << "|";
for(unsigned x = 0; x < w2; x++) {
unsigned x2 = x * w / w2;
unsigned y2 = y * h / h2;
int r = image[y2 * w * 4 + x2 * 4 + 0];
int g = image[y2 * w * 4 + x2 * 4 + 1];
int b = image[y2 * w * 4 + x2 * 4 + 2];
int a = image[y2 * w * 4 + x2 * 4 + 3];
int lightness = ((r + g + b) / 3) * a / 255;
int min = (r < g && r < b) ? r : (g < b ? g : b);
int max = (r > g && r > b) ? r : (g > b ? g : b);
int saturation = max - min;
int letter = 'i'; //i for grey, or r,y,g,c,b,m for colors
if(saturation > 32) {
int h = lightness >= (min + max) / 2;
if(h) letter = (min == r ? 'c' : (min == g ? 'm' : 'y'));
else letter = (max == r ? 'r' : (max == g ? 'g' : 'b'));
}
int symbol = ' ';
if(lightness > 224) symbol = '@';
else if(lightness > 128) symbol = letter - 32;
else if(lightness > 32) symbol = letter;
else if(lightness > 16) symbol = '.';
std::cout << (char)symbol;
}
std::cout << "|";
std::cout << std::endl;
}
std::cout << '+';
for(unsigned x = 0; x < w2; x++) std::cout << '-';
std::cout << '+' << std::endl;
}
}
/*
Show the filtertypes of each scanline in this PNG image.
*/
void displayFilterTypes(const std::vector<unsigned char>& buffer, bool ignore_checksums) {
//Get color type and interlace type
lodepng::State state;
if(ignore_checksums) {
state.decoder.ignore_crc = 1;
state.decoder.zlibsettings.ignore_adler32 = 1;
}
unsigned w, h;
unsigned error;
error = lodepng_inspect(&w, &h, &state, &buffer[0], buffer.size());
if(error) {
std::cout << "inspect error " << error << ": " << lodepng_error_text(error) << std::endl;
return;
}
if(state.info_png.interlace_method == 1) {
std::cout << "showing filtertypes for interlaced PNG not supported by this example" << std::endl;
return;
}
//Read literal data from all IDAT chunks
const unsigned char *chunk, *begin, *end;
end = &buffer.back() + 1;
begin = chunk = &buffer.front() + 8;
std::vector<unsigned char> zdata;
while(chunk < end && end - chunk >= 8) {
char type[5];
lodepng_chunk_type(type, chunk);
if(std::string(type).size() != 4) {
std::cout << "this is probably not a PNG" << std::endl;
return;
}
if(std::string(type) == "IDAT") {
const unsigned char* cdata = lodepng_chunk_data_const(chunk);
unsigned clength = lodepng_chunk_length(chunk);
if(chunk + clength + 12 > end || clength > buffer.size() || chunk + clength + 12 < begin) {
std::cout << "invalid chunk length" << std::endl;
return;
}
for(unsigned i = 0; i < clength; i++) {
zdata.push_back(cdata[i]);
}
}
chunk = lodepng_chunk_next_const(chunk, end);
}
//Decompress all IDAT data
std::vector<unsigned char> data;
error = lodepng::decompress(data, &zdata[0], zdata.size());
if(error) {
std::cout << "decompress error " << error << ": " << lodepng_error_text(error) << std::endl;
return;
}
//A line is 1 filter byte + all pixels
size_t linebytes = 1 + lodepng_get_raw_size(w, 1, &state.info_png.color);
if(linebytes == 0) {
std::cout << "error: linebytes is 0" << std::endl;
return;
}
std::cout << "Filter types: ";
for(size_t i = 0; i < data.size(); i += linebytes) {
std::cout << (int)(data[i]) << " ";
}
std::cout << std::endl;
}
/*
Main
*/
int main(int argc, char *argv[]) /*list the chunks*/ {
bool ignore_checksums = false;
std::string filename = "";
for (int i = 1; i < argc; i++) {
if(std::string(argv[i]) == "--ignore_checksums") ignore_checksums = true;
else filename = argv[i];
}
if(filename == "") {
std::cout << "Please provide a filename to preview" << std::endl;
return 0;
}
std::vector<unsigned char> buffer;
std::vector<unsigned char> image;
unsigned w, h;
lodepng::load_file(buffer, filename); //load the image file with given filename
lodepng::State state;
if(ignore_checksums) {
state.decoder.ignore_crc = 1;
state.decoder.zlibsettings.ignore_adler32 = 1;
}
unsigned error = lodepng::decode(image, w, h, state, buffer);
if(error) {
std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
return 0;
}
std::cout << "Filesize: " << buffer.size() << " (" << buffer.size() / 1024 << "K)" << std::endl;
std::cout << "Width: " << w << std::endl;
std::cout << "Height: " << h << std::endl;
std::cout << "Num pixels: " << w * h << std::endl;
if(w > 0 && h > 0) {
std::cout << "Top left pixel color:"
<< " r: " << (int)image[0]
<< " g: " << (int)image[1]
<< " b: " << (int)image[2]
<< " a: " << (int)image[3]
<< std::endl;
}
displayPNGInfo(state.info_png);
std::cout << std::endl;
displayChunkNames(buffer);
std::cout << std::endl;
displayFilterTypes(buffer, ignore_checksums);
std::cout << std::endl;
displayAsciiArt(image, w, h);
}

View File

@ -0,0 +1,72 @@
/*
LodePNG Examples
Copyright (c) 2005-2010 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.
*/
/*
LodePNG decode-encode: decodes the image, then encodes it again, with all the
same information, chunks, color types, etc... as the original image had.
This sample shows how LodePNG can be used for a conforming PNG editor.
*/
//g++ lodepng.cpp example_reencode.cpp -ansi -pedantic -Wall -Wextra -lSDL -O3 -o reencode
#include "lodepng.h"
#include <iostream>
int main(int argc, char *argv[]) {
std::vector<unsigned char> image;
unsigned w, h;
std::vector<unsigned char> buffer;
lodepng::State state;
unsigned error;
//check if user gave a filename
if(argc < 3) {
std::cout << "please provide in and out filename" << std::endl;
return 0;
}
state.decoder.color_convert = 0;
state.decoder.remember_unknown_chunks = 1; //make it reproduce even unknown chunks in the saved image
lodepng::load_file(buffer, argv[1]);
error = lodepng::decode(image, w, h, state, buffer);
if(error) {
std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
return 0;
}
buffer.clear();
state.encoder.text_compression = 1;
error = lodepng::encode(buffer, image, w, h, state);
if(error) {
std::cout << "encoder error " << error << ": " << lodepng_error_text(error) << std::endl;
return 0;
}
lodepng::save_file(buffer, argv[2]);
}

View File

@ -0,0 +1,133 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
/*
Compile command for Linux:
gcc lodepng.c example_sdl.c -ansi -pedantic -Wall -Wextra -lSDL -O3 -o showpng
*/
/*
LodePNG SDL example
This example displays a PNG with a checkerboard pattern to show tranparency.
It requires the SDL library to compile and run.
If multiple filenames are given to the command line, it shows all of them.
Press any key to see next image, or esc to quit.
*/
#include "lodepng.h"
#include <SDL/SDL.h>
/*shows image with SDL. Returns 1 if user wants to fully quit, 0 if user wants to see next image.*/
int show(const char* filename) {
unsigned error;
unsigned char* image;
unsigned w, h, x, y;
SDL_Surface* scr;
SDL_Event event;
int done;
size_t jump = 1;
printf("showing %s\n", filename);
/*load the PNG in one function call*/
error = lodepng_decode32_file(&image, &w, &h, filename);
/*stop if there is an error*/
if(error) {
printf("decoder error %u: %s\n", error, lodepng_error_text(error));
return 0;
}
/*avoid too large window size by downscaling large image*/
if(w / 1024 >= jump) jump = w / 1024 + 1;
if(h / 1024 >= jump) jump = h / 1024 + 1;
/*init SDL*/
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("Error, SDL video init failed\n");
return 0;
}
scr = SDL_SetVideoMode(w / jump, h / jump, 32, SDL_HWSURFACE);
if(!scr) {
printf("Error, no SDL screen\n");
return 0;
}
SDL_WM_SetCaption(filename, NULL); /*set window caption*/
/*plot the pixels of the PNG file*/
for(y = 0; y + jump - 1 < h; y += jump)
for(x = 0; x + jump - 1 < w; x += jump) {
int checkerColor;
Uint32* bufp;
Uint32 r, g, b, a;
/*get RGBA components*/
r = image[4 * y * w + 4 * x + 0]; /*red*/
g = image[4 * y * w + 4 * x + 1]; /*green*/
b = image[4 * y * w + 4 * x + 2]; /*blue*/
a = image[4 * y * w + 4 * x + 3]; /*alpha*/
/*make translucency visible by placing checkerboard pattern behind image*/
checkerColor = 191 + 64 * (((x / 16) % 2) == ((y / 16) % 2));
r = (a * r + (255 - a) * checkerColor) / 255;
g = (a * g + (255 - a) * checkerColor) / 255;
b = (a * b + (255 - a) * checkerColor) / 255;
/*give the color value to the pixel of the screenbuffer*/
bufp = (Uint32 *)scr->pixels + (y * scr->pitch / 4) / jump + (x / jump);
*bufp = 65536 * r + 256 * g + b;
}
/*pause until you press escape and meanwhile redraw screen*/
done = 0;
while(done == 0) {
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT) done = 2;
else if(SDL_GetKeyState(NULL)[SDLK_ESCAPE]) done = 2;
else if(event.type == SDL_KEYDOWN) done = 1; /*press any other key for next image*/
}
SDL_UpdateRect(scr, 0, 0, 0, 0); /*redraw screen*/
SDL_Delay(5); /*pause 5 ms so it consumes less processing power*/
}
/*cleanup*/
free(image);
SDL_Quit();
return done == 2 ? 1 : 0;
}
int main(int argc, char* argv[]) {
int i;
if(argc <= 1) printf("Please enter PNG file name(s) to display\n");;
for(i = 1; i < argc; i++) {
if(show(argv[i])) return 0;
}
return 0;
}

View File

@ -0,0 +1,122 @@
/*
LodePNG Examples
Copyright (c) 2005-2012 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.
*/
//Compile command for Linux:
//g++ lodepng.cpp example_sdl.cpp -lSDL -O3 -o showpng
/*
LodePNG SDL example
This example displays a PNG with a checkerboard pattern to show tranparency.
It requires the SDL library to compile and run.
If multiple filenames are given to the command line, it shows all of them.
Press any key to see next image, or esc to quit.
*/
#include "lodepng.h"
#include <iostream>
#include <SDL/SDL.h>
int show(const std::string& caption, const unsigned char* rgba, unsigned w, unsigned h) {
//avoid too large window size by downscaling large image
unsigned jump = 1;
if(w / 1024 >= jump) jump = w / 1024 + 1;
if(h / 1024 >= jump) jump = h / 1024 + 1;
//init SDL
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << "error, SDL video init failed" << std::endl;
return 0;
}
SDL_Surface* scr = SDL_SetVideoMode(w / jump, h / jump, 32, SDL_HWSURFACE);
if(!scr) {
std::cout << "error, no SDL screen" << std::endl;
return 0;
}
SDL_WM_SetCaption(caption.c_str(), NULL); //set window caption
//plot the pixels of the PNG file
for(unsigned y = 0; y + jump - 1 < h; y += jump)
for(unsigned x = 0; x + jump - 1 < w; x += jump) {
//get RGBA components
Uint32 r = rgba[4 * y * w + 4 * x + 0]; //red
Uint32 g = rgba[4 * y * w + 4 * x + 1]; //green
Uint32 b = rgba[4 * y * w + 4 * x + 2]; //blue
Uint32 a = rgba[4 * y * w + 4 * x + 3]; //alpha
//make translucency visible by placing checkerboard pattern behind image
int checkerColor = 191 + 64 * (((x / 16) % 2) == ((y / 16) % 2));
r = (a * r + (255 - a) * checkerColor) / 255;
g = (a * g + (255 - a) * checkerColor) / 255;
b = (a * b + (255 - a) * checkerColor) / 255;
//give the color value to the pixel of the screenbuffer
Uint32* bufp;
bufp = (Uint32 *)scr->pixels + (y * scr->pitch / 4) / jump + (x / jump);
*bufp = 65536 * r + 256 * g + b;
}
//pause until you press escape and meanwhile redraw screen
SDL_Event event;
int done = 0;
while(done == 0) {
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT) done = 2;
else if(SDL_GetKeyState(NULL)[SDLK_ESCAPE]) done = 2;
else if(event.type == SDL_KEYDOWN) done = 1; //press any other key for next image
}
SDL_UpdateRect(scr, 0, 0, 0, 0); //redraw screen
SDL_Delay(5); //pause 5 ms so it consumes less processing power
}
SDL_Quit();
return done == 2 ? 1 : 0;
}
/*shows image with SDL. Returns 1 if user wants to fully quit, 0 if user wants to see next image.*/
int showfile(const char* filename) {
std::cout << "showing " << filename << std::endl;
std::vector<unsigned char> buffer, image;
lodepng::load_file(buffer, filename); //load the image file with given filename
unsigned w, h;
unsigned error = lodepng::decode(image, w, h, buffer); //decode the png
//stop if there is an error
if(error) {
std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
return 0;
}
return show(filename, &image[0], w, h);
}
int main(int argc, char* argv[]) {
if(argc <= 1) std::cout << "Please enter PNG file name(s) to display" << std::endl;
for(int i = 1; i < argc; i++) {
if(showfile(argv[i])) return 0;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,350 @@
/*
LodePNG Benchmark
Copyright (c) 2005-2019 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.
*/
//g++ lodepng.cpp lodepng_benchmark.cpp -Wall -Wextra -pedantic -ansi -lSDL -O3
//g++ lodepng.cpp lodepng_benchmark.cpp -Wall -Wextra -pedantic -ansi -lSDL -O3 && ./a.out
#include "lodepng.h"
#include <cmath>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h> //SDL is used for timing.
bool apply_mods = false;
#define NUM_DECODE 5 //decode multiple times to measure better. Must be at least 1.
size_t total_pixels = 0;
size_t total_png_orig_size = 0;
size_t total_raw_orig_size = 0; // This is the uncompressed data in the raw color format in the original input PNGs
double total_dec_time = 0;
size_t total_png_in_size = 0;
size_t total_raw_in_size = 0; // This is the uncompressed data in the raw color format in the input PNGs given to the decoder (not same as orig when using the encoded ones)
size_t total_raw_dec_size = 0; // This is the uncompressed data in the raw color format of raw image buffers output by the decoder
double total_enc_time = 0;
size_t total_raw_enc_size = 0; // This is the uncompressed data in the raw color format of the raw images given to the encoder
size_t total_png_out_size = 0;
size_t total_raw_out_size = 0; // This is the uncompressed data in the raw color format of the encoded PNGs
bool verbose = false;
bool do_decode = false;
bool do_encode = false;
bool decode_encoded = false; // do the decoding benchmark on the encoded images rather than the original inputs
std::string dumpdir;
////////////////////////////////////////////////////////////////////////////////
double getTime() {
return SDL_GetTicks() / 1000.0;
}
template<typename T, typename U>
void assertEquals(const T& expected, const U& actual, const std::string& message = "") {
if(expected != (T)actual) {
std::cout << "Error: Not equal! Expected " << expected << " got " << actual << "." << std::endl;
std::cout << "Message: " << message << std::endl;
std::exit(1);
}
}
void assertTrue(bool value, const std::string& message = "") {
if(!value) {
std::cout << "Error: expected true." << std::endl;
std::cout << "Message: " << message << std::endl;
std::exit(1);
}
}
//Test image data
struct Image {
std::vector<unsigned char> data;
unsigned width;
unsigned height;
LodePNGColorType colorType;
unsigned bitDepth;
std::string name;
};
//Utility for debug messages
template<typename T>
std::string valtostr(const T& val) {
std::ostringstream sstream;
sstream << val;
return sstream.str();
}
template<typename T>
void printValue(const std::string& name, const T& value, const std::string& unit = "") {
std::cout << name << ": " << value << unit << std::endl;
}
template<typename T, typename U>
void printValue(const std::string& name, const T& value, const std::string& s2, const U& value2, const std::string& unit = "") {
std::cout << name << ": " << value << s2 << value2 << unit << std::endl;
}
//Test LodePNG encoding and decoding the encoded result, using the C interface
std::vector<unsigned char> testEncode(Image& image) {
unsigned char* encoded = 0;
size_t encoded_size = 0;
lodepng::State state;
state.info_raw.colortype = image.colorType;
state.info_raw.bitdepth = image.bitDepth;
// Try custom compression settings
if(apply_mods) {
//state.encoder.filter_strategy = LFS_ZERO;
state.encoder.filter_strategy = LFS_ENTROPY;
//state.encoder.zlibsettings.btype = 0;
//state.encoder.zlibsettings.btype = 1;
//state.encoder.auto_convert = 0;
//state.encoder.zlibsettings.use_lz77 = 0;
}
double t_enc0 = getTime();
unsigned error_enc = lodepng_encode(&encoded, &encoded_size, &image.data[0],
image.width, image.height, &state);
double t_enc1 = getTime();
assertEquals(0, error_enc, "encoder error");
total_raw_enc_size += lodepng_get_raw_size(image.width, image.height, &state.info_raw);
total_png_out_size += encoded_size;
total_enc_time += (t_enc1 - t_enc0);
if(verbose) {
printValue("encoding time", t_enc1 - t_enc0, "s");
std::cout << "compression: " << ((double)(encoded_size) / (double)(image.data.size())) * 100 << "%"
<< ", ratio: " << ((double)(image.data.size()) / (double)(encoded_size))
<< ", size: " << encoded_size
<< ", bpp: " << (8.0 * encoded_size / image.width / image.height) << std::endl;
}
if(!dumpdir.empty()) {
std::string dumpname = dumpdir;
if(dumpname[dumpname.size() - 1] != '/') dumpname += "/";
dumpname += image.name;
if(lodepng_save_file(encoded, encoded_size, dumpname.c_str())) {
std::cout << "WARNING: failed to dump " << dumpname << ". The dir must already exist." << std::endl;
} else if(verbose) {
std::cout << "saved to: " << dumpname << std::endl;
}
}
// output image stats
{
lodepng::State inspect;
unsigned w, h;
lodepng_inspect(&w, &h, &inspect, encoded, encoded_size);
total_raw_out_size += lodepng_get_raw_size(w, h, &inspect.info_png.color);
}
std::vector<unsigned char> result(encoded, encoded + encoded_size);
free(encoded);
return result;
}
void testDecode(const std::vector<unsigned char>& png) {
lodepng::State state;
unsigned char* decoded = 0;
unsigned w, h;
// Try custom decompression settings
if(apply_mods) {
state.decoder.color_convert = 0;
//state.decoder.ignore_crc = 1;
}
double t_dec0 = getTime();
for(int i = 0; i < NUM_DECODE; i++) {
unsigned error_dec = lodepng_decode(&decoded, &w, &h, &state, png.data(), png.size());
assertEquals(0, error_dec, "decoder error");
}
double t_dec1 = getTime();
total_dec_time += (t_dec1 - t_dec0);
total_raw_dec_size += lodepng_get_raw_size(w, h, &state.info_raw);
if(verbose) {
printValue("decoding time", t_dec1 - t_dec0, "/", NUM_DECODE, " s");
}
free(decoded);
// input image stats
{
lodepng::State inspect;
unsigned w, h;
lodepng_inspect(&w, &h, &inspect, png.data(), png.size());
total_raw_in_size += lodepng_get_raw_size(w, h, &inspect.info_png.color);
total_png_in_size += png.size();
}
}
std::string getFilePart(const std::string& path) {
if(path.empty()) return "";
int slash = path.size() - 1;
while(slash >= 0 && path[slash] != '/') slash--;
return path.substr(slash + 1);
}
void testFile(const std::string& filename) {
if(verbose) std::cout << "file " << filename << std::endl;
std::vector<unsigned char> png;
if(lodepng::load_file(png, filename)) {
std::cout << "\nfailed to load file " << filename << std::endl << std::endl;
return;
}
// input image stats
{
lodepng::State inspect;
unsigned w, h;
lodepng_inspect(&w, &h, &inspect, png.data(), png.size());
total_pixels += (w * h);
total_png_orig_size += png.size();
size_t raw_size = lodepng_get_raw_size(w, h, &inspect.info_png.color);
total_raw_orig_size += raw_size;
if(verbose) std::cout << "orig compressed size: " << png.size() << ", pixels: " << (w * h) << ", raw size: " << raw_size << std::endl;
}
if(do_encode) {
Image image;
image.name = getFilePart(filename);
image.colorType = LCT_RGBA;
image.bitDepth = 8;
assertEquals(0, lodepng::decode(image.data, image.width, image.height, filename, image.colorType, image.bitDepth));
std::vector<unsigned char> temp = testEncode(image);
if(decode_encoded) png = temp;
}
if(do_decode) {
testDecode(png);
}
if(verbose) std::cout << std::endl;
}
void showHelp(int argc, char *argv[]) {
(void)argc;
std::cout << "Usage: " << argv[0] << " png_filenames... [OPTIONS...] [--dumpdir directory]" << std::endl;
std::cout << "Options:" << std::endl;
std::cout << " -h: show this help" << std::endl;
std::cout << " -v: verbose" << std::endl;
std::cout << " -d: decode only" << std::endl;
std::cout << " -e: encode only" << std::endl;
std::cout << " -o: decode on original images rather than encoded ones (always true if -d without -e)" << std::endl;
std::cout << " -m: apply modifications to encoder and decoder settings, the modification itself must be implemented or changed in the benchmark source code (search for apply_mods in the code, for encode and for decode)" << std::endl;
}
int main(int argc, char *argv[]) {
verbose = false;
do_decode = true;
do_encode = true;
decode_encoded = true;
std::vector<std::string> files;
for(int i = 1; i < argc; i++) {
std::string arg = argv[i];
if(arg == "-v") verbose = true;
else if(arg == "-h" || arg == "--help") { showHelp(argc, argv); return 0; }
else if(arg == "-d") do_decode ? (do_encode = false) : (do_decode = true);
else if(arg == "-e") do_encode ? (do_decode = false) : (do_encode = true);
else if(arg == "-o") decode_encoded = false;
else if(arg == "-m") apply_mods = true;
else if(arg == "--dumpdir" && i + 1 < argc) {
dumpdir = argv[++i];
}
else files.push_back(arg);
}
if(!do_encode) decode_encoded = false;
if(files.empty()) {
std::cout << "must give .png filenames to benchamrk" << std::endl;
showHelp(argc, argv);
return 1;
}
for(size_t i = 0; i < files.size(); i++) {
testFile(files[i]);
}
// test images stats
if(verbose) {
std::cout << "Final Summary: " << std::endl;
std::cout << "input images: " << files.size() << std::endl;
std::cout << "total_pixels: " << total_pixels << std::endl;
// file size of original PNGs that were given as command line arguments to the tool
std::cout << "total_png_orig_size: " << total_png_orig_size << " (" << (8.0 * total_png_orig_size / total_pixels) << " bpp)" << std::endl;
// size of the data inside the original PNGs, dependent on color encoding (bit depth used in the PNG)
std::cout << "total_raw_orig_size: " << total_raw_orig_size << " (" << (8.0 * total_raw_orig_size / total_pixels) << " bpp)" << std::endl;
// size of the pixel data given to the benchmark encoder, dependent on color encoding (bit depth used in the image representation in the benchmark tool, probably 32 bits)
if(do_encode) std::cout << "total_raw_enc_size: " << total_raw_enc_size << " (" << (8.0 * total_raw_enc_size / total_pixels) << " bpp)" << std::endl;
// file size of PNGs created by the benchmark encoder
if(do_encode) std::cout << "total_png_out_size: " << total_png_out_size << " (" << (8.0 * total_png_out_size / total_pixels) << " bpp)" << std::endl;
// size of the data inside the PNGs created by the benchmark encoder, dependent on color encoding (bit depth used in the PNG), may differ from total_raw_orig_size since the encoder may choose to use a different color encoding
if(do_encode) std::cout << "total_raw_out_size: " << total_raw_out_size << " (" << (8.0 * total_raw_out_size / total_pixels) << " bpp)" << std::endl;
// size of file size of the PNGs given to the benchmark decoder, this could either be the original ones or the ones encoded by the benchmark encoder depending on user options
if(do_decode) std::cout << "total_png_in_size: " << total_png_in_size << " (" << (8.0 * total_png_in_size / total_pixels) << " bpp)" << std::endl;
// size of the data inside the PNGs mentioned at total_png_in_size, dependent on color encoding (bit depth used in the image representation in the benchmark tool, probably 32 bits)
if(do_decode) std::cout << "total_raw_in_size: " << total_raw_in_size << " (" << (8.0 * total_raw_in_size / total_pixels) << " bpp)" << std::endl;
// size of the pixel data requested from the benchmark decoder, dependent on color encoding requested (bit depth used in the image representation in the benchmark tool, probably 32 bits)
if(do_decode) std::cout << "total_raw_dec_size: " << total_raw_dec_size << " (" << (8.0 * total_raw_dec_size / total_pixels) << " bpp)" << std::endl;
}
// final encoding stats
if(do_encode) {
std::cout << "encoding time: " << total_enc_time << "s on " << total_pixels << " pixels and " << total_raw_out_size << " raw bytes ("
<< ((total_raw_enc_size/1024.0/1024.0)/(total_enc_time)) << " MB/s, " << ((total_pixels/1024.0/1024.0)/(total_enc_time)) << " MP/s)" << std::endl;
std::cout << "encoded size: " << total_png_out_size << " (" << (100.0 * total_png_out_size / total_raw_out_size) << "%), bpp: "
<< (8.0 * total_png_out_size / total_pixels) << std::endl;
}
// final decoding stats
if(do_decode) {
if(verbose) std::cout << "decoding iterations: " << NUM_DECODE << std::endl;
std::cout << "decoding time: " << total_dec_time/NUM_DECODE << "s on " << total_pixels << " pixels and " << total_png_in_size
<< " compressed bytes (" << ((total_raw_in_size/1024.0/1024.0)/(total_dec_time/NUM_DECODE)) << " MB/s, "
<< ((total_pixels/1024.0/1024.0)/(total_dec_time/NUM_DECODE)) << " MP/s)" << std::endl;
}
}

View File

@ -0,0 +1,96 @@
/*
LodePNG Fuzzer
Copyright (c) 2005-2019 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.
*/
// clang++ -fsanitize=fuzzer lodepng.cpp lodepng_fuzzer.cpp -O3 && ./a.out
#include "lodepng.h"
#include <cstdint>
namespace {
// Amount of valid colortype/bidthdepth combinations in the PNG file format.
const size_t num_combinations = 15;
LodePNGColorType colortypes[num_combinations] = {
LCT_GREY, LCT_GREY, LCT_GREY, LCT_GREY, LCT_GREY, // 1, 2, 4, 8 or 16 bits
LCT_RGB, LCT_RGB, // 8 or 16 bits
LCT_PALETTE, LCT_PALETTE, LCT_PALETTE, LCT_PALETTE, // 1, 2, 4 or 8 bits
LCT_GREY_ALPHA, LCT_GREY_ALPHA, // 8 or 16 bits
LCT_RGBA, LCT_RGBA, // 8 or 16 bits
};
unsigned bitdepths[num_combinations] = {
1, 2, 4, 8, 16, // gray
8, 16, // rgb
1, 2, 4, 8, // palette
8, 16, // gray+alpha
8, 16, // rgb+alpha
};
unsigned testDecode(lodepng::State& state, const uint8_t* data, size_t size) {
unsigned w, h;
std::vector<unsigned char> image;
return lodepng::decode(image, w, h, state, (const unsigned char*)data, size);
}
} // end anonymous namespace
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if(size == 0) return 0;
// Setting last byte of input as random_color_type
// Fuzzer will still be able to mutate the data accordingly as
// last byte of png file can be changed and file will still remain valid.
size_t random_color_type = data[size-1] % num_combinations;
lodepng::State state;
// Make the decoder ignore three types of checksums the PNG/zlib format have
// built-in, because they are less likely to be correct in the random input
// data, and if invalid make the decoder return an error before much gets ran.
state.decoder.zlibsettings.ignore_adler32 = 1;
state.decoder.zlibsettings.ignore_nlen = 1;
state.decoder.ignore_crc = 1;
// Also make decoder attempt to support partial files with missing ending to
// go further with parsing.
state.decoder.ignore_end = 1;
// First test without color conversion (keep color type of the PNG)
state.decoder.color_convert = 0;
unsigned error = testDecode(state, data, size);
// If valid PNG found, try decoding with color conversion to the most common
// default color type, and to the randomly chosen type.
if(error == 0) {
state.decoder.color_convert = 1;
testDecode(state, data, size);
state.info_raw.colortype = colortypes[random_color_type];
state.info_raw.bitdepth = bitdepths[random_color_type];
testDecode(state, data, size);
}
return 0;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,290 @@
/*
LodePNG Utils
Copyright (c) 2005-2020 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.
*/
/*
Extra C++ utilities for LodePNG, for convenience.
Not part of the stable API of lodepng, more loose separate utils.
*/
#ifndef LODEPNG_UTIL_H
#define LODEPNG_UTIL_H
#include <string>
#include <vector>
#include "lodepng.h"
namespace lodepng {
/*
Returns info from the header of the PNG by value, purely for convenience.
Does NOT check for errors. Returns bogus info if the PNG has an error.
Does not require cleanup of allocated memory because no palette or text chunk
info is in the LodePNGInfo object after checking only the header of the PNG.
*/
LodePNGInfo getPNGHeaderInfo(const std::vector<unsigned char>& png);
/*
Get the names and sizes of all chunks in the PNG file.
Returns 0 if ok, non-0 if error happened.
*/
unsigned getChunkInfo(std::vector<std::string>& names, std::vector<size_t>& sizes,
const std::vector<unsigned char>& png);
/*
Returns the names and full chunks (including the name and everything else that
makes up the chunk) for all chunks except IHDR, PLTE, IDAT and IEND.
It separates the chunks into 3 separate lists, representing the chunks between
certain critical chunks: 0: IHDR-PLTE, 1: PLTE-IDAT, 2: IDAT-IEND
Returns 0 if ok, non-0 if error happened.
*/
unsigned getChunks(std::vector<std::string> names[3],
std::vector<std::vector<unsigned char> > chunks[3],
const std::vector<unsigned char>& png);
/*
Inserts chunks into the given png file. The chunks must be fully encoded,
including length, type, content and CRC.
The array index determines where it goes:
0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND.
They're appended at the end of those locations within the PNG.
Returns 0 if ok, non-0 if error happened.
*/
unsigned insertChunks(std::vector<unsigned char>& png,
const std::vector<std::vector<unsigned char> > chunks[3]);
/*
Get the filtertypes of each scanline in this PNG file.
Returns 0 if ok, 1 if PNG decoding error happened.
For a non-interlaced PNG, it returns one filtertype per scanline, in order.
For interlaced PNGs, it returns a result as if it's not interlaced. It returns
one filtertype per scanline, in order. The values match pass 6 and 7 of the
Adam7 interlacing, alternating between the two, so that the values correspond
the most to their scanlines.
*/
unsigned getFilterTypes(std::vector<unsigned char>& filterTypes, const std::vector<unsigned char>& png);
/*
Get the filtertypes of each scanline in every interlace pass this PNG file.
Returns 0 if ok, 1 if PNG decoding error happened.
For a non-interlaced PNG, it returns one filtertype per scanline, in order, in
a single std::vector in filterTypes.
For an interlaced PNG, it returns 7 std::vectors in filterTypes, one for each
Adam7 pass. The amount of values per pass can be calculated as follows, where
w and h are the size of the image and all divisions are integer divisions:
pass 1: (h + 7) / 8
pass 2: w <= 4 ? 0 : (h + 7) / 8
pass 3: h <= 4 ? 0 : (h + 7) / 8
pass 4: w <= 2 ? 0 : (h + 3) / 4
pass 5: h <= 2 ? 0 : (h + 3) / 4
pass 6: w <= 1 ? 0 : (h + 1) / 2
pass 7: h <= 1 ? 0 : (h + 1) / 2
*/
unsigned getFilterTypesInterlaced(std::vector<std::vector<unsigned char> >& filterTypes,
const std::vector<unsigned char>& png);
/*
Returns the value of the i-th pixel in an image with 1, 2, 4 or 8-bit color.
E.g. if bits is 4 and i is 5, it returns the 5th nibble (4-bit group), which
is the second half of the 3th byte, in big endian (PNG's endian order).
*/
int getPaletteValue(const unsigned char* data, size_t i, int bits);
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
/* Similar to convertRGBModel, but the 'to' model is sRGB. The pixel format
of in and out must be the same and is given by state_in->info_raw. An
error may occur if the pixel format cannot contain the new colors (e.g. palette) */
unsigned convertToSrgb(unsigned char* out, const unsigned char* in,
unsigned w, unsigned h,
const LodePNGState* state_in);
/* Similar to convertRGBModel, but the 'from' model is sRGB. The pixel format
of in and out must be the same and is given by state_out->info_raw. An
error may occur if the pixel format cannot contain the new colors (e.g. palette) */
unsigned convertFromSrgb(unsigned char* out, const unsigned char* in,
unsigned w, unsigned h,
const LodePNGState* state_out);
/*
Converts from one RGB model to another RGB model.
Similar to calling convertToXYZ followed by convertFromXYZ, but may be
more efficient and more precise (e.g. no computation needed when both models
are the same). See their documentation for more info.
Parameters:
*) out: output pixel data
*) in: input pixel data
*) w, h: image size
*) state_out: output RGB color model in state_out->info_png and byte format in state_out->info_raw.
*) state_in: output RGB color model in state_in->info_png and byte format in state_in->info_raw
*) return value: 0 if ok, positive value if error
*) rendering_intent: 1 for relative, 3 for absolute, should be relative for standard behavior.
See description at convertFromXYZ.
*/
unsigned convertRGBModel(unsigned char* out, const unsigned char* in,
unsigned w, unsigned h,
const LodePNGState* state_out,
const LodePNGState* state_in,
unsigned rendering_intent);
/*
Converts the RGB color to the absolute XYZ color space given the RGB color profile
chunks in the PNG info.
Color space here refers to the different possible RGB spaces with different
possible chromaticities or whitepoint and XYZ color from colorimetry, not the
LodePNGColorType that describes the byte based encoding.
You need this function only if the PNG could contain data in an arbitrary RGB
color space and you wish to output to a display or format that does not provide
color management for you (so you need to convert rather than pass on the profile
to it) but expects a certain RGB format (e.g. sRGB). See the background info below.
Supports the gAMA, cHRM, sRGB and iCCP colorimetry chunks. If no colometry chunks are present
(that is, in state->info_png, the fields gama_defined, chrm_defined, srgb_defined and
iccp_defined are all 0), it assumes the format is sRGB.
For more information, see the chunk specifications in the PNG specification.
Some background:
A PNG image contains RGB data inside, but this data may use a specific RGB model (by default sRGB but
different if colorimetry chunks are given).
The computer display and/or operating system can have another RGB model (typically sRGB, or wider gamut
or HDR formats).
The PNG chunks describe what format the data inside has, not the format of the display. To correctly
display a PNG image on a display, a conversion is needed from the PNG model to the display model if their
models differ. Some options to achieve that are:
*) If your use case already supports color management on its own, you can give it the RGB values straight from
the PNG image and give it the information from the cHRM, gAMA, sRGB and iCCP chunks (which you can find
in the LodePNGInfo), and the color management should then handle it correctly for you. You don't need
this function here in that case.
*) If your use case does not support color management, you may instead want to give it the RGB values in a
consistent color model, such as sRGB, but the PNG does not necessarily have it in this desired model.
In that case, use the function below (or a similar one from a CMS library if you prefer) to convert it to
the absolute color space XYZ, and then you can convert it to the target RGB with the counterpart convertFromXYZ
further below.
Parameters:
*) out: 4 floats per pixel, X,Y,Z,alpha color format, in range 0-1 (normally, not clipped if beyond), must
be allocated to have 4 * w * h floats available.
*) whitepoint: output argument, the whitepoint the original RGB data used, given in absolute XYZ. Needed for
relative rendering intents: give these values to counterpart function convertFromXYZ.
*) in: input RGB color, in byte format given by state->info_raw and RGB color profile given by info->info_png
*) w, h: image size
*) state (when using a LodePNG decode function that takes a LodePNGState parameter, can directly use that one):
state->info_png: PNG info with possibly an RGB color model in cHRM,gAMA and/or sRGB chunks
state->info_raw: byte format of in (amount of channels, bit depth)
*) return value: 0 if ok, positive value if error
*/
unsigned convertToXYZ(float* out, float whitepoint[3],
const unsigned char* in, unsigned w, unsigned h,
const LodePNGState* state);
/*
Same as convertToXYZ but takes floating point input. Slower.
The main black..white range in 0..1. Does not clip values that are outside that range.
*/
unsigned convertToXYZFloat(float* out, float whitepoint[3], const float* in,
unsigned w, unsigned h, const LodePNGState* state);
/*
Converts XYZ to RGB in the RGB color model given by info and byte format by mode_out.
If info has no coloremtry chunks, converts to sRGB.
Parameters:
*) out: output color in byte format given by state->info_raw and RGB color profile given
by info->info_png. Must have enough bytes allocated to contain pixels in the given byte format.
*) in: 4 floats per pixel, X,Y,Z,alpha color format, in range 0-1 (normally).
*) whitepoint: input argument, the original whitepoint in absolute XYZ that the pixel data
in "in" had back when it was in a previous RGB space. Needed to preserve the whitepoint
in the new target RGB space for relative rendering intent.
*) rendering_intent: the desired rendering intent, with numeric meaning matching the
values used by ICC: 0=perceptual, 1=relative, 2=saturation, 3=absolute.
Should be 1 for normal use cases, it adapts white to match that of different RGB
models which is the best practice. Using 3 may change the color of white and may
turn grayscale into colors of a certain tone. Using 0 and 2 will have the same
effect as 1 because using those requires more data than the matrix-based RGB profiles
supporetd here have.
*) w, h: image size
*) state:
state->info_png: PNG info with possibly an RGB color profile in cHRM,gAMA and/or sRGB chunks
state->info_raw: byte format of out (amount of channels, bit depth)
*) return value: 0 if ok, positive value if error
*/
unsigned convertFromXYZ(unsigned char* out, const float* in, unsigned w, unsigned h,
const LodePNGState* state,
const float whitepoint[3], unsigned rendering_intent);
/*
Same as convertFromXYZ but outputs the RGB colors in floating point.
The main black..white range in 0..1. Does not clip values that are outside that range.
*/
unsigned convertFromXYZFloat(float* out, const float* in, unsigned w, unsigned h,
const LodePNGState* state,
const float whitepoint[3], unsigned rendering_intent);
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
/*
The information for extractZlibInfo.
*/
struct ZlibBlockInfo {
int btype; //block type (0-2)
size_t compressedbits; //size of compressed block in bits
size_t uncompressedbytes; //size of uncompressed block in bytes
// only filled in for block type 2
size_t treebits; //encoded tree size in bits
int hlit; //the HLIT value that was filled in for this tree
int hdist; //the HDIST value that was filled in for this tree
int hclen; //the HCLEN value that was filled in for this tree
std::vector<int> clcl; //19 code length code lengths (compressed tree's tree)
std::vector<int> treecodes; //N tree codes, with values 0-18. Values 17 or 18 are followed by the repetition value.
std::vector<int> litlenlengths; //288 code lengths for lit/len symbols
std::vector<int> distlengths; //32 code lengths for dist symbols
// only filled in for block types 1 or 2
std::vector<int> lz77_lcode; //LZ77 codes. 0-255: literals. 256: end symbol. 257-285: length code of length/dist pairs
// the next vectors have the same size as lz77_lcode, but an element only has meaningful value if lz77_lcode contains a length code.
std::vector<int> lz77_dcode;
std::vector<int> lz77_lbits;
std::vector<int> lz77_dbits;
std::vector<int> lz77_lvalue;
std::vector<int> lz77_dvalue;
size_t numlit; //number of lit codes in this block
size_t numlen; //number of len codes in this block
};
//Extracts all info needed from a PNG file to reconstruct the zlib compression exactly.
void extractZlibInfo(std::vector<ZlibBlockInfo>& zlibinfo, const std::vector<unsigned char>& in);
} // namespace lodepng
#endif /*LODEPNG_UTIL_H inclusion guard*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,120 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "lodepng-master/lodepng.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
bool cmp_images32(const std::string &f1, const std::string &f2) {
std::cout << "COMPARING IMAGES " << basename(f1.c_str()) << " -> " << basename(f2.c_str()) << std::endl;
unsigned int error, width1, height1;
unsigned char* image1 = 0;
unsigned int width2, height2;
unsigned char* image2 = 0;
error = lodepng_decode32_file(&image1, &width1, &height1, f1.c_str());
if (error) {
std::cerr << "error " << error << ": " << lodepng_error_text(error) << std::endl;
return false;
}
error = lodepng_decode32_file(&image2, &width2, &height2, f2.c_str());
if (error) {
std::cerr << "error " << error << ": " << lodepng_error_text(error) << std::endl;
return false;
}
if (width1 != width2 || height1 != height2) {
std::cerr << "DIMENSIONS DIFFER\n";
return false;
}
for (int i = 0; i < width1 * height1; ++i) {
if (image1[i] != image2[i]) {
std::cerr << "PIXELS DIFFER AT i = " << i << std::endl;
return false;
}
}
return true;
}
// copies an image into another and compares them
void decode_and_encode32(const std::string &filename1, const std::string &filename2) {
unsigned int error, width, height;
unsigned char* image = 0;
error = lodepng_decode32_file(&image, &width, &height, filename1.c_str());
if (error) {
std::cerr << "error " << error << ": " << lodepng_error_text(error) << std::endl;
return;
}
error = lodepng_encode32_file(filename2.c_str(), image, width, height);
if (error) {
std::cerr << "error " << error << ": " << lodepng_error_text(error) << std::endl;
return;
}
free(image);
}
void test1(const std::string &images_path) {
std::cout << "test1" << std::endl;
std::string filename1 = images_path + "/test1.png";
std::string filename2 = images_path + "/out/test1_1out.png";
std::string filename3 = images_path + "/out/test1_2out.png";
decode_and_encode32(filename1, filename2);
decode_and_encode32(filename1, filename3);
if (!cmp_images32(filename1, filename2)) {
std::cout << "files are different" << std::endl;
} else {
std::cout << "files are not different" << std::endl;
}
if (!cmp_images32(filename3, filename2)) {
std::cout << "files are different" << std::endl;
} else {
std::cout << "files are not different" << std::endl;
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
std::cout << "usage: " << basename(argv[0]) << " images_folder_path"
<< std::endl;
return 1;
}
std::string images_path(argv[1]);
test1(images_path);
return 0;
}

View File

@ -0,0 +1,166 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "lodepng_sapi.sapi.h"
#include "sandbox.h"
#include "sandboxed_api/util/flag.h"
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all);
ABSL_DECLARE_FLAG(string, sandbox2_danger_danger_permit_all_and_log);
// takes a png image (f1), decodes it and ecodes it into f2.
// can be viewed as copying f1 into f2. This function has a basic usage
// of the decode and encode functions.
void decode_and_encode32(SapiLodepngSandbox &sandbox, LodepngApi &api,
const std::string &f1, const std::string &f2) {
sapi::v::UInt width(0), height(0);
sapi::v::ConstCStr filename1(f1.c_str()), filename2(f2.c_str());
// in order to pass unsigned char ** to the function, we pass a variable that
// contains the pointer.
sapi::v::IntBase<unsigned char *> image(0);
api.lodepng_decode32_file(image.PtrBoth(), width.PtrBoth(), height.PtrBoth(),
filename1.PtrBefore())
.IgnoreError();
// after the function is called, we need to access the data stored at the
// address to which the previous variable points. To do that, we have to
// transfer the data from the sandbox memory to this process's memory.
sapi::v::RemotePtr remote_out_ptr(reinterpret_cast<void *>(image.GetValue()));
sapi::v::Array<char> out_img(width.GetValue() * height.GetValue());
out_img.SetRemote(remote_out_ptr.GetValue());
sandbox.TransferFromSandboxee(&out_img).IgnoreError();
// now the pixels are available at out_img.GetData()
// when calling the encoding function, we need only an unsigned char *
// (instead of **) so we can simply use the sapi::v::Array defined before
// (PtrBefore will give us a pointer).
api.lodepng_encode32_file(filename2.PtrBefore(), out_img.PtrBefore(),
width.GetValue(), height.GetValue())
.IgnoreError();
// Since in this function we do not actually used the pixels, we could simply
// call the encode function with the pointer from before (the remote pointer,
// since the memory has already been allocated on the sandboxed process).
// However, most of the use cases of this library require accessing the pixels
// which is why the solution in which data is transferred around is used.
}
// compares the pixels of the f1 and f2 png files.
bool cmp_images32(SapiLodepngSandbox &sandbox, LodepngApi &api,
const std::string &f1, const std::string &f2) {
std::cout << "COMPARING IMAGES " << basename(f1.c_str()) << " --- "
<< basename(f2.c_str()) << std::endl;
sapi::v::UInt width1, height1, width2, height2;
sapi::v::ConstCStr filename1(f1.c_str()), filename2(f2.c_str());
sapi::v::IntBase<unsigned char *> image1_ptr(0), image2_ptr(0);
api.lodepng_decode32_file(image1_ptr.PtrBoth(), width1.PtrBoth(),
height1.PtrBoth(), filename1.PtrBefore())
.IgnoreError();
api.lodepng_decode32_file(image2_ptr.PtrBoth(), width2.PtrBoth(),
height2.PtrBoth(), filename2.PtrBefore())
.IgnoreError();
sapi::v::RemotePtr remote_out_ptr1(
reinterpret_cast<void *>(image1_ptr.GetValue()));
sapi::v::Array<char> pixels1(width1.GetValue() * height1.GetValue());
pixels1.SetRemote(remote_out_ptr1.GetValue());
sandbox.TransferFromSandboxee(&pixels1).IgnoreError();
sapi::v::RemotePtr remote_out_ptr2(
reinterpret_cast<void *>(image2_ptr.GetValue()));
sapi::v::Array<char> pixels2(width2.GetValue() * height2.GetValue());
pixels2.SetRemote(remote_out_ptr2.GetValue());
sandbox.TransferFromSandboxee(&pixels2).IgnoreError();
if (width1.GetValue() != width2.GetValue() ||
height1.GetValue() != height2.GetValue()) {
std::cerr << "DIMENSIONS DIFFER\n";
return false;
}
for (size_t i = 0; i < width1.GetValue() * height1.GetValue(); ++i) {
if (pixels1.GetData()[i] != pixels2.GetData()[i]) {
std::cerr << "PIXELS DIFFER AT i = " << i << std::endl;
return false;
}
}
return true;
}
// this test simply copies the png from filename1 to filename2 and filename3
// and then decodes those 2 files and compares the pixels. If those pixels are
// equal, then encoding and decoding worked.
void test1(SapiLodepngSandbox &sandbox, LodepngApi &api,
const std::string &images_path) {
std::cout << "test1" << std::endl;
std::string filename1 = images_path + "/test1.png";
std::string filename2 = images_path + "/out/test1_1out.png";
std::string filename3 = images_path + "/out/test1_2out.png";
// const char *filename1 =
// "/usr/local/google/home/amedar/sapi_lodepng/test_images/test1.png"; const
// char *filename2 =
// "/usr/local/google/home/amedar/sapi_lodepng/test_images/out/test1_1out.png";
// const char *filename3 =
// "/usr/local/google/home/amedar/sapi_lodepng/test_images/out/test1_2out.png";
decode_and_encode32(sandbox, api, filename1, filename2);
decode_and_encode32(sandbox, api, filename1, filename3);
if (!cmp_images32(sandbox, api, filename1, filename2)) {
std::cout << "files are different" << std::endl;
} else {
std::cout << "files are not different" << std::endl;
}
if (!cmp_images32(sandbox, api, filename3, filename2)) {
std::cout << "files are different" << std::endl;
} else {
std::cout << "files are not different" << std::endl;
}
}
// at the moment there are no arguments when running
int main(int argc, char *argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (argc != 2) {
std::cout << "usage: " << basename(argv[0]) << " images_folder_path"
<< std::endl;
return 1;
}
std::string images_path(argv[1]);
SapiLodepngSandbox sandbox(images_path);
sandbox.Init().IgnoreError();
LodepngApi api(&sandbox);
test1(sandbox, api, images_path);
return 0;
}

View File

@ -0,0 +1,14 @@
#include "gtest/gtest.h"
#include "lodepng_sapi.sapi.h"
#include "sandbox.h"
#include <glog/logging.h>
#include "gmock/gmock.h"
// #include "gtest/gtest.h"
namespace {
TEST(addition, basic) {
EXPECT_EQ(2, 1 + 1);
}
} // namespace

View File

@ -0,0 +1,54 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SAPI_LODEPNG_SANDBOX_H_
#define SAPI_LODEPNG_SANDBOX_H_
#include "lodepng_sapi.sapi.h"
#include <unistd.h>
#include <syscall.h>
// TODO change this with the location on your own machine
#define base_path "/usr/local/google/home/amedar/internship/sandboxed-api/oss-internship-2020/sapi_lodepng/"
class SapiLodepngSandbox : public LodepngSandbox {
public:
SapiLodepngSandbox(const std::string &images_path): images_path_(images_path) {}
std::unique_ptr<sandbox2::Policy> ModifyPolicy(
sandbox2::PolicyBuilder*) override {
return sandbox2::PolicyBuilder()
.AllowStaticStartup()
.AllowRead()
.AllowWrite()
.AllowOpen()
.AllowSystemMalloc()
.AllowExit()
.AllowStat()
// .AddFile("/usr/local/google/home/amedar/sapi_lodepng/test_images/test1.png")
.AddDirectory(images_path_, /*is_ro=*/false)
// .AddDirectory("/usr/local/google/home/amedar/sapi_lodepng/test_images/out", /*is_ro=*/false)
.AllowSyscalls({
__NR_futex,
__NR_lseek,
__NR_close,
})
.BuildOrDie();
}
private:
std::string images_path_;
};
#endif // SAPI_LODEPNG_SANDBOX_H_

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 KiB