Qt toBase64 and Linux base64 differs - c++

Subj. Why can it be?
I've tried all the flags for Qt toBase64 but nothing changed.
Bash:
cat Invader_1.png | base64
Output:
iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz
AAALEwAACxMBAJqcGAAAA0JJREFUeJzt3MFt20AURdHnQIWoFLoSq5S4E7uSsBR24mxiIIsgSDIT
cex3DjBLjT5J4ULcTAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACcY0vyNmFt9x27yhbPaKovZw8AnEcAoJgAQDEBgGICAMUEAIoJABQTACgm
AFBMAKCYAEAxAYBiAgDFBACKCQAUEwAodjl7gIUcSZ4n7fV18PNHkpfhKdZyS3Id3GPPnGd0TNgD
fmnP+Ik1+51nvoc97styvAJAMQGAYgIAxQQAigkAFBMAKCYAUEwAoJgAQDEBgGICAMUEAIoJABQT
ACgmAFBMAACSbBk/sML6GGsLSfwDgGoCAMUEAIoJABQTACgmAFBMAKCYAEAxAYBiAgDFBACKCQAU
EwAoJgBQTACgmABAscvZA0xyS3Id3GP08+9ekxyDe1yTPA1PspaV7sst44eCHEleBvdgkj3nnzIz
87SZbYHrcF9+v/YJ13M6rwBQTACgmABAMQGAYgIAxQQAigkAFBMAKCYAUEwAoJgAQDEBgGICAMUE
AIoJABQTACj2cPL3b0m+nTwDnOkxJx4u4h8AFBMAKCYAUEwAoJgAQDEBgGICAMUEAIoJABQTACgm
AFBMAKCYAEAxAYBiAgDFBACKXc4eYJLXJMfgHtckT8OT8BH4vSxiS/I2YW0LzWKtv7aM2xaa5Z95
BYBiAgDFBACKCQAUEwAoJgBQTACgmABAMQGAYgIAxQQAigkAFBMAKCYAUEwAoJgAQDEBmO8xyYP1
X9bjXzwH/oAAQDEBgGICAMUEAIoJABQTACgmAFBMAKCYAEAxAYBiAgDFBACKCQAUEwAoJgBQTACg
2OXk7z+SPE/aZ8YeM2bZfqwVvGT83lyT3Ab3mGXP5/u9HBP2YCF7krdF1jbherYFruN97ROuh594 BYBiAgDFBACKCQAUEwAoJgBQTACgmABAMQGAYgIAxQQAigkAFBMAKCYAUEwAoJgAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAn3wG6mDu8
W58tNgAAAABJRU5ErkJggg==
Qt:
QImage image;
image.load("/home/undead/Pictures/1489180309_Invader_1.png");
image.save(&buffer, "PNG");
buffer.close();
bytes_array = bytes_array.toBase64();
Output:
iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAACXBIWXMAAAsTAAALEwEAmpwYAAADQklEQVR4nO3cwW3bQBRF0edAhagUuhKrlLgTu5KwFHbibGIgiyBIMhNx7HcOMEuNPknhQtxMAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJxjS_I2YW33HbvKFs9oqi9nDwCcRwCgmABAMQGAYgIAxQQAigkAFBMAKCYAUEwAoJgAQDEBgGICAMUEAIoJABQTACh2OXuAhRxJnift9XXw80eSl-Ep1nJLch3cY8-cZ3RM2AN-ac_4iTX7nWe-hz3uy3K8AkAxAYBiAgDFBACKCQAUEwAoJgBQTACgmABAMQGAYgIAxQQAigkAFBMAKCYAUEwAAJJsGT-wwvoYawtJ_AOAagIAxQQAigkAFBMAKCYAUEwAoJgAQDEBgGICAMUEAIoJABQTACgmAFBMAKCYAECxy9kDTHJLch3cY_Tz716THIN7XJM8DU-ylpXuyy3jh4IcSV4G92CSPeefMjPztJltgetwX36_9gnXczqvAFBMAKCYAEAxAYBiAgDFBACKCQAUEwAoJgBQTACgmABAMQGAYgIAxQQAigkAFBMAKPZw8vdvSb6dPAOc6TEnHi7iHwAUEwAoJgBQTACgmABAMQGAYgIAxQQAigkAFBMAKCYAUEwAoJgAQDEBgGICAMUEAIpdzh5gktckx-Ae1yRPw5PwEfi9LGJL8jZhbQvNYq2_tozbFprln3kFgGICAMUEAIoJABQTACgmAFBMAKCYAEAxAYBiAgDFBACKCQAUEwAoJgBQTACgmABAMQGY7zHJg_Vf1uNfPAf-gABAMQGAYgIAxQQAigkAFBMAKCYAUEwAoJgAQDEBgGICAMUEAIoJABQTACgmAFBMAKDY5eTvP5I8T9pnxh4zZtl-rBW8ZPzeXJPcBveYZc_n-70cE_ZgIXuSt0XWNuF6tgWu433tE66Hn3gFgGICAMUEAIoJABQTACgmAFBMAKCYAEAxAYBiAgDFBACKCQAUEwAoJgBQTACgmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcCffAbqYO7xbny02AAAAAElFTkSuQmCC

