I need to convert base64 to opencv::mat file. So I took a set of 10 frames from a video and appended base64(A)(using base64.b64encode in python).
After that, I used the code from here to convert that base64 to Mat. Images looked fine.
But they have larger file size than the original images, plus when I encoded these final images to base64(B)(using base64.b64encode in python), the encoded base64 is different from original base64(A). I can't understand why? This is also affecting the output of my application that is using the cv::mat output.
For base64 to Mat I am using code from here(asposted above).
Edited: Following is my python script to convert set of jpeg to base64 (.txt)
def img2txt(file_directory):
imageFiles = glob.glob(file_directory+"/*.jpg")
imageFiles.sort()
fileWrite='base64encoding.txt'
#print fileWrite
for i in range(0,len(imageFiles)):
image = open(imageFiles[i],'rb')
image_read = image.read()
image_64_encode = base64.b64encode(image_read)
with open (fileWrite, 'a') as f:
f.writelines(image_64_encode+'\n')
base64decode function : from here
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
/*for (j = i; j < 4; j++)
char_array_4[j] = 0;*/
for (j = 0; j < i; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
//char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++)
ret += char_array_3[j];
}
return ret;
}
C++ Main function:
int main()
{
ifstream in("TestBase64.txt");
if(!in) {
cout << "Cannot open input file.\n";
return 1;
}
int i=0;
string encoded_string;
while (getline(in, encoded_string))
{
string decoded_string = base64_decode(encoded_string);
vector<uchar> data(decoded_string.begin(), decoded_string.end());
cv::imwrite("/Frames_from_B_to_Mat/Frames_from_B_to_Mat"+b+".jpg");
i++;
}
return 0;
}
On the line:
vector<uchar> data(decoded_string.begin(), decoded_string.end());
you are presumably holding the JPEG-encoded representation of one image in data. So you may as well just write this to a binary file, rather than use cv::imwrite() which is for writing a Mat to a file.
If, for some inexplicable reason, you want to use cv::imwrite(), you need to pass it a Mat. So you would end up decoding the JPEG representation to a Mat and then encoding to JPEG and writing - which seems silly:
cv::Mat img = cv::imdecode(data, cv::IMREAD_COLOR);
cv::imwrite('result.jpg',img);
TLDR;
What I'm saying is that your data is already JPEG-encoded, you read it from a JPEG file.
Related
I'm trying to write a program in c++ that can encode images into base64 and also decode base64 into images. I believe the encoder function is working fine and some websites can take the base64 code I generate and decode it into the image fine, but for some reason once I decode the base64 into a string and then write it to a file and save it as a png it says it can't be opened in an image viewer.
I confirmed that the string that is being written to the new file is exactly the same as the existing file (when opened in a text editor), but for some reason, the new file can't be opened but the existing one can be. I have even tried just making a new file in a text editor, and copying the text from the old file into it, but it still doesn't open in an image viewer.
I believe that both of the encode functions and the base64 decode function all work fine. I think the problem is in the Image Decode function.
Image Encode Function
string base64_encode_image(const string& path) {
vector<char> temp;
std::ifstream infile;
infile.open(path, ios::binary); // Open file in binary mode
if (infile.is_open()) {
while (!infile.eof()) {
char c = (char)infile.get();
temp.push_back(c);
}
infile.close();
}
else return "File could not be opened";
string ret(temp.begin(), temp.end() - 1);
ret = base64_encode((unsigned const char*)ret.c_str(), ret.size());
return ret;
}
Image Decode Function
void base64_decode_image(const string& input) {
ofstream outfile;
outfile.open("test.png", ofstream::out);
string temp = base64_decode(input);
outfile.write(temp.c_str(), temp.size());
outfile.close();
cout << "file saved" << endl;
}
Encode Function base64
string base64_encode(unsigned const char* input, unsigned const int len) {
string ret;
size_t i = 0;
unsigned char bytes[3];
unsigned char sextets[4];
while (i <= (len - 3)) {
bytes[0] = *(input++);
bytes[1] = *(input++);
bytes[2] = *(input++);
sextets[0] = (bytes[0] & 0xfc) >> 2; // Cuts last two bits off of first byte
sextets[1] = ((bytes[0] & 0x03) << 4) + ((bytes[1] & 0xf0) >> 4); // Takes last two bits from first byte and adds it to first 4 bits of 2nd byte
sextets[2] = ((bytes[1] & 0x0f) << 2) + ((bytes[2] & 0xc0) >> 6); // Takes last 4 bits of 2nd byte and adds it to first 2 bits of third byte
sextets[3] = bytes[2] & 0x3f; // takes last 6 bits of third byte
for (size_t j = 0; j < 4; ++j) {
ret += base64_chars[sextets[j]];
}
i += 3; // increases to go to third byte
}
if (i != len) {
size_t k = 0;
size_t j = len - i; // Find index of last byte
while (k < j) { // Sets first bytes
bytes[k] = *(input++);
++k;
}
while (j < 3) { // Set last bytes to 0x00
bytes[j] = '\0';
++j;
}
sextets[0] = (bytes[0] & 0xfc) >> 2; // Cuts last two bits off of first byte
sextets[1] = ((bytes[0] & 0x03) << 4) + ((bytes[1] & 0xf0) >> 4); // Takes last two bits from first byte and adds it to first 4 bits of 2nd byte
sextets[2] = ((bytes[1] & 0x0f) << 2) + ((bytes[2] & 0xc0) >> 6); // Takes last 4 bits of 2nd byte and adds it to first 2 bits of third byte
// No last one is needed, because if there were 4, then (i == len) == true
for (j = 0; j < (len - i) + 1; ++j) { // Gets sextets that include data
ret += base64_chars[sextets[j]]; // Appends them to string
}
while ((j++) < 4) // Appends remaining ='s
ret += '=';
}
return ret;
}
Decode Function base64
string base64_decode(const string& input) {
string ret;
size_t i = 0;
unsigned char bytes[3];
unsigned char sextets[4];
while (i < input.size() && input[i] != '=') {
size_t j = i % 4; // index per sextet
if (is_base64(input[i])) sextets[j] = input[i++]; // set sextets with characters from string
else { cerr << "Non base64 string included in input (possibly newline)" << endl; return ""; }
if (i % 4 == 0) {
for (j = 0; j < 4; ++j) // Using j as a seperate index (not the same as it was originally used as, will later be reset)
sextets[j] = indexof(base64_chars, strlen(base64_chars), sextets[j]); // Change value to indicies of b64 characters and not ascii characters
bytes[0] = (sextets[0] << 2) + ((sextets[1] & 0x30) >> 4); // Similar bitshifting to before
bytes[1] = ((sextets[1] & 0x0f) << 4) + ((sextets[2] & 0x3c) >> 2);
bytes[2] = ((sextets[2] & 0x03) << 6) + sextets[3];
for (j = 0; j < 3; ++j) // Using j seperately again to iterate through bytes and adding them to full string
ret += bytes[j];
}
}
if (i % 4 != 0) {
for (size_t j = 0; j < (i % 4); ++j)
sextets[j] = indexof(base64_chars, strlen(base64_chars), sextets[j]);
bytes[0] = (sextets[0] << 2) + ((sextets[1] & 0x30) >> 4); // Similar bitshifting to before
bytes[1] = ((sextets[1] & 0x0f) << 4) + ((sextets[2] & 0x3c) >> 2);
for (size_t j = 0; j < (i % 4) - 1; ++j)
ret += bytes[j]; // Add final bytes
}
return ret;
}
When I try to open the files produced by Image decode function It says that the file format isn't supported, or that it has been corrupted.
The base64 produced by the encode function that I'm trying to decode is in this link
https://pastebin.com/S5D90Fs8
When you open outfile in base64_decode_image, you do not specify the ofstream::binary flag like you do in base64_encode_image when reading the image. Without that flag, you're writing in text mode which can alter the data you're writing (when adjusting for newlines).
We have an certificate file (binary) having '\0' in multiple places. While trying to decode using openssl it gives junk data while size used to be perfect.
Same code works perfectly if there is no '\0' in the base64encoded data
We tried achieving it using below code but still file is not readable
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
int in_1 = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
std::ofstream outfile;
outfile.open("output_file.pfx", std::ios::binary | std::ios::out);
bool f = isalnum(encoded_string[in_]);
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i < 4; i++)
{
char_array_4[i] = base64_chars.find(char_array_4[i]);
}
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
{
if (char_array_3[i] != NULL)
{
ret += char_array_3[i];
char val = char_array_3[i];
outfile.write(&val, sizeof(char));
}
else
{
/*char str3[3155];
strcpy(str3, ret.c_str());
ret = "";
ret.append(str3, sizeof(str3));*/
ret += "NUL";
char val111 = char_array_3[i];
outfile.write(&val111, sizeof(char));
}
}
i = 0;
}
}
if (i) {
for (j = 0; j < i; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
for (j = 0; (j < i - 1); j++)
{
if (char_array_3[i] != NULL)
{
ret += char_array_3[i];
char val1 = char_array_3[i];
outfile.write(&val1, sizeof(char));
}
else
{
ret += "NUL";
char val11 = char_array_3[i];
outfile.write(&val11, sizeof(char));
}
}//ret += char_array_3[j];
}
outfile.close();
return ret;
}
int main()
{
base64_decode("U4tR8mRzyrqpNhhFjkbEe4I6LTYXhL7PxkbddNTQ1yZ6ofZ4s1R/UOQsq6x+CNxB+yddPirwT0yPgtm6IC1qYF9GGQsOqXHkpTrmXf0GiXDVpm91EMnyxtMu74B3OMIYgxmjoeua7HoKQkW6/GRuCpgWIoZQq7uOaKIsc3k9HGgfAFk6vTGER1YJlG28lOhsiGccl0EqD0uhrBGNhFERfAzB2gaJjI1oRO87Q2NbevKHeZycpyXgazvtw9JigA+Hp3+Cy9LUIRvF6k5uv0DKxOs5cynqYslb1LfKqT0IvLjBl4gNHl+pG5/Ur70XzZTiO1+n5jWITPoslZ4slVkl4qiTaqNWHgLT6aSUhWwPlvK+7wlk+st5ykAuSIE2e3Lia+omBRH2LQfG1v7KaOJApF3k4D0li/4QWOJ3zLwBDHB6WCwMQfNS8vTRWM1yIO/o9417wJEpBlcr/B308vGheoTF9+qRKGDe0M5PNHeBbEHhgNkLsKvcS/31HK6Xd36cg85yvyLghQRr9Gyn7TUU5m6f6iSlx3u+yo1vT7BBV6OjbxPklwCIYCZWIIOJq10JXC+bSGPbTKZYXjQW90URKesUOMi9s+DS7BKVEr471AnEyazividrgivfHDNWQisIcOctpDFCfEBAa28PYjIj4KJo5bDkSluRVcVDJVrP2Ns=");
return 0;
}
There is a bug in the handling of the trailing bytes, you are using i as the array index instead of j. As i can be larger than the size of char_array_3 it produces undefined behaviour. The correct code is:
for (j = 0; (j < i - 1); j++)
{
if (char_array_3[j] != NULL)
{
ret += char_array_3[j];
char val1 = char_array_3[j];
outfile.write(&val1, sizeof(char));
}
else
{
ret += "NUL";
char val11 = char_array_3[j];
outfile.write(&val11, sizeof(char));
}
}
I have an opencv image and I want to convert it to a base46 string so I can serialize it.
I have this code:
std::vector<char> convertImageToChar(cv::Mat image)
{
std::stringstream os;
int imageSize = image.size().area() * image.elemSize1();
typedef boost::archive::iterators::base64_from_binary<const char *> base64_text; // compose all the above operations in to a new iterator
std::vector<char> output(base64_text(image.data), base64_text(image.data + imageSize));
return output;
}
The code compiles well, but I am getting error during run time: expression t<64 on line 51 on base64_from_binary.
What is the problem and how I can fix it?
I have no experience with boost base64_text, so in the following I refer to this code for base64 related stuff. It should be straightforward to port to boost, if needed.
Aside from boost related stuff, there are a few problems with your implementation:
You don't take into account that an image may not be continuous.
You won't know how to recover the original image, since you don't encode image size, type and channels.
You can take a look at the following code and how data is managed in the function mat2str and str2mat. This will handle arbitrary Mat type. Their code is an adaptation from here:
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
// Code from: http://www.adp-gmbh.ch/cpp/common/base64.html
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(uchar const* bytes_to_encode, unsigned int in_len) {
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i <4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while ((i++ < 3))
ret += '=';
}
return ret;
}
std::string base64_decode(std::string const& encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4) {
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if (i) {
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
string mat2str(const Mat& m)
{
Mat src;
if (!m.isContinuous()) {
src = m.clone();
}
else {
src = m;
}
// Create header
int type = m.type();
int channels = m.channels();
vector<uchar> data(4*sizeof(int));
memcpy(&data[0 * sizeof(int)], (uchar*)&m.rows, sizeof(int));
memcpy(&data[1 * sizeof(int)], (uchar*)&m.cols, sizeof(int));
memcpy(&data[2 * sizeof(int)], (uchar*)&type, sizeof(int));
memcpy(&data[3 * sizeof(int)], (uchar*)&channels, sizeof(int));
// Add image data
data.insert(data.end(), m.datastart, m.dataend);
// Encode
return base64_encode(data.data(), data.size());
}
Mat str2mat(const string& s)
{
// Decode data
string data = base64_decode(s);
// Decode Header
int rows;
int cols;
int type;
int channels;
memcpy((char*)&rows, &data[0 * sizeof(int)], sizeof(int));
memcpy((char*)&cols, &data[1 * sizeof(int)], sizeof(int));
memcpy((char*)&type, &data[2 * sizeof(int)], sizeof(int));
memcpy((char*)&channels, &data[3 * sizeof(int)], sizeof(int));
// Make the mat
return Mat(rows, cols, type, (uchar*)&data[4*sizeof(int)]).clone();
}
int main()
{
string encoded;
{
Mat3b m(100, 100, Vec3b(0, 0));
circle(m, Point(50, 50), 25, Scalar(0, 255, 0));
imshow("Original", m);
waitKey(1);
encoded = mat2str(m);
}
Mat decoded = str2mat(encoded);
imshow("Reconstructed", decoded);
waitKey();
return 0;
}
I am working on an MFC app that uses CDHtmlDialog class to create a dynamic HTML page.
Now i want to pass/stream a image pointer to the HTML page to show it to the users.
The image will be stored in the hard disk, and the MFC should have a way of streaming this to the HTML page for display on a particular user event.
I am not sure how to convert a JPG or GIF file into something else that i can pass to the HTML page.
Possibly as an argument to JavaScript function residing in the HTML page.
Any help is welcome. Please guide with sample codes.
Thanks in advance.
Firstly, refer to How to display Base64 images in HTML?. Then encode the image data using the following function. Hope this help!
string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i <4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i)
{
for (j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
for (j = 0; (j < i + 1); j++)
ret += base64_chars[char_array_4[j]];
while ((i++ < 3))
ret += '=';
}
return ret;
}
I should note that this program is adhering (at least, trying to) to the Tiled API.
I'm trying to use the uncompress() function in zlib, but for some reason my program crashes whenever I call the function. This is what I have, and all of the parameters look right, so I'm not really sure what the problem is.
// const char* filedata passed in function is Zlib compressed and Base64 encoded
uLong inLen = static_cast<uLong>((strlen(filedata)*6)/8); // Calculate the length
std::string inBuffer = BASE64_DECODE(filedata); // My data
uLongf outLen = static_cast<uLongf>(width*height*4); // Tiled API specification
Bytef* outBuffer = new Bytef(outLen); // Destination
int ret = uncompress(outBuffer, &outLen,
reinterpret_cast<Bytef*>(&inBuffer[0]), inLen);
ret returns nothing, the program crashes. Does anybody have any ideas? Here is the BASE64_DECODE function:
std::string BASE64_DECODE(std::string const& encoded_string)
{
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in_ = 0;
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while(in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_]))
{
char_array_4[i++] = encoded_string[in_]; in_++;
if (i == 4)
{
for (i = 0; i <4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret += char_array_3[i];
i = 0;
}
}
if(i)
{
for (j = i; j <4; j++)
char_array_4[j] = 0;
for (j = 0; j <4; j++)
char_array_4[j] = base64_chars.find(char_array_4[j]);
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
}
return ret;
}
EDIT: If you're looking at this in the future, make sure you delete the outBuffer variable later in the program to prevent memory leaks.
Bytef isn't used with a constructor that takes a length argument. You probably meant Bytef* outBuffer = new Bytef[outLen]; (square brackets).
I think Bytef is usually typedef-ed to some primitive type anyway, so using it is analogous to something like new int[len] or new uint64_t[len].