QImage data alignment - qt

The documentation of
QImage::QImage(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR, void *cleanupInfo = Q_NULLPTR)
describes that the data, refered by parameter 'data', must be 32 bit aligned. http://doc.qt.io/qt-5/qimage.html#QImage-3 But it's at least unclear what is meant exactly. I assume, each pixel takes 32 bits. But that is not the case. Constructing an image like this is working:
uint8_t* rgb = new uint8_t[3 * height * width];
QImage Img(rgb, width, height, QImage::Format_RGB888);
But this is confusing. When I want to get the pixel values from the image, I thought I need to do this (since the data is 32 bit aligned and Qrgb is 32 bit):
QRgb*rawPixelData = (QRgb*) Img.bits();
for(uint32_t i = 0; i < (Img.width * Img.height); ++i)
{
qDebug() << "Red" << qRed(rawPixelData[i]);
qDebug() << "Green" << qGreen(rawPixelData[i]);
qDebug() << "Blue" << qBlue(rawPixelData[i]);
}
But this is not working (leads to a crash). So, I assume, the data is not 32bit aligned. So, isn't the data 32 bit aligned, or I'm understanding something wrong?

I assume that by the "data" they mean the array of bytes used. And by alignment they mean that the first byte of the array would be 32bit aligned and thus data % 4 would always be 0. It is not the internal alignment of every pixel, just the alignment of the memory block that contains the pixel data.
Furthermore, bits() returns a pointer to an unsigned byte, not a pointer to a QRgb. A QRgb is essentially just an integer:
typedef unsigned int QRgb;
I suspect you are getting a crash because the raw data is "compacted". Meaning that if your image has only RGB and no alpha, it will use only 24bits or 3 bytes per pixel, because that would eliminate a 25% memory usage overhead. As a result, you are walking off the actual data and getting a crash.
You should try iterating it as w * h * 3 unsigned chars and incrementing by 3 for each next pixel, and your rgb would be respectively the bytes at i, i+1, i+2.
It could probably work if your image format was RGBA.
And indeed if you bother to check the byteCount you'd realize that the amount of bytes used internally are the minimum amount for a given format:
QImage img(100, 100, QImage::Format_RGB888);
qDebug() << img.byteCount(); // 30000 or 3 bytes or 24 bits
QImage img2(100, 100, QImage::Format_RGB555);
qDebug() << img2.byteCount(); // 20000 or 2 bytes or 15 bits
QImage img3(100, 100, QImage::Format_RGBA8888);
qDebug() << img3.byteCount(); // 40000 or 4 bytes or 32 bits

But it's at least unclear what is meant exactly.
The expression is part of the software engineering vernacular and has nothing to do with the specific situation at hand: it doesn't have anything to do with Qt nor images nor pixels.
On platforms where Qt is supported, it has the following strict meaning:
uchar *data = ...;
Q_ASSERT(reinterpret_cast<uintptr_t>(data) & 3 == 0);
Or, on an arbitrary C++17 platform, it has the following strict meaning:
size_t size = ...;
uchar *data = ...;
Q_ASSERT(std::align(4, size, reinterpret_cast<void*&>(data), size) ==
reinterpret_cast<void*>(data));

Related

Arduino Variable Size and Fixed Point