You are comparing 2 different things.
cat Invader_1.png | base64
Outputs the base64 binary content of Invader_1.png.
While
QImage image;
image.load("/home/undead/Pictures/1489180309_Invader_1.png");
image.save(&buffer, "PNG");
buffer.close();
bytes_array = bytes_array.toBase64();
Converts 1489180309_Invader_1.png into a pixel image and back to a PNG and then outputs the base64 binary content of the new PNG.
And as stated by #JustRufus and #TobySpeight, a PNG of the same image can be created with different settings (e.g compression levels) and/or metadata leading to different binary contents.
If you want to compare things you should fix your Qt code to just read the file:
QFile file("/home/undead/Pictures/1489180309_Invader_1.png");
file.open(QFile::ReadOnly);
QByteArray data = file.readAll();
file.close();
data = data.toBase64();

Related

Qt: Safe parsing of Windows format data under Linux

I have a Server-Client application in which JSON data is send between those. The Client has a Linux and a Windows version, while the Server application runs under Linux.
The Linux Client communicates just find, but I have problems with the Windows Client.
The problematic JSON data contains a text field with an apostrophe. Let's say the content is "a dog`s name", then the Windows client sends this as "a dog\x92s name", while the Linux client goes for "a dog\xE2\x80\x99s name", at least that is what qDebug() shows me.
I parse the JSON data with the lines
QJsonDocument document = QJsonDocument::fromJson(body);
if(document.isArray()) json_data = document.array();
if(document.isObject()) json_data.append(document.object());
where body is a QByteArray and json_data is a QJsonArray.
If the Windows data is fed into this, it seems that the Qt JSON parser does not recognize it as valid JSON and thus json_data end up being empty.
I really don't want to do anything manually with that text specific to those very characters, as I want it not only to work with that apostrophe but with all kinds of special characters that a user might enter in general. Is there some way to handle this in general? I assume the Windows is in something like the Windows-1252 encoding?
I think windows client sends strings encoded in CP1251 or CP1252. And json decoder expects utf-8.
Maybe source code is not in utf-8 and has string literals. Qt4 has QTextCodec::setCodecForCStrings. Qt5 assume string literals encoded in utf-8.
$ echo -n "’" | iconv -f utf-8 -t cp1251 | xxd
00000000: 92
$ echo -n "’" | xxd
00000000: e280 99
If you don't want to fix windows client the proper way (fixing it's output encoding) you can deal with this situation by converting all input from windows client to unicode before building QJsonDocument on server.
QByteArray bodycp1252;
QTextCodec* cp1252 = QTextCodec::codecForName("CP1252");
QTextCodec* utf8 = QTextCodec::codecForName("UTF-8");
QByteArray body = utf8->fromUnicode(cp1252->toUnicode(bodycp1252));
QJsonDocument document = QJsonDocument::fromJson(body);
It's possible to check if QByteArray contains valid utf-8 data with QUtf8::isValidUtf8(const char *chars, qsizetype len) function. It is defined in private headers, so you need to add QT += core-private. Unfortunately implementation is not visible by linker (not exported from QtCore.lib) so you need to add qutfcodec.cpp from qt sources to your project to resolve linker errors.
////////////////// is-valid-utf8.pro
QT -= gui
QT += core core-private
CONFIG += c++11 console
CONFIG -= app_bundle
qt_src = "C:/Qt/5.15.1/Src"
SOURCES += \
main.cpp \
$$qt_src/qtbase/src/corelib/codecs/qutfcodec.cpp
////////////////// main.cpp
#include <QCoreApplication>
#include <private/qutfcodec_p.h>
#include <QTextCodec>
#include <QDebug>
bool isValidUtf8(const QByteArray& data) {
return QUtf8::isValidUtf8(data.data(), data.size()).isValidUtf8;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextCodec* utf8 = QTextCodec::codecForName("UTF-8");
QTextCodec* cp1251 = QTextCodec::codecForName("CP1251");
QByteArray utf8data1 = utf8->fromUnicode("Привет мир");
QByteArray cp1251data1 = cp1251->fromUnicode("Привет мир");
QByteArray utf8data2 = utf8->fromUnicode("Hello world");
QByteArray cp1251data2 = cp1251->fromUnicode("Hello world");
Q_ASSERT(isValidUtf8(utf8data1));
Q_ASSERT(isValidUtf8(cp1251data1) == false);
Q_ASSERT(isValidUtf8(utf8data2));
Q_ASSERT(isValidUtf8(cp1251data2));
qDebug() << "test passed";
return 0;
}
source

