I have a function that takes two Image inputs (image and image2), mixing the color values pixel-by-pixel. Factor represents the percentage of the color value from image, so it follows that the remaining value (1-factor) is from image2. I have the pixel buffer represented by unsigned characters, and I'm having difficulty figuring out what syntax I need in order to access and set my values. I've tried a number of things, but right now it gives me the following error:
filters.C:91:41: error: scalar object āpā requires one element in initializer
unsigned char *p = {red, green, blue};
The function:
void Filter::Execute()
{
if (input->GetWidth() == input2->GetWidth() && input->GetHeight() == input2->GetHeight())
{
int width = input->GetWidth();
int height = input->GetHeight();
output.ResetSize(width, height);
for (int w = 0; w < width; w++)
{
for (int h = 0; h < height; h++)
{
unsigned char red = input->GetPixel(w, h)[0]*factor+input2->GetPixel(w, h)[0]*(1-factor);
unsigned char green = input->GetPixel(w, h)[1]*factor+input2->GetPixel(w, h)[1]*(1-factor);
unsigned char blue = input->GetPixel(w, h)[2]*factor+input2->GetPixel(w, h)[2]*(1-factor);
unsigned char *p = {red, green, blue};
output.SetPixel(w, h, p);
}
}
}
}
And this is how I have my image class set up:
#include <image.h>
#include <stdlib.h>
Image::Image()
{
width = 0;
height = 0;
buffer = NULL;
}
Image::~Image()
{
if (buffer != NULL)
{
delete[] buffer;
}
}
void Image::ResetSize(int w, int h)
{
width = w;
height = h;
if (buffer != NULL)
{
delete[] buffer;
}
else
{
buffer = new unsigned char[3*width*height];
}
}
unsigned char * Image::GetPixel(int w, int h)
{
int index = h*width + w;
return buffer+3*index;
}
void Image::SetPixel(int w, int h, unsigned char *p)
{
int index = h*width + w;
buffer[3*index+0] = p[0];
buffer[3*index+1] = p[1];
buffer[3*index+2] = p[2];
}
What am I overlooking?
unsigned char * is not an array, it's a pointer. You want to declare it
unsigned char p[] = {red, green, blue};
Related
stb_image.h provides a method to flip an image vertically and it works fine. I tried to implement an horizontal flip aka mirror but it alters the image colors.
On pictures that only have 3 colors you could get bluish or reddish or even magenta colored pictures instead of their actual colors. It's the same if we're talking about JPEG or PNG images, you get the same strange results. Curiously if you flip that very same image vertically, its colors look normal.
I've tried testing pretty much any function you could find here and the code I'm providing you with has been the only one that got me close to my actual goal.
// Function I've been trying to implement to enable Horizontal Flip
static void stbi_horizontal_flip(void *image, int w, int h, int bytes_per_pixel)
{
size_t line_bytes = (size_t)w * bytes_per_pixel;
stbi_uc temp[line_bytes];
stbi_uc *bytes = (stbi_uc *)image;
Debug() << line_bytes;
for (int col = 0; col < h; col++) {
stbi_uc *line = bytes + col * line_bytes;
memcpy(&temp, line, line_bytes);
for (int row = 0; row < line_bytes; row++) {
line[row] = temp[line_bytes - row - bytes_per_pixel];
}
}
stbi_horizontally_flip_on_load = false;
}
// stb_image's function for Vertical Flip
static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel)
{
int row;
size_t bytes_per_row = (size_t)w * bytes_per_pixel;
stbi_uc temp[2048];
stbi_uc *bytes = (stbi_uc *)image;
for (row = 0; row < (h>>1); row++) {
stbi_uc *row0 = bytes + row * bytes_per_row;
stbi_uc *row1 = bytes + (h - row - 1) * bytes_per_row;
size_t bytes_left = bytes_per_row;
while (bytes_left) {
size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp);
memcpy(temp, row0, bytes_copy);
memcpy(row0, row1, bytes_copy);
memcpy(row1, temp, bytes_copy);
row0 += bytes_copy;
row1 += bytes_copy;
bytes_left -= bytes_copy;
}
}
}
static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
{
stbi__result_info ri;
void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
if (result == NULL) return NULL;
if (ri.bits_per_channel != 8) {
STBI_ASSERT(ri.bits_per_channel == 16);
result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
ri.bits_per_channel = 8;
}
// #TODO: move stbi__convert_format to here
if (stbi_horizontally_flip_on_load) {
int channels = req_comp ? req_comp : *comp;
stbi_horizontal_flip(result, *x, *y, channels * sizeof(stbi_uc));
}
if (stbi__vertically_flip_on_load) {
int channels = req_comp ? req_comp : *comp;
stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc));
}
return (unsigned char *) result;
}
STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
{
unsigned char *result;
stbi__context s;
stbi__start_file(&s,f);
result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
if (result) {
// need to 'unget' all the characters in the IO buffer
fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
}
return result;
}
STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
{
FILE *f = stbi__fopen(filename, "rb");
unsigned char *result;
if (!f) return stbi__errpuc("can't fopen", "Unable to open file");
result = stbi_load_from_file(f,x,y,comp,req_comp);
fclose(f);
return result;
}
STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
{
stbi__context s;
stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
}
void Gosu::load_image_file(Gosu::Bitmap& bitmap, const string& filename)
{
Buffer buffer;
load_file(buffer, filename);
load_image_file(bitmap, buffer.front_reader());
}
void Gosu::load_image_file(Gosu::Bitmap& bitmap, Reader input)
{
bool needs_color_key = is_bmp(input);
stbi_io_callbacks callbacks;
callbacks.read = read_callback;
callbacks.skip = skip_callback;
callbacks.eof = eof_callback;
int x, y, n;
stbi_uc* bytes = stbi_load_from_callbacks(&callbacks, &input, &x, &y, &n, STBI_rgb_alpha);
if (bytes == nullptr) {
throw runtime_error("Cannot load image: " + string(stbi_failure_reason()));
}
bitmap.resize(x, y);
printf("Channels %d, Gosu Color size %d, unsigned char size %d, bytes array size %d",
n, sizeof(Gosu::Color), sizeof(stbi_uc), sizeof(bytes));
// Output: Channels 3 or 4, Gosu Color size 4, unsigned char size 1, bytes array 8
memcpy(bitmap.data(), bytes, x * y * sizeof(Gosu::Color));
stbi_image_free(bytes);
if (needs_color_key) apply_color_key(bitmap, Gosu::Color::FUCHSIA);
}```
// Output: Channels 3 or 4, Gosu Color size 4, unsigned char size 1, bytes array 8
That is what I got back from stb_image, but I'd prefer to get an 8bit array instead. Even so what actually matters is to get rid of that unexpected color change.
Thanks to Igor's comment I could focus on my immediate problem and not long after I came up with the code I've posted below.
What I've been wondering since I finally could flip the images horizontally was why the other methods I found either on the web or as part of image processors' code didn't work as expected. O_o? Sometimes I copied and pasted them only changing some variables' names or types to match stb_image's and they still failed either to compile or display a decent result.
By the way, I tried before to subtract positions to the right value to no avail but it made me think some of them could be used as nice color blend effects. XD
// Horizontal Flip by Kyonides Arkanthes shared under GPLv2 or v3
static void stbi_kyon_horizontal_flip(void *image, int w, int h, int bytes_per_pixel)
{
size_t line_bytes = (size_t)w * bytes_per_pixel;
stbi_uc temp[line_bytes];
stbi_uc *bytes = (stbi_uc *)image;
int lpos, rpos;
for (int col = 0; col < h; col++) {
stbi_uc *line = bytes + col * line_bytes;
memcpy(&temp, line, line_bytes);
for (int row = 0; row < w; row++) {
lpos = row * bytes_per_pixel;
rpos = line_bytes - row * bytes_per_pixel - 1;
line[lpos] = temp[rpos - 3];
line[lpos + 1] = temp[rpos - 2];
line[lpos + 2] = temp[rpos - 1];
line[lpos + 3] = temp[rpos];
}
}
stbi_kyon_horizontally_flip_on_load = false;
}```
You just reversed the order of RGBA, you try to use this, I tested, the effect is normal.
for (int row = 0; row < Qimg2.width(); row++) {
lpos = row * bytes_per_pixel;
rpos = line_bytes - row * bytes_per_pixel - 1;
line[lpos] = temp[rpos - 2];
line[lpos + 1] = temp[rpos - 1];
line[lpos + 2] = temp[rpos - 3];
line[lpos + 3] = temp[rpos];
}
I have the following code written to have IPP resize my matrix:
#include "ipp_mx.h"
#include "ipp.h"
#include "stdafx.h"
#define IPPCALL(name) name
int main()
{
IppiSize srcSize = { 3,3 };
float srcImage[9] =
{ 20, 40, 30,
35, 55, 70,
100, 30, 20 };
float* src = new float[srcSize.width*srcSize.height];
for (int i = 0; i < srcSize.width*srcSize.height; i++) {
src[i] = srcImage[i];
}
double xFactor = 10; double yFactor = 10;
int numChannels = 1;
int bytesPerPixel = 4;
int srcStep = srcSize.width*bytesPerPixel*numChannels;
IppiRect srcRoi = { 0, 0, srcSize.width, srcSize.width };
float* dest = new float[srcSize.width*srcSize.height*xFactor*yFactor];
IppiSize destSize = { srcSize.width*xFactor, srcSize.height*yFactor };
int destStep = destSize.width*bytesPerPixel*numChannels;
IppiRect destRoi = { 0, 0, destSize.width, destSize.width };
double xShift = 0; double yShift = 0;
int interpolation = 1; //nearest neighbour
int bufSize;
IPPCALL(ippiResizeGetBufSize)(srcRoi, destRoi, 1, interpolation, &bufSize);
unsigned char* buffer = new unsigned char[bufSize];
IPPCALL(ippiResizeSqrPixel_32f_C1R)(src, srcSize, srcStep, srcRoi, dest, destStep, destRoi, xFactor, yFactor, xShift, yShift, interpolation, buffer);
return 0;
}
Is there an IPP function I can use that now converts this float matrix dest to an RGB24 format, given a colour map?
I know I can do it by hand in a for loop, but the raw matrices I want to work with are much larger and for loops may not cut it.
The technique I found to work consists of 3 steps:
Convert/truncate the float value to unsigned char - in my case the input values are within the 8 bit range and I don't care about the decimal numbers.
Convert the unsigned char value to 3 channel RGB gray which essentially assigns the same input values to all 3 channels.
Construct a palette to map 3 channel values to another 3 channel values.
Pass the palette and the input value to a lookup table function.
This is demonstrated on the code below. Note that my palette was setup to assign green for values under 30 and blue for values greater or equals than 30.
unsigned char** GeneratePalette()
{
unsigned char red[256];
unsigned char green[256];
unsigned char blue[256];
for(int value = 0; value < 256; value++)
{
if(value < 30)
{
red[value] = 0;
green[value] = 255;
blue[value] = 0;
}
else
{
red[value] = 0;
green[value] = 0;
blue[value] = 255;
}
}
unsigned char* table[3] = { red, green, blue };
return table;
}
void Test()
{
unsigned char** palette = GeneratePalette();
IppiSize srcSize = { 2,1 };
float src[2] = { 54, 19 };
unsigned char truncated[2];
IPPCALL(ippiConvert_32f8u_C1R)(src, srcSize.width * sizeof(float), truncated, srcSize.width * sizeof(unsigned char), srcSize, ippRndZero);
unsigned char copied[6] = {0};
IPPCALL(ippiGrayToRGB_8u_C1C3R)(truncated, srcSize.width * sizeof(unsigned char), copied, srcSize.width * sizeof(unsigned char) * 3, srcSize);
unsigned char dest[6];
IPPCALL(ippiLUTPalette_8u_C3R)(copied, 6, dest, 6, srcSize, palette, 8);
}
int main()
{
Test();
return 0;
}
In the end, this was not very efficient and working on a single for loop was faster.
I'm trying to create a dynamic array of arrays (of arrays). But for some reason the data gets corrupted. I'm using the data to generate a texture in a OpenGL application.
The following code works fine:
unsigned char imageData[64][64][3];
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < 64; j++)
{
unsigned char r = 0, g = 0, b = 0;
if (i < 32)
{
if (j < 32)
r = 255;
else
b = 255;
}
else
{
if (j < 32)
g = 255;
}
imageData[i][j][0] = r;
imageData[i][j][1] = g;
imageData[i][j][2] = b;
}
std::cout << std::endl;
}
glTexImage2D(target, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
Problem is, I want to be able to create a texture of any size (not just 64*64). So I'm trying this:
unsigned char*** imageData = new unsigned char**[64]();
for (int i = 0; i < 64; i++)
{
imageData[i] = new unsigned char*[64]();
for (int j = 0; j < 64; j++)
{
imageData[i][j] = new unsigned char[3]();
unsigned char r = 0, g = 0, b = 0;
if (i < 32)
{
if (j < 32)
r = 255;
else
b = 255;
}
else
{
if (j < 32)
g = 255;
}
imageData[i][j][0] = r;
imageData[i][j][1] = g;
imageData[i][j][2] = b;
}
std::cout << std::endl;
}
glTexImage2D(target, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData);
But that doesn't work, the image gets all messed up so I assume I'm creating the array of arrays (of arrays) incorrectly? What am I doing wrong?
Also, I guess I should be using vectors instead. But how can I cast the vector of vectors of vectors data into a (void *) ?
This line contains multiple bugs:
unsigned char* pixel = &(imageData[(y * height) + x]);
You should multiply x by height and add y. And there's also the fact that each pixel is actually 3 bytes. Some issues that led to this bug in your code (and will lead to to others)
You should also be using std::vector. You can call std::vector::data to get a pointer to the underlying data to interface to C API's.
You should have a class that represents a pixel. This will handle the offsetting correctly and give things names and made the code clearer.
Whenever you are working with a multi dimensional array that you encode into a single dimensional one, you should try to carefully write an access function that takes care of indexing so you can test it separately.
(end bulleted list... oh SO).
struct Pixel {
unsigned char red;
unsigned char blue;
unsigned char green;
};
struct TwoDimPixelArray {
TwoDimArray(int width, int height)
: m_width(width), m_height(height)
{
m_vector.resize(m_width * m_height);
}
Pixel& get(int x, int y) {
return m_vector[x*height + y];
}
Pixel* data() { return m_vector.data(); }
private:
int m_width;
int m_height;
std::vector<Pixel> m_vector;
}
int width = 64;
int height = 64;
TwoDimPixelArray imageData(width, height);
for (int x = 0; x != width ; ++ x) {
for (int y = 0; y != height ; ++y) {
auto& pixel = imageData.get(x, y);
// ... pixel.red = something, pixel.blue = something, etc
}
}
glTexImage2D(target, 0, GL_RGB, 64, 64, 0, GL_RGB, GL_UNSIGNED_BYTE, imageData.data());
You need to use continuous memory for it to work with opengl.
My solution is inspired by previous answers, with a different indexing system
unsigned char* imageData = new unsigned char[width*height*3];
unsigned char r, g, b;
const unsigned int row_size_bytes = width * 3;
for( unsigned int x = 0; x < width; x++ ) {
unsigned int current_row_offset_bytes = x * 3;
for( unsigned int y = 0; y < height; y++ ) {
unsigned int one_dim_offset = y * row_size_bytes + current_row_offset_bytes
unsigned char* pixel = &(imageData[one_dim_offset]);
pixel[0] = r;
pixel[1] = g;
pixel[2] = b;
}
}
Unfortunnately it's untested, but i'm confident assuming sizeof(char) is 1.
I want to find a small bmp file from another bigger bmp file (the bigger one is captured from screen and called Sample.bmp , the small bmp file is called Button.bmp . Thing is the when comparing the images the file can't be found anywhere.
the compare code :
for (int i=0;i<SCREEN_WIDTH-width;++i)
{
for (int j=0;j<SCREEN_HEIGHT-height;++j)
{
boolean isequal = true;
for(int qqq=i;qqq<i+width;++qqq)
{
for (int kkk=j;kkk<j+height;++kkk)
{
if (PI[qqq][kkk]!=NPI[qqq-i][kkk-j]) isequal = false;
if (isequal == false)
{
qqq = i + width + 1;
kkk = j + height + 1;
}
}
}
if (isequal==true)
{
MidX = i;
MidY = j;
return;
}
}
}
note : Screen_width and Screen_height are for the bigger image and width and height are for the smaller one
Full Code:
void readBMP()
{
int i;
FILE* f = fopen("Sample.bmp", "rb");
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header
// extract image height and width from header
int width = *(int*)&info[18];
int height = *(int*)&info[22];
int size = 3 * width * height;
unsigned char* data = new unsigned char[size]; // allocate 3 bytes per pixel
fread(data, sizeof(unsigned char), size, f); // read the rest of the data at once
fclose(f);
for(int qq=0;qq<SCREEN_WIDTH;++qq)
for (int kk=0;kk<SCREEN_HEIGHT;++kk)
{
PI[qq][kk][0] = data[kk * width + qq];
PI[qq][kk][1] = data[kk * width + qq + 1];
PI[qq][kk][2] = data[kk * width + qq + 2];
}
}
void FindImageInScreen(char* FileName)
{
FILE* f = fopen(FileName, "rb");
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header
// extract image height and width from header
int width = *(int*)&info[18];
int height = *(int*)&info[22];
int size = 3 * width * height;
unsigned char* data = new unsigned char[size]; // allocate 3 bytes per pixel
fread(data, sizeof(unsigned char), size, f); // read the rest of the data at once
fclose(f);
for(int qq=0;qq<width;++qq)
for (int kk=0;kk<height;++kk)
{
NPI[qq][kk][0] = data[kk * width + qq];
NPI[qq][kk][1] = data[kk * width + qq + 1];
NPI[qq][kk][2] = data[kk * width + qq + 2];
}
for (int i=0;i<SCREEN_WIDTH-width;++i)
{
for (int j=0;j<SCREEN_HEIGHT-height;++j)
{
boolean isequal = true;
for(int qqq=i;qqq<i+width;++qqq)
{
for (int kkk=j;kkk<j+height;++kkk)
{
if (PI[qqq][kkk][0]!=NPI[qqq-i][kkk-j][0]) isequal = false;
if (isequal == false)
{
qqq = i + width + 1;
kkk = j + height + 1;
}
}
}
if (isequal==true)
{
MidX = i;
MidY = j;
return;
}
}
}
MidX = -1;
MidY = -1;
return;
}
definition of arrays (added because of request) , This is before functions execute :
PI = new unsigned int**[SCREEN_WIDTH];
for (int i=0;i<SCREEN_WIDTH;++i)
PI[i] = new unsigned int*[SCREEN_HEIGHT];
for (int i=0;i<SCREEN_WIDTH;++i)
for (int j=0;j<SCREEN_HEIGHT;++j)
PI[i][j] = new unsigned int[3];
NPI = new unsigned int**[SCREEN_WIDTH];
for (int i=0;i<SCREEN_WIDTH;++i)
NPI[i] = new unsigned int*[SCREEN_HEIGHT];
for (int i=0;i<SCREEN_WIDTH;++i)
for (int j=0;j<SCREEN_HEIGHT;++j)
NPI[i][j] = new unsigned int[3];
The First function executes then the second. and sorry for some bad programming because I did thousands of changes to make it work!
PI[qq][kk][0] = data[kk * width + qq];
From how PI and NPI are filled in, it appears that they are 3-dimensional arrays (it would help if you included their definition in the code sample). But
if (PI[qqq][kkk]!=NPI[qqq-i][kkk-j]) isequal = false;
which is only indexing 2 dimensions of each. PI[a][b] is the address of the array containing PI[a][b][0..2] and will certainly never match the address of NPI[x][y], so this statement is always returning false I expect.
Lets get you started. Here is a better LoadBMP.
Yours, among other thing, read the size, and uses SCREEN_HEIGHT anyway.
Using this for loading both images is probably easier.
#include <vector>
#include <cstdio>
#include <string>
using namespace std;
typedef unsigned char UC;
struct RGB { UC r,g,b; };
bool operator == ( const RGB& p1, const RGB& p2 ) { return p1.r==p2.r && p1.g==p2.g && p1.b==p2.b; }
struct BMP
{
int width;
int height;
vector<RGB> pixels;
RGB& Pix(int x,int y) { return pixels[ y*width + x ]; }
};
void LoadBMP( BMP& bmp, const char* filename )
{
FILE* f = fopen(filename, "rb");
UC info[54];
fread(info, 1, 54, f); // read the 54-byte header
// extract image height and width from header
bmp.width = *(int*) (info+18);
bmp.height = *(int*) (info+22);
// scanlines are always multiple of 4, padded with 0-3 bytes
int scanlinesize = 3*bmp.width;
while( scanlinesize % 4 ) ++scanlinesize;
int size = scanlinesize * bmp.height;
UC* data = new UC[size];
fread(data, 1, size, f);
fclose(f);
bmp.pixels.clear();
bmp.pixels.reserve(bmp.height*bmp.width);
for(int yy=0;yy<bmp.height;++yy)
{
UC* p = data+scanlinesize*yy;
for (int xx=0;xx<bmp.width;++xx)
{
RGB rgb;
rgb.b = *p++;
rgb.g = *p++;
rgb.r = *p++;
bmp.pixels.push_back(rgb);
}
}
delete[] data;
}
I want to convert a yuv picture into RGB to display on a QT pixmap. What I have right now is that I see a empty pixmap.
int convertYUVtoRGB(int y, int u, int v) {
int r,g,b;
r = y + (int)(1.402f*v);
g = y - (int)(0.344f*u +0.714f*v);
b = y + (int)(1.772f*u);
r = r>255? 255 : r<0 ? 0 : r;
g = g>255? 255 : g<0 ? 0 : g;
b = b>255? 255 : b<0 ? 0 : b;
return 0xff000000 | (b<<16) | (g<<8) | r;
}
unsigned char * convertYUV420_NV21toRGB8888(unsigned char data[78080], int width, int height) {
int size = width*height;
int offset = size;
unsigned char * pixels = new unsigned char[size];
int u, v, y1, y2, y3, y4;
// i percorre os Y and the final pixels
// k percorre os pixles U e V
for(int i=0, k=0; i < size; i+=2, k+=2) {
y1 = data[i ]&0xff;
y2 = data[i+1]&0xff;
y3 = data[width+i ]&0xff;
y4 = data[width+i+1]&0xff;
u = data[offset+k ]&0xff;
v = data[offset+k+1]&0xff;
u = u-128;
v = v-128;
pixels[i ] = convertYUVtoRGB(y1, u, v);
pixels[i+1] = convertYUVtoRGB(y2, u, v);
pixels[width+i ] = convertYUVtoRGB(y3, u, v);
pixels[width+i+1] = convertYUVtoRGB(y4, u, v);
if (i!=0 && (i+2)%width==0)
i+=width;
}
return pixels;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
unsigned char * buffer;
unsigned char * image = NULL;
QPixmap pixmap;
QImage img(320, 122, QImage::Format_ARGB32_Premultiplied);
img.fill(QColor(Qt::white).rgb());
ifstream is;
is.open ("bunny.yuv", ios::binary );
// is.seekg (0, ios::end);
// length = is.tellg();
// is.seekg (0, ios::beg);
buffer = new unsigned char[78081];
is.read((char * )buffer,78080);
is.close();
/*
for (int x = 0; x < 10; ++x) {
for (int y = 0; y < 10; ++y) {
img.setPixel(x, y, qRgb(0, 0, 0));
}
}
*/
for(int i = 0; i < 78080; i++)
qDebug() << buffer[i]<< endl;
image = convertYUV420_NV21toRGB8888(buffer,320,122);
QByteArray byteImage((const char *)image);
pixmap.loadFromData(byteImage);
QLabel myLabel;
myLabel.setPixmap(pixmap);
myLabel.setGeometry(20,100,320,122);
myLabel.show();
return a.exec();
}
EDIT: I've added the right format and parenthesses. Still the same problem.
Kind regards,
And when you have done the calculation in Jason's post - the best format for the pixmap is QImage::Format_ARGB32_Premultiplied - the format is Blue byte Green byte Red byte 0xff
This won't do what you think it does:
r = y + (int)1.402f*v;
g = y - (int)(0.344f*u +0.714f*v);
b = y + (int)1.772f*u;
As you've missed parentheses and so cast your float constants to ints before the calculation.
And then having converted your YUV data into RGB packed into an int, you store that int into a char...
So:
unsigned char * pixels = new unsigned char[size];
Should probably be:
unsigned int* pixels = new unsigned int[size];
And obviously that affects the return type of the function too. You might also want to change the type of your YUV -> RGB function to unsigned as well, just for consistency.
In convertYUV420_NV21toRGB8888, pixels is an unsigned char array but you're trying to assign a int to it. All you will get is the low byte, and most of the bytes in your output will remain unset. You need to completely rethink the way you're writing the output.