I am working on a project where I need to use Fixed Point math, I am not able to figure out why the numbers are "Rolling Over", I was able to get a large enough number when I changed the shift amount from 16 to 8 and finally to 4. Here is the code I am using at present:
#define SHIFT_AMOUNT 8
#define SHIFT_MASK ((1 << SHIFT_AMOUNT) - 1)
#define FIXED_ONE (1 << SHIFT_AMOUNT)
#define INT2FIXED(x) ((x) << SHIFT_AMOUNT)
#define FLOAT2FIXED(x) ((int)((x) * (1 << SHIFT_AMOUNT)))
#define FIXED2INT(x) ((x) >> SHIFT_AMOUNT)
#define FIXED2FLOAT(x) (((float)(x)) / (1 << SHIFT_AMOUNT))
int32_t test = FLOAT2FIXED(1.00);
void setup()
{
Serial.begin(57600);
}
void loop(){
test += FLOAT2FIXED(1.00);
Serial.println(FIXED2FLOAT(test));
}
And the output:
1
2
3
...
127
-128
-127
-126
When SHIFT_AMOUNT = 8 I am only able to store variables from -128 to 128 but since I am using a 32 bit variable shouldn't a 16 bit shift move the decimal point to the "Middle" leaving 2 16 bit sections, one for the Whole Number and the other for the decimals? Shouldn't the whole range of the int32_t be −2,147,483,648 to 2,147,483,647 with the shift at 16? Is there a setting that I am missing or am I just way off with how this works?
If SHIFT_AMOUNT = 4 I get a range that I need but this doesn't seem right since all the other examples that I have seen online use the 16 bit shift.
Here is a link showing what I am looking to do
EDIT
If I have this correctly, when shifting 8 bits when using a 16 bit wide type that leaves 8bits for the whole and 8 for the fractal leaving a range of -128 to 128. Hence the need for using the 4bit shift increasing the range of the whole to -32,768 to 32,767 is this correct? If that is right then is the int32_t not a true 32 bit wide?
EDIT2
Patrick Trentin pointed out where I was going wrong. Everything was correct except for the part I copied from the linked question. I was casting to a int not a int32_t. The int type is 16bits wide, hence having to use 4 to get the range I needed.
Change this:
#define FLOAT2FIXED(x) ((int)((x) * (1 << SHIFT_AMOUNT)))
into this:
#define FLOAT2FIXED(x) ((int32_t)((x) * (1 << SHIFT_AMOUNT)))
Rationale: the size of int is 16-bit on an Arduino Uno (see the documentation), this caps the size of the values that you are storing within your int32_t variable to 16 bits.
EDIT:
The fact that int16_t is an alias of signed int, which is an alias for int, can be corroborated by either looking at the online documentation or at the content of the file
arduino-version/hardware/tools/avr/lib/avr/include/stdint.h
among the Arduino Uno sources:
/** \ingroup avr_stdint
16-bit signed type. */
typedef signed int int16_t;

Struct Stuffing Incorrectly

I have the following struct:
typedef union
{
struct
{
unsigned char ID;
unsigned short Vdd;
unsigned char B1State;
unsigned short B1FloatV;
unsigned short B1ChargeV;
unsigned short B1Current;
unsigned short B1TempC;
unsigned short B1StateTimer;
unsigned short B1DutyMod;
unsigned char B2State;
unsigned short B2FloatV;
unsigned short B2ChargeV;
unsigned short B2Current;
unsigned short B2TempC;
unsigned short B2StateTimer;
unsigned short B2DutyMod;
} bat_values;
unsigned char buf[64];
} BATTERY_CHARGE_STATUS;
and I am stuffing it from an array as follows:
for(unsigned char ii = 0; ii < 64; ii++) usb_debug_data.buf[ii]=inBuffer[ii];
I can see that the array has the following (arbitrary) values:
inBuffer[0] = 80;
inBuffer[1] = 128;
inBuffer[2] = 12;
inBuffer[3] = 0;
inBuffer[4] = 23;
...
now I want display these values by changing the text of a QEditLine:
str=QString::number((int)usb_debug_data.bat_values.ID);
ui->batID->setText(str);
str=QString::number((int)usb_debug_data.bat_values.Vdd)
ui->Vdd->setText(str);
str=QString::number((int)usb_debug_data.bat_values.B1State)
ui->B1State->setText(str);
...
however, the QEditLine text values are not turning up as expected. I see the following:
usb_debug_data.bat_values.ID = 80 (correct)
usb_debug_data.bat_values.Vdd = 12 (incorrect)
usb_debug_data.bat_values.B1State = 23 (incorrect)
seems like 'usb_debug_data.bat_values.Vdd', which is a short, is not taking its value from inBuffer[1] and inBuffer[2]. Likewise, 'usb_debug_data.bat_values.B1State' should get its value from inBuffer[3] but for some reason is picking up its value from inBuffer[4].
Any idea why this is happening?
C and C++ are free to insert padding between elements of a structure, and beyond the last element, for whatever purposes it desires (usually efficiency but sometimes because the underlying architecture does not allow unaligned access at all).
So you'll probably find that items of two-bytes length are aligned to two-byte boundaries, so you'll end up with something like:
unsigned char ID; // 1 byte
// 1 byte filler, aligns following short
unsigned short Vdd; // 2 bytes
unsigned char B1State; // 1 byte
// 3 bytes filler, aligns following int
unsigned int myVar; // 4 bytes
Many compilers will allow you to specific how to pack structures, such as with:
#pragma pack(1)
or the gcc:
__attribute__((packed))
attribute.
If you don't want to (or can't) pack your structures, you can revert to field-by-filed copying (probably best in a function):
void copyData (BATTERY_CHARGE_STATUS *bsc, unsigned char *debugData) {
memcpy (&(bsc->ID), debugData, sizeof (bsc->ID));
debugData += sizeof (bsc->ID);
memcpy (&(bsc->Vdd), debugData, sizeof (bsc->Vdd));
debugData += sizeof (bsc->Vdd);
: : :
memcpy (&(bsc->B2DutyMod), debugData, sizeof (bsc->B2DutyMod));
debugData += sizeof (bsc->B2DutyMod); // Not really needed
}
It's a pain that you have to keep the structure and function synchronised but hopefully it won't be changing that much.
Structs are not packed by default so the compiler is free to insert padding between members. The most common reason is to ensure some machine dependent alignment. The wikipedia entry on data structure alignment is a pretty good place to start. You essentially have two choices:
insert compiler specific pragmas to force alignment (e.g, #pragma packed or __attribute__((packed))__.
write explicit serialization and deserialization functions to transform your structures into and from byte arrays
I usually prefer the latter since it doesn't make my code ugly with little compiler specific adornments everywhere.
The next thing that you are likely to discover is that the byte order for multi-byte integers is also platform specific. Look up endianness for more details

Qt - Get audio amplitude from QBytearray

I'm trying to create a program, using Qt (c++), which can record audio from my microphone using QAudioinput and QIODevice. I made a research and I came up with an example located on the this page. This example does what I need.
Now, I am trying to create an audio waveform of the recorded sound. I want to extract audio amplitudes and save them on a QList. To do that I use the following code:
//Check the number of samples in input buffer
qint64 len = m_audioInput->bytesReady();
//Limit sample size
if(len > 4096)
len = 4096;
//Read sound samples from input device to buffer
qint64 l = m_input->read(m_buffer.data(), len);
if(l > 0)
{
//Assign sound samples to short array
short* resultingData = (short*)m_buffer.data();
for ( i=0; i < len; i++ )
{
btlist.append( resultingData[ i ]);
}
}
m_audioInput is QAudioinput | m_buffer is QBytearray | m_input is QIODevice | btlist is QList
I use the following QAudioFormat:
m_format.setFrequency(44100); //set frequency to 44100
m_format.setSampleRate(44100); //set sample rate to 44100
m_format.setChannels(1); //set channels to mono
m_format.setSampleSize(16); //set sample sze to 16 bit
m_format.setSampleType(QAudioFormat::SignedInt ); //signed integer sample
m_format.setByteOrder(QAudioFormat::LittleEndian); //Byte order
m_format.setCodec("audio/pcm"); //set codec as simple audio/pcm
When I print my QList, using qWarning() << btlist.at(int), I get some positive and negative numbers which represents my audio amplitudes. I used Microsoft Excel to plot the data and compare it with the actual sound waveform.
(EDIT BASED ON THE OP COMMENT)
I am drawing the waveform using QPainter in Qt like this
for(int i = 1; i < btlist.size(); i++){
double x1 = (i-(i/1.25))-0.2;
double y1 = btlist.at(i-1);
double x2 = i-(i/1.25);
double y2 = btlist.at(i);
painter.drawLine(x1,y1,x2, y2);
}
The problem is that I also get lots of zeros (0) in my QList between the amplitude data like this, which if I draw as a waveform they are a straight line, which is not normal because it causes corruption to my waveform.
My question is why is that happening? What these zeros (0) represent? Am I doing something wrong? Also, is there a better way to extract audio amplitudes from QBytearray?
Thank you.
The drawline method you are using take integer values. Which means most of the time both of your x indexes will be the same. By simplifiyng your formula the x value at a given i is (i/5.0). By itself it is not an issue because the lines will be superposed, and it is a perfect way of drawing (just to make sure that's what you want to do).
The zero you see can be perfectly valid. They represent silence.
The real issue is that the range of your 16 bits PCM values is [-32767 , 32768]. I doubt that the paint device you are using cover this range. You need to normalize your y-axis. Moreover, it seems taht the qt coordinated system doesn't have negative values (edit: Nevermind the negatives, its says logical coordinates are converted).
For instance, convert your pcm values using :
((btlist.at(i) / MAX_AMPLITUDE + 1.0) / 2) * paintDevice.height();
Edit:
Btw, you are not using l, which is the real amount of data you read. If it is inferior to len, you will read invalid values at the end of your buffer, possibly read garbage\ read zeros\crash.
And your buffer is a byte buffer. And you iterate using a short pointer. So whether you use l or len the maximum size need to be divided by two. This is probably the cause of the ling line of zero in your picture.
for ( i=0; i < l/2; i++ )
{
btlist.append( resultingData[ i ]);
}

how to print a uint16 monochrome image in Qt?

I'm trying to print a image from a Dicom file. I pass the raw data to a convertToFormat_RGB888 function. As far as I know, Qt can't handle monochrome 16 bits images.
Here's the original image (converted to jpg here):
http://imageshack.us/photo/my-images/839/16bitc.jpg/
bool convertToFormat_RGB888(gdcm::Image const & gimage, char *buffer, QImage* &imageQt)
Inside this function, I get inside this...
...
else if (gimage.GetPixelFormat() == gdcm::PixelFormat::UINT16)
{
short *buffer16 = (short*)buffer;
unsigned char *ubuffer = new unsigned char[dimX*dimY*3];
unsigned char *pubuffer = ubuffer;
for (unsigned int i = 0; i < dimX*dimY; i++)
{
*pubuffer++ = *buffer16;
*pubuffer++ = *buffer16;
*pubuffer++ = *buffer16;
buffer16++;
}
imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888);
...
This code is a little adaptation from here:
gdcm.sourceforge.net/2.0/html/ConvertToQImage_8cxx-example.html
But the original one I got a execution error. Using mine at least I get an image, but it's not the same.
Here is the new image (converted to jpg here):
http://imageshack.us/photo/my-images/204/8bitz.jpg/
What am I doing wrong?
Thanks.
Try to get values of pixels from buffer manually and pass it to QImage::setPixel. It can be simplier.
You are assigning 16-bit integer to 8-bit variables here:
*pubuffer++ = *buffer16;
The result is undefined and most compilers just move the lower 8 bits to the destination. You want the upper 8 bits
*pubuffer++ = (*buffer16) >> 8;
The other issue is endianness. Depending to the endianness of the source data, you may need to call one of the QtEndian functions.
Lastly, you don't really need to use any of the 32 or 24-bit Qt image formats. Use 8-bit QImage::Format_Indexed8 and set the color table to grays.

Question about pointer alignment

I'm working on a memory pool implementation and I'm a little confused about pointers alignment...
Suppose that I have a memory pool that hands out fixed size memory blocks, at the point of memory pool creation I malloc((size)*(num of blocks)). If what's being allocated are objects and the size comes from the sizeof operator alignment shouldn't be a concern, but if the size is uneven (he/she wants 100 byte blocks for whatever reason), then when I split the chunk given by malloc I'd end up with unaligned pointers. My question is should I always align the blocks to some boundary and if yes which?
Proper alignment is at least helpful (performance-wise) on most x86 implementations (and some kind of alignment is actually mandatory in other architectures). You might ask (like calloc does) for a pair of arguments, size of items in bytes and number of items, rather than just one (size in bytes, like malloc does); then you can intrinsically align (by rounding up block sizes) to the next-higher power of 2 above the item size (but switch to multiples of 16 bytes above 16, don't keep doubling forever, just like #derobert recommends and explains!-). This way, if a caller just wants N bytes w/o any alignment nor padding, they can always ask for N items of 1 byte each (just like they would with calloc and for the same reason;-).
X86 will work without alignment, but performance is better when data is aligned. Alignment for type is generally sizeof(type), up to a maximum of 16 (bytes).
I wrote this silly test program just to be sure (asuming malloc knows what its doing), and it returns 16 on my amd64 box. It returns 8 when compiled in 32-bit mode:
#include <stdlib.h>
#include <stdio.h>
int main() {
int i;
unsigned long used_bits = 0, alignment;
for (i = 0; i < 1000; ++i) {
used_bits |= (unsigned long)malloc(1); /* common sizes */
used_bits |= (unsigned long)malloc(2);
used_bits |= (unsigned long)malloc(4);
used_bits |= (unsigned long)malloc(8);
used_bits |= (unsigned long)malloc(16);
used_bits |= (unsigned long)malloc(437); /* random number */
}
alignment = 1;
while (!(used_bits & alignment)) {
alignment <<= 1;
}
printf("Alignment is: %lu\n", alignment);
return 0;
}

Resources