How to encode text in Choregraphe NAO

Encoded text
I want to read list from file but its getting all coded and .encode doesn't really work
import json,sys
with open('your_file.txt') as f:
lines = f.read().splitlines()
self.logger.info(lines)
self.tts.say(lines[1])
If your file is saved with UTF-8 encoding, this should work:
with open('text.txt', encoding = 'utf-8', mode = 'r') as my_file:
If this doesn't work, your text file's encoding is not UTF-8. Write your file's encoding in place of utf-8. How to determine the encoding of text?
Or if you share your input file as is, I can figure that out for you.

Converting a sequence of ppm images to video with python

I'm trying to make a video out of ppm images using IPython (python 2.7).
I wrote this code :
import cv2
import glob
img1 = cv2.imread('C:/Users/Joseph/image0.ppm')
height, width, layers = img1.shape
video1 = cv2.VideoWriter('video1.avi', -1, 1, (width, height))
filenames = glob.glob('C:/Users/Joseph/*.ppm')
for filename in filenames:
print(filename)
img = cv2.imread(filename)
video1.write(img)
cv2.destroyAllWindows()
video1.release()
The video is created but is empty size=0B and it cannot be opened.
There is no error message.
I suspect the problem is the writing of the location, since print(filename) yields :
C:/Users/Joseph\image0.ppm
C:/Users/Joseph\image1.ppm
C:/Users/Joseph\image2.ppm
C:/Users/Joseph\image2.ppm
instead of what I had expected : C:/Users/Joseph/image0.ppm
Could you help me please?
EDIT: The type of file is type: GIMP 2.10.14 (.ppm). Could the issue be connected to this type of ppm ?
EDIT 2: It seems that the issue is not connected directly to .ppm.
Indeed, I tried (taking into account the answer of Rotem) :
import cv2
import glob
i = cv2.imread('C:/Users/Joseph/image0.ppm')
cv2.imwrite('C:/Users/Joseph/image.jpg',i)
img1 = cv2.imread('C:/Users/Joseph/image.jpg')
height, width, layers = img1.shape
# Set FOURCC code to '24BG' - '24BG' is used for creating uncompressed raw video
video1 = cv2.VideoWriter('video1.avi', cv2.VideoWriter_fourcc('D','I','B',' '), 1, (width, height))
filenames = glob.glob('C:/Users/Joseph/*.ppm')
try:
for filename in filenames:
print(filename)
img = cv2.imread(filename)
cv2.imwrite('C:/Users/Joseph/a.jpg',img)
img=cv2.imread('C:/Users/Joseph/a.jpg')
# Display input image for debugging
cv2.imshow('img', img)
cv2.waitKey(1000)
video1.write(img)
except:
print('An error occurred.')
cv2.destroyAllWindows()
video1.release()
And it doesn't work either. And I don't get any image displayed.
so it seems that it's an error in my cv2 for video. The jpg is well created.
EDIT : The solution.
In the spirit of the answer of rotem, I tried : cv2.VideoWriter_fourcc('M','J','P','G') and it worked !
There are multiple reasons for getting an empty video file, but the path looks correct.
In Windows system C:/Users/Joseph\image0.ppm and C:/Users/Joseph/image0.ppm are the same.
Manually delete video1.avi file, just to make sure the file is not locked.
I think the issue involved video codec, but I can't be sure about it.
in the command video1 = cv2.VideoWriter('video1.avi', -1, 1, (width, height)), the second parameter is a FOURCC code that selects the video codec for the video encoder.
When setting the value to -1, a dialog box is opened letting you select the codec.
In older versions of OpenCV it's not always working.
Try setting the FOURCC to 'DIB ', applies "Basic Windows bitmap format".
Use it for creating raw (uncompressed) AVI video file.
Here is the code:
import cv2
import glob
img1 = cv2.imread('C:/Users/Joseph/image0.ppm')
height, width, layers = img1.shape
# Set FOURCC code to '24BG' - '24BG' is used for creating uncompressed raw video
video1 = cv2.VideoWriter('video1.avi', cv2.VideoWriter_fourcc('D','I','B',' '), 1, (width, height))
filenames = glob.glob('*.ppm')
try:
for filename in filenames:
print(filename)
img = cv2.imread(filename)
# Display input image for debugging
cv2.imshow('img', img)
cv2.waitKey(1000)
video1.write(img)
except:
print('An error occurred.')
cv2.destroyAllWindows()
video1.release()
I added cv2.imshow('img', img) to help you debugging the problem, in case it's not a codec issue.
Make sure you are not getting any exceptions.
Please let me no if my answer solves your problem.

libavformat: get formats Mime Type in C++

I work on an C++ Application running on Arch Linux that should use libavformat to obtain a media files mime type. Currently using the following lines:
std::string path = "/path/to/file.extension";
av_register_all();
AVFormatContext* pFormatCtx = avformat_alloc_context();
avformat_open_input(&pFormatCtx, path.c_str(), NULL, NULL);
avformat_find_stream_info(pFormatCtx, NULL);
std::string mimeType(pFormatCtx->iformat->mime_type);
Now, that will work as expected with *.mkv (Matroska) files. Returning the expected Comma seperated mimeType String "video/x-matroska,...". But with any other File Format like *.mp4 or *.avi the iformat->mime_type will always return NULL.
How do i get the Mime Types of the other Container Formats?
It seems that avformat_find_stream_info sets only the iformat and that most
AVInputFormat variables don't initialize the mime_type field.
You can also use
AVOutputFormat* format = av_guess_format(NULL,path.c_str(),NULL);
if(format)
printf("%s\n",format->mime_type);

How to read a XML file using fstream in IOS

I am using XCode, and here is a c++ code in XCode
std::fstream stream("templates.Xml", std::ios::binary | std::ios::in);
if(!stream) return false;
I put the Xml file in the folder that contain the ".xcodeproj", and I put it in the folder that contains ".app" but the stream always return false, why?
It looks like you are trying to open the file from the wrong directory.
"templates.Xml" is saved in the bundle- is not saved in the documents directory. By default, if you open "./filename", this actually points to:
/Users/arinmorf/Library/Application Support/iPhone Simulator/7.0.3/Applications/246E91F9-FAB2-4A46-B1F1-855B5363F24D/Documents/
Where arinmorf would be your username and the long hex string is randomly generated every time you install the app on the simulator.
The templates.xml file would be found in:
/Users/arinmorf/Library/Application Support/iPhone Simulator/7.0.3/Applications/246E91F9-FAB2-4A46-B1F1-855B5363F24D/iFly.app/templates.xml
iFly.app is the name of my app, yours would be "T". BUT you can't use the absolute path in your project, because of the randomly generated string, you need to use the NSBundle or CFBundleRef.
In objective-C, you would use:
filePath = [[NSBundle mainBundle] pathForResource:#"templates" ofType:#"xml"];
NSData *myData = [NSData dataWithContentsOfFile:filePath];
In C++ it looks like:
CFURLRef fileURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("templates"), CFSTR("xml"), NULL);
CFStringRef filePath = CFURLCopyFileSystemPath(fileURL, kCFURLPOSIXPathStyle);
CFStringEncoding encodingMethod = CFStringGetSystemEncoding();
const char *path = CFStringGetCStringPtr(filePath, encodingMethod);
FILE* f = fopen(path, "r");
(Credit to Chris Frederick at https://stackoverflow.com/a/8768366/2070758 for C++ version)
Yes, I solved the problem in two ways either depending on Main Bundle, or create custom bundle and use it.