Last active
July 21, 2022 08:22
-
-
Save Neboer/f47a7fa2006650e9350a384225f94a4f to your computer and use it in GitHub Desktop.
nbtp is a simple C/C++ program to convert any binary file to a validate png picture use lodepng
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "lodepng.h" | |
#include <math.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#define max_buffer 0xFFFFFF | |
struct size | |
{ | |
unsigned width; | |
unsigned height; | |
unsigned char *raw_image; | |
}; | |
void encodeOneStep(unsigned char *raw_image_data, char *dest_filename, | |
unsigned width, unsigned height) | |
{ | |
unsigned error = lodepng_encode_file(dest_filename, raw_image_data, width, | |
height, LCT_RGB, 8); | |
/*if there's an error, display it*/ | |
if (error) | |
{ | |
printf("error %u: %s\n", error, lodepng_error_text(error)); | |
return; | |
} | |
} | |
struct size encode_file(const char *filename) | |
{ | |
FILE *file_to_encode = fopen(filename, "rb"); | |
unsigned char *generated_image = malloc(max_buffer); | |
size_t file_length = | |
fread(generated_image + 4, 1, max_buffer, file_to_encode); | |
printf("file length: %lu\n", file_length); | |
fclose(file_to_encode); | |
*((uint32_t *)generated_image) = file_length; | |
unsigned useful_data_size = file_length + 4; | |
unsigned useful_pixels = ceil((double)useful_data_size / (double)3.0); | |
unsigned side = ceil(sqrt((double)useful_pixels)); | |
struct size result = {side, side, generated_image}; | |
memset(generated_image + useful_data_size, 255, side * side * 3 - useful_data_size); | |
return result; | |
} | |
void decode_file(const char *source_png_fn, const char *output_fn) | |
{ | |
struct size bin_file; | |
lodepng_decode_file(&bin_file.raw_image, &bin_file.width, &bin_file.height, source_png_fn, LCT_RGB, 8); | |
uint32_t file_length = *((uint32_t *)bin_file.raw_image); | |
FILE *output = fopen(output_fn, "wb"); | |
fwrite(bin_file.raw_image + 4, 1, file_length, output); | |
fclose(output); | |
} | |
int main(int argc, char **argv) | |
{ | |
if (argv[1][0] == 'd') | |
{ | |
decode_file(argv[2], argv[3]); | |
} | |
else if (argv[1][0] == 'e') | |
{ | |
struct size binary_content = encode_file(argv[2]); | |
printf("image size: %d * %d\n", binary_content.width, binary_content.height); | |
encodeOneStep(binary_content.raw_image, argv[3], binary_content.width, | |
binary_content.height); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <lodepng.h> | |
#include <iostream> | |
#include <fstream> | |
#include <sstream> | |
#include <vector> | |
#include <string> | |
#include <cmath> | |
typedef std::vector<unsigned char> DataVect; | |
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,LCT_RGB,8); | |
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; | |
} | |
DataVect 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, LCT_RGB); | |
//if there's an error, display it | |
if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl; | |
return image; | |
//the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ... | |
} | |
DataVect get_file_bin(const std::string& filename){ | |
std::ifstream file(filename); | |
std::ostringstream ss; | |
ss << file.rdbuf(); | |
file.close(); | |
const std::string& s = ss.str(); | |
DataVect vec(s.begin(), s.end()); | |
return vec; | |
} | |
void write_to_disk(const std::string& filename,const DataVect &data){ | |
FILE* dest_file = fopen(filename.c_str(),"w"); | |
fwrite(&data[0],data.size(),1,dest_file); | |
fclose(dest_file); | |
} | |
int binary_to_raw_image(DataVect &input_data){ | |
int original_size = input_data.size(); | |
union {uint32_t size;unsigned char bytes[4];} prepend_size_data{}; | |
prepend_size_data.size = original_size; | |
int length_of_side = ceil(sqrt((float)(original_size + 4) / 3.0)); | |
int container_capacity = length_of_side * length_of_side * 3; | |
int rest_length = container_capacity - (original_size + 4); | |
std::cout << input_data.size() << std::endl; | |
input_data.insert(input_data.begin(),&prepend_size_data.bytes[0], &prepend_size_data.bytes[4]); | |
std::cout << input_data.size() << std::endl; | |
input_data.insert(input_data.end(),rest_length,'\0'); | |
std::cout << input_data.size() << std::endl; | |
return length_of_side; | |
} | |
void raw_image_to_binary(DataVect &input_raw_image){ | |
union {uint32_t size;unsigned char bytes[4];} prepend_size_data{}; | |
memcpy(prepend_size_data.bytes,&input_raw_image[0],4); | |
//The range used is [first,last), which includes all the elements between first and last, including the element pointed by first but not the element pointed by last. | |
input_raw_image.erase(input_raw_image.begin(),input_raw_image.begin()+4); | |
input_raw_image.erase(input_raw_image.begin() + prepend_size_data.size, input_raw_image.end()); | |
} | |
// usage: nbtp b2p/p2b file1 file2 | |
int main(int argc, char** argv){ | |
if (strcmp(argv[1],"b2p") == 0){ | |
// input binary data output png file | |
DataVect bin = get_file_bin(argv[2]); | |
int side_length = binary_to_raw_image(bin); | |
encodeTwoSteps(argv[3],bin,side_length, side_length); | |
} else if (strcmp(argv[1],"p2b") == 0){ | |
DataVect binary_image = decodeTwoSteps(argv[2]); | |
raw_image_to_binary(binary_image); | |
write_to_disk(argv[3],binary_image); | |
} | |
} |
之前说的是nbtp.cpp的使用方法,这个程序存在bug,现在已经被第一个nbtp.c取代。请大家自行探索第一个程序的用法,其实和第二个大同小异!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
需要依赖lodepng,程序使用方法:(图片解码为文件)nbtp p2b ./tupian.png ./output