Im developing translation on little script that uses ImGui as frontend. I need extended set of unicode characters to be available in font that will be used. Since this script is injecting via DLL there's no way (I think so. I have no experience with c++ at all.) to use:
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels);
Adding font from ttf file resulted in error that data == NULL;
void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0);
if (!data)
{
IM_ASSERT(0); // Could not load file.
return NULL;
}
I've also tried to use io.Fonts->AddFontFromMemoryCompressedBase85TTF and compiling font by included binary_to_compressed_c but output is so big that I'm getting:
fatal error C1091: compiler limit: string exceeds 65535 bytes in length
But function is not accepting any types except char*. I was connecting chars into string and then re-assemble it by str() and c_str() but app was crashing after injection. Here is function handling base85 conversion from ImGui:
ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges)
{
int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4;
void* compressed_ttf = ImGui::MemAlloc((size_t)compressed_ttf_size);
Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf);
ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges);
ImGui::MemFree(compressed_ttf);
return font;
}
How I can fix this problem ? I've tried everything and nothing is working. Only passing smaller chars into compile function is working (Tried with bundled Cousine_Regular.ttf).
I've found workaround this problem. If you really need to use BASE85 there's still no answer but you can increase your size limit by converting to int type (Dont put -base85 in binary_to_compressed_c.exe) then insert resulting table to header file and use instrucions provided by ImGui like so:
Header file:
// File: 'DroidSans.ttf' (190044 bytes)
// Exported using binary_to_compressed_c.cpp
static const unsigned int droid_compressed_size = 134345;
static const unsigned int droid_compressed_data[134348 / 4] =
Your import / render file:
static const ImWchar ranges[] = { 0x0020, 0x00FF, 0x0100, 0x017F, 0 };
//Because I need extended characters im passing my array to function.
io.Fonts->AddFontFromMemoryCompressedTTF(droid_compressed_data, droid_compressed_size, 16.0f, NULL, ranges);
That's getting rid of the problem about converting from string to char and other stuff related to base85 importing.
Related
I'm working with a ATmega328p and Arduino System in a Project, I'm trying to get the saved data in 2 spaces of a eeprom memory and concat it. I always ask to google and check examples but this time I give up.
byte dataEE = readEEPROM(disk1,space);
I normally use strcat, but in this case I cand find the way to convert Byte type to char*
char * strcat ( char * destination, const char * source );
My system is working right now with String to solve this. but a I'd like to know a more efficient way, I always read that we must avoid the String.
String TimeData = String(readEEPROM(disk1,space1)) + String(readEEPROM(disk1,space2));
Maybe something like this:
char TimeData[3];
TimeData[0] = (char) readEEPROM(disk1,space1);
TimeData[1] = (char) readEEPROM(disk1,space2);
TimeData[2] = 0;
Now you can use TimeData wherever you would normally use a null-terminated char* string.
I'm writing a resource file which I want to insert a bunch of data from various common files such as .JPG, .BMP (for example) and I want it to be in binary.
I'm going to code something to retrieve these data later on organized by index, and this is what I got so far:
float randomValue = 23.14f;
ofstream fileWriter;
fileWriter.open("myFile.dat", ios::binary);
fileWriter.write((char*)&randomValue, sizeof(randomValue));
fileWriter.close();
//With this my .dat file, when opened in notepad has "B!¹A" in it
float retrieveValue = 0.0f;
ifstream fileReader;
fileReader.open("myFile.dat", ios::binary);
fileReader.read((char*)&retrieveValue, sizeof(retrieveValue));
fileReader.close();
cout << retrieveValue << endl; //This gives me exactly the 23.14 I wanted, perfect!
While this works nicely, I'd like to understand what exactly is happening there.
I'm converting the address of randomValue to char*, and writing the values in this address to the file?
I'm curious also because I need to do this for an array, and I can't do this:
int* myArray = new int[10];
//fill myArray values with random stuff
fileWriter.open("myFile.dat", ios::binary);
fileWriter.write((char*)&myArray, sizeof(myArray));
fileWriter.close();
From what I understand, this would just write the first address' value in the file, not all the array. So, for testing, I'm trying to simply convert a variable to a char* which I would write to a file, and convert back to the variable to see if I'm retrieving the values correctly, so I'm with this:
int* intArray = new int[10];
for(int i = 0; i < 10; i++)
{
cout << &intArray[i]; //the address of each number in my array
cout << intArray[i]; //it's value
cout << reinterpret_cast<char*>(&intArray[i]); //the char* value of each one
}
But for some reason I don't know, my computer "beeps" when I run this code. During the array, I'm also saving these to a char* and trying to convert back to int, but I'm not getting the results expected, I'm getting some really long values.
Something like:
float randomValue = 23.14f;
char* charValue = reinterpret_cast<char*>(&randomValue);
//charValue contains "B!¹A" plus a bunch of other (un-initiallized values?) characters, so I'm guessing the value is correct
//Now I'm here
I want to convert charValue back to randomValue, how can I do it?
edit: There's valuable information in the answers below, but they don't solve my (original) problem. I was testing these type of conversions because I'm doing a code that I will pick a bunch of resource files such as BMP, JPG, MP3, and save them in a single .DAT file organized by some criteria I still haven't fully figured out.
Later, I am going to use this resource file to read from and load these contents into a program (game) I'm coding.
The criteria I am still thinking but I was wondering if it's possible to do something like this:
//In my ResourceFile.DAT
[4 bytes = objectID][3 bytes = objectType (WAV, MP3, JPG, BMP, etc)][4 bytes = objectLength][objectLength bytes = actual objectData]
//repeating this until end of file
And then in the code that reads the resource file, I want to do something like this (untested):
ifstream fileReader;
fileReader.open("myFile.DAT", ios::binary);
//file check stuff
while(!fileReader.eof())
{
//Here I'll load
int objectID = 0;
fileReader((char*)&objectID, 4); //read 4 bytes to fill objectID
char objectType[3];
fileReader(&objectType, 3); //read the type so I know which parser use
int objectLength = 0;
fileReader((char*)&objectLength, 4); //get the length of the object data
char* objectData = new char[objectLength];
fileReader(objectData, objectLength); //fill objectData with the data
//Here I'll use a parser to fill classes depending on the type etc, and move on to the next obj
}
Currently my code is working with the original files (BMP, WAV, etc) and filling them into classes, and I want to know how I can save the data from these files into a binary data file.
For example, my class that manages BMP data has this:
class FileBMP
{
public:
int imageWidth;
int imageHeight;
int* imageData;
}
When I load it, I call:
void FileBMP::Load(int iwidth, int iheight)
{
int imageTotalSize = iwidth * iheight * 4;
imageData = new int[imageTotalSize]; //This will give me 4 times the amount of pixels in the image
int cPixel = 0;
while(cPixel < imageTotalSize)
{
imageData[cPixel] = 0; //R value
imageData[cPixel + 1] = 0; //G value
imageData[cPixel + 2] = 0; //B value
imageData[cPixel + 3] = 0; //A value
cPixel += 4;
}
}
So I have this single dimension array containing values in the format of [RGBA] per pixel, which I am using later on for drawing on screen.
I want to be able to save just this array in the binary data format that I am planning that I stated above, and then read it and fill this array.
I think it's asking too much for a code like this, so I'd like to understand what I need to know to save these values into a binary file and then read back to fill it.
Sorry for the long post!
edit2: I solved my problem by making the first edit... thanks for the valuable info, I also got to know what I wanted to!
By using the & operator, you're getting a pointer to the contents of the variable (think of it as just a memory address).
float a = 123.45f;
float* p = &a; // now p points to a, i.e. has the memory address to a's contents.
char* c = (char*)&a; // c points to the same memory location, but the code says to treat the contents as char instead of float.
When you gave the (char*)&randomValue for write(), you simply told "take this memory address having char data and write sizeof(randomValue) chars from there". You're not writing the address value itself, but the contents from that location of memory ("raw binary data").
cout << reinterpret_cast<char*>(&intArray[i]); //the char* value of each one
Here you're expected to give char* type data, terminated with a null char (zero). However, you're providing the raw bytes of the float value instead. Your program might crash here, as cout will input chars until it finds the terminator char -- which it might not find anytime soon.
float randomValue = 23.14f;
char* charValue = reinterpret_cast<char*>(&randomValue);
float back = *(float*)charValue;
Edit: to save binary data, you simply need to provide the data and write() it. Do not use << operator overloads with ofstream/cout. For example:
int values[3] = { 5, 6, 7 };
struct AnyData
{
float a;
int b;
} data;
cout.write((char*)&values, sizeof(int) * 3); // the other two values follow the first one, you can write them all at once.
cout.write((char*)&data, sizeof(data)); // you can also save structs that do not have pointers.
In case you're going to write structs, have a look at #pragma pack compiler directive. Compilers will align (use padding) variable to certain size (int), which means that the following struct actually might require 8 bytes:
#pragma pack (push, 1)
struct CouldBeLongerThanYouThink
{
char a;
char b;
};
#pragma pack (pop)
Also, do not write pointer values itself (if there are pointer members in a struct), because the memory addresses will not point to any meaningful data once read back from a file. Always write the data itself, not pointer values.
What's happening is that you're copying the internal
representation of your data to a file, and then copying it back
into memory, This works as long as the program doing the
writing was compiled with the same version of the compiler,
using the same options. Otherwise, it might or it might not
work, depending on any number of things beyond your control.
It's not clear to me what you're trying to do, but formats like
.jpg and .bmp normally specify the format they want the
different types to have, and you have to respect that format.
It is unclear what you really want to do, so I cannot recommend a way of solving your real problem. But I would not be surprised if running the program actually caused beeps or any other strange behavior in your program.
int* intArray = new int[10];
for(int i = 0; i < 10; i++)
{
cout << reinterpret_cast<char*>(&intArray[i]);
}
The memory returned by new above is uninitialized, but you are trying to print it as if it was a null terminated string. That uninitialized memory could have the bell character (that causes beeps when printed to the terminal) or any other values, including that it might potentially not have a null termination and the insertion operator into the stream will overrun the buffer until it either finds a null or your program crashes accessing invalid memory.
There are other incorrect assumptions in your code, like for example given int *p = new int[10]; the expression sizeof(p) will be the size of a pointer in your architecture, not 10 times the size of an integer.
I am helping a friend get a graphics LCD working on his AVR, a few months ago all was working without issue, it has been untouched since then. The chip has now been swapped out from an ATMega32 to an ATMega164P. Essentially the same chip with more flash, since this change a lot of the code has stopped working.
We have narrowed where the error is occuring, but are unable to rectify it. It is where we pass in a pointer to a const char string, and attempt to print that string, however for some reason the stack(heap, something else?) gets corrupted and the pointer contains all zeros. Does anyone have any ideas how this could occur? We have -O1 level optimisations enabled which are required for correct timing, we have switched to winAVR compiler as well with no changes. We also do not have access to a debugger, and only have limited 'print' style debugging.
Here is the section of code that is causing issues:
//in the header file that is included
int SGCTEXTStringF(int column, int row, int font, int colour, const char* text);
//Call the function
SGCTEXTStringF(0, 0, 0x10, SGCColour(255,255,255), "text");
//Function
int SGCTEXTStringF(int column, int row, int font, int colour, const char* text){
unsigned char bytes[23]={0};
//...Code to communicate with LCD and set up a 'print string'
if(text[0] == 0) {
bytes[6] = 'a';
bytes[7] = 't';
bytes[8] = 'e';
bytes[9] = 's';
bytes[10] = 't';
}
//..more code to finish sending the array
}
Now the display prints 'atest' when the code is run, this is showing that the const char array is being some how zero'd? I have also tried the following lines which also all print 'atest'
if(text[1] == 0) //prints 'atest'
if(*text== 0) //prints 'atest'
if(text != 0) //prints 'atest'
This shows that it gets a valid pointer, but it appears to point to all zeros.
We also tried changing the call to the method to:
const char * string = "test";
SGCTEXTStringF(0, 0, 0x10, SGCColour(255,255,255), string);
This code was known to be working a few months ago, we even have a video of it running, now every single function in the program exhibits the same issue, char arrays being passed (on the stack?) don't seem to work and get cleared to 0s.
I can arrange to host a copy of the complete source code if anyone is interested. Any help or pointers at all are appreciated!
The ATMega164P is not the replacement for the ATMega32 but for the ATMega16. For the ATMega32 you would need the ATMega324P.
If you are using the memory map for the ATMega32 (which has double EEPROM, SRAM and flash), your string may have landed in memory which simply does not exist.
For porting issues you may look at the porting guide from Atmel.
I'm trying to port the C openGL texture loading code found here:
http://www.nullterminator.net/gltexture.html
to C++. In particular I'm trying to deal with reading some textures in from a file, what is the best way of rewriting the following code in an idiomatic and portable manner:
GLuint texture;
int width = 256, height = 256;
BYTE * data;
FILE * file;
// open texture data
file = fopen( filename, "rb" );
if ( file == NULL ) return 0;
// allocate buffer
data = malloc( width * height * 3 );
// read texture data
fread( data, width * height * 3, 1, file );
fclose( file );
In particular what is the best way of replacing the BYTE macro in a c++ way that is portable?
EDIT: BYTE macro is not defined in the current environment I am working in. I was trying to figure out what the underlying type of this is on other systems so that I can typedef for the correct type.
Assuming the original code is portable, you can just leave it. Just make sure you pull in the definition of BYTE as is. C++ compilers are backwards compatible to C, so the corresponding headers are still there.
(If BYTE is really a macro, I'd perhaps typedef it.)
The C code should work just fine when compiled as C++.
Rather than use the BYTE type, just use the OpenGL-defined type GLbyte, which is the actual type the APIs take anyway. It is defined in gl.h thus:
typedef signed char GLbyte;
A very quick (untested!) translation of the above code into C++ would be something like:
GLuint texture;
unsigned width = 256, height = 256;
unsigned buffer_size = width * height * 3;
GLbyte * data;
std::ifstream file;
// open texture data
file.open(filename, ios_base::in | ios_base::binary);
if (!file) return 0;
// allocate buffer
data = new BYTE[buffer_size];
// read texture data
file.read(data, buffer_size);
file.close();
// Process data...
// ...
// Don't forget to release it when you're done!
delete [] data;
BYTE* in this case seems to be just a macro for char* or unsigned char*. I could be wrong but I doubt it. So using char* or unsigned char* in your program would be equivalent. However if you are porting from C to C++ you might want to consider using ifstream (in binary mode) from the C++ standard library.
Use unsigned char instead of BYTE - should work as expected (you might have to cast the return value of malloc().
I'm pretty close to losing my head here ;)
I'm developing a service that uses gsoap. I would like to return a mime response.
I have everything working, but when reading binary files, all kind of files like jpeg, pdf, etc... contains the \0 char several times over the data (if opened with notepad can see a lot of NUL).
So any code for reading a raw file fails miserably once it finds the end-of-file char. I have tried to replace the \0 but the file becomes incorrect to display.
I have also tried several methods including the example that comes with gsoap.
So resuming,
fstream generic code doesn't work.
for (i = 0; i < MAX_FILE_SIZE; i++)
{ if ((c = fgetc(fd)) == EOF)
break;
image.__ptr[i] = c;
}
doesn't work also
QFile::ReadAll works but when converting QString to char* the array is trimmed in the first NUL.
So, which is the best aproach to read an entire binary file? Its crazy how sometimes C++ at the basic.
Thanks in advance.
I have tried this as retnick suggested below
UrlToPdf urlToPdf;
urlToPdf.getUrl(&input, &result);
QByteArray raw = urlToPdf.getPdf(QString(result.data.c_str()));
int size = raw.toBase64().size();
char* arraydata = new char[size];
strcpy(arraydata, raw.toBase64().data());
soap_set_mime(this, "MIME_boundary", NULL);
if(soap_set_mime_attachment(this, arraydata, size, SOAP_MIME_BASE64, "application/pdf", NULL, NULL, NULL))
{
soap_clr_mime(this);
soapMessage = this->error;
}
but no luck... the mime response is bigger than the actual file...
David G Ortega
to read binary files use fread()
Once you read it treat it as an array of bytes not as a string. No string functions allowed.
EDIT: The gSOAP documentation section 14.1 explains how to send MIME attachments. I only refer to the relevant function (please read it all).
int soap_set_mime_attachment(struct soap *soap, char *buf_ptr, size_t buf_size,
enum soap_mime_encoding encoding,
const char *type, const char *id,
const char *location, const char *description);
char *buf_ptr is your buffer.
size_t buf_size is the length of your buffer.
So just do your QFile::ReadAll.
this gives you back a QByteArray. The QByteArray has the method
QByteArray QByteArray::toBase64 () const
this will return a
QByteArray base64image = QByteArray::toBase64(rawImage);
so now just do
soap_set_mime(soap, "MIME_boundary", "<boundary.xml#just-testing.com>");
/* add a base64 encoded image (base64image points to base64 data) */
soap_set_mime_attachment(soap,
base64image.data(), base64image.size(),
SOAP_MIME_BASE64, "image/jpeg",
"<boundary.jpeg#just-testing.com>", NULL, NULL);
I have not tested this but should be close to finished.
QFile::ReadAll works but when converting QString to char* the array is trimmed in the first NUL.
Are you sure it's actually trimmed or you just can't print/view the array in the debugger [since C-style strings are 0 terminated]?
If the QString itself is not enough for your needs you may want to convert it to a std::vector or similar using the range constructor or range assign, you'll have lots less grief towards the how much data the container holds.
EDIT:
Here's some sample code for fstream reading from a binary file:
std::ifstream image( <image_file_name>, std::ios_base::in | std::ios_base::binary );
std::istream_iterator< char > image_begin( image ), image_end;
std::vector< char > vctImage( image_begin, image_end );
The std::ios_base::binary is the most important part of the thing (similar to fopen/fread ["rb"] & probably QFile has something similar)
Also posting some sample code usually helps in getting the right answer.
HIH
I have the solution for this... As renick suggested I tried his idea but it failed without undestanding it so much... From a logical point of view recnick was right... bat the truth is that any king of string manipulation using QT QByteArray, std or mem is going to stop when findind the first \0 char, Qt QString can do it without problems but when converting it to c string (char*) the data will be again trimmed with the first \0
I found that using QDataStream::readRawData reads the file into a char* given the size to read. So thats how I accomplished the deal...
QFile file("test.pdf");
file.open(QIODevice::ReadOnly);
int size = file.size();
char* buffer = new char[size];
QDataStream stream(&file);
stream.readRawData(buffer, size);
soap_set_mime(this, "MIME_boundary", NULL);
if(soap_set_mime_attachment(this, buffer, size, SOAP_MIME_BINARY, "application/pdf", NULL, NULL, NULL))
{
soap_clr_mime(this);
soapMessage = this->error;
}
Note that in the line
if(soap_set_mime_attachment(this, buffer, size, SOAP_MIME_BINARY, "application/pdf", NULL, NULL, NULL))
I'm still using the size var instead of doing sizeof(buffer) or any other aproach since this one is going to trimm again the data qhen finding the first \0...
Hope this helps...
David G Ortega