Skip to content

Commit

Permalink
pix_sig2pix~/pix2sig~: swap channels if necessary
Browse files Browse the repository at this point in the history
where the data layout is GL_UNSIGNED_INT_8_8_8_8 (mostly on Apple...)

Closes: #370
  • Loading branch information
IOhannes m zmölnig authored and IOhannes m zmölnig committed Jul 27, 2023
1 parent d7abdc4 commit c8bc5b5
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 25 deletions.
41 changes: 30 additions & 11 deletions src/Pixes/pix_pix2sig~.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,23 +117,38 @@ void pix_pix2sig :: filltypeMess(t_symbol*s, int argc, t_atom*argv) {
// signal Performance
namespace {
template<typename T>
void perform_pix2sig(t_sample**out, size_t N, void*data_, size_t dataoffset, unsigned int format, t_sample scale) {
void perform_pix2sig(t_sample**out, size_t N, void*data_, size_t dataoffset, unsigned int format, t_sample scale, bool swap) {
T*data = static_cast<T*>(data_);
t_sample*out_red = out[0];
t_sample*out_green = out[1];
t_sample*out_blue = out[2];
t_sample*out_alpha = out[3];
size_t n = N;

const int R = (swap)?3:0;
const int G = (swap)?2:1;
const int B = (swap)?1:2;
const int A = (swap)?0:3;

switch(format) {
case GEM_RGBA:
default:
case GEM_RAW_RGBA:
data += dataoffset*4;
while(n--) {
*(out_red ++) = scale * static_cast<t_sample>(data[chRed]);
*(out_green++) = scale * static_cast<t_sample>(data[chGreen]);
*(out_blue ++) = scale * static_cast<t_sample>(data[chBlue]);
*(out_alpha++) = scale * static_cast<t_sample>(data[chAlpha]);
*(out_red ++) = scale * static_cast<t_sample>(data[R]);
*(out_green++) = scale * static_cast<t_sample>(data[G]);
*(out_blue ++) = scale * static_cast<t_sample>(data[B]);
*(out_alpha++) = scale * static_cast<t_sample>(data[A]);
data+=4;
}
break;
case GEM_RAW_BGRA:
data += dataoffset*4;
while(n--) {
*(out_red ++) = scale * static_cast<t_sample>(data[B]);
*(out_green++) = scale * static_cast<t_sample>(data[G]);
*(out_blue ++) = scale * static_cast<t_sample>(data[R]);
*(out_alpha++) = scale * static_cast<t_sample>(data[A]);
data+=4;
}
break;
Expand Down Expand Up @@ -188,9 +203,10 @@ void pix_pix2sig :: perform(t_sample**out, size_t N)
};

/* metadata for the actual converters */
typedef void (*performer_t)(t_sample**out, size_t N, void*data, size_t offset, unsigned int format, t_sample scale);
typedef void (*performer_t)(t_sample**out, size_t N, void*data, size_t offset, unsigned int format, t_sample scale, bool swap);
performer_t p2s_perform;
t_sample scale = 1.;
bool swap = false;

size_t processed = 0; /* number of converted pixels */
int line; /* linenumber in waterfall mode */
Expand All @@ -207,6 +223,9 @@ void pix_pix2sig :: perform(t_sample**out, size_t N)
line = height + line;

switch(m_image.type) {
case GL_UNSIGNED_INT_8_8_8_8:
swap = true;
/* fallthrough */
default:
p2s_perform = perform_pix2sig<unsigned char>;
scale = 1./255.;
Expand Down Expand Up @@ -236,7 +255,7 @@ void pix_pix2sig :: perform(t_sample**out, size_t N)
m_offsetY %= height;
size_t r = m_image.upsidedown?m_offsetY:(height-m_offsetY);
if ((m_offsetX + count) > width) count = (width - m_offsetX);
p2s_perform(outsignal, count, data, r*width+m_offsetX, m_image.format, scale);
p2s_perform(outsignal, count, data, r*width+m_offsetX, m_image.format, scale, swap);
processed += count;
m_offsetX = 0;
m_offsetY = (m_offsetY+1)%height;
Expand All @@ -247,7 +266,7 @@ void pix_pix2sig :: perform(t_sample**out, size_t N)
if(!m_image.upsidedown) r = height-r-1;
size_t count = N-processed;
if (count>width) count = width;
p2s_perform(outsignal, count, data, r*width, m_image.format, scale);
p2s_perform(outsignal, count, data, r*width, m_image.format, scale, swap);
processed += count;
m_offsetY = (m_offsetY+1)%height;
}
Expand All @@ -257,7 +276,7 @@ void pix_pix2sig :: perform(t_sample**out, size_t N)
if(!m_image.upsidedown) r = height-r-1;
size_t count = N-processed;
if (count>width) count = width;
p2s_perform(outsignal, count, data, r*width+m_offsetX, m_image.format, scale);
p2s_perform(outsignal, count, data, r*width+m_offsetX, m_image.format, scale, swap);
processed += count;
m_offsetX = (count % width);
m_offsetY += !m_offsetX;
Expand All @@ -275,7 +294,7 @@ void pix_pix2sig :: perform(t_sample**out, size_t N)
size_t r = m_offsetY;
if (!m_image.upsidedown) r = height-r-1;
if ((m_offsetX + count) > width) count = (width - m_offsetX);
p2s_perform(outsignal, count, data, r*width+m_offsetX, m_image.format, scale);
p2s_perform(outsignal, count, data, r*width+m_offsetX, m_image.format, scale, swap);
processed += count;
m_offsetX = 0;
m_offsetY = (m_offsetY+1)%height;
Expand Down
47 changes: 33 additions & 14 deletions src/Pixes/pix_sig2pix~.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,13 @@ void pix_sig2pix :: dimenMess(int width, int height)
}

m_pixBlock.image.xsize =(GLint) width;
m_pixBlock.image.ysize = (GLint) height;
m_pixBlock.image.ysize =(GLint) height;
m_pixBlock.image.setCsizeByFormat(m_reqFormat);
if(m_reqType)
if(m_reqType) {
if(GEM_RGBA == m_reqFormat)
m_pixBlock.image.setCsizeByFormat(GL_RGBA);
m_pixBlock.image.type = m_reqType;
}

m_pixBlock.image.reallocate();
m_pixBlock.image.setBlack();
Expand All @@ -93,9 +96,7 @@ void pix_sig2pix :: csMess(std::string s)
return;
}
m_reqFormat=cs;
m_pixBlock.image.setCsizeByFormat(m_reqFormat);
m_pixBlock.image.reallocate();
m_pixBlock.image.setBlack();
dimenMess(m_pixBlock.image.xsize, m_pixBlock.image.ysize);
}


Expand Down Expand Up @@ -131,21 +132,35 @@ void pix_sig2pix :: startRendering()

namespace {
template<typename T>
void perform_sig2pix(t_sample**in, void*data_, unsigned int format, size_t n, t_sample scale) {
void perform_sig2pix(t_sample**in, void*data_, unsigned int format, size_t n, t_sample scale, bool swap) {
T*data = static_cast<T*>(data_);
t_sample*in_red = in[0];
t_sample*in_green = in[1];
t_sample*in_blue = in[2];
t_sample*in_alpha = in[3];

const int R = (swap)?3:0;
const int G = (swap)?2:1;
const int B = (swap)?1:2;
const int A = (swap)?0:3;

switch(format) {
case GL_RGBA:
default:
case GEM_RAW_RGBA:
while(n--) {
data[R] = static_cast<T> (scale*(*in_red++));
data[G] = static_cast<T> (scale*(*in_green++));
data[B] = static_cast<T> (scale*(*in_blue++));
data[A] = static_cast<T> (scale*(*in_alpha++));
data+=4;
}
break;
case GEM_RAW_BGRA:
while(n--) {
data[chRed] = static_cast<T> (scale*(*in_red++));
data[chGreen] = static_cast<T> (scale*(*in_green++));
data[chBlue] = static_cast<T> (scale*(*in_blue++));
data[chAlpha] = static_cast<T> (scale*(*in_alpha++));
data[B] = static_cast<T> (scale*(*in_red++));
data[G] = static_cast<T> (scale*(*in_green++));
data[R] = static_cast<T> (scale*(*in_blue++));
data[A] = static_cast<T> (scale*(*in_alpha++));
data+=4;
}
break;
Expand Down Expand Up @@ -181,7 +196,11 @@ void pix_sig2pix :: perform(t_sample**signals, size_t n)
const int format = m_pixBlock.image.format;
size_t pixsize = width * height;
size_t chansize = 0;
bool swap = false;
switch(type) {
case GL_UNSIGNED_INT_8_8_8_8:
swap = true;
/* fallthrough */
default:
chansize=sizeof(unsigned char);
break;
Expand Down Expand Up @@ -242,13 +261,13 @@ void pix_sig2pix :: perform(t_sample**signals, size_t n)

switch(type) {
default:
perform_sig2pix<unsigned char>(signals, data + offset * chansize, format, count, 255.0);
perform_sig2pix<unsigned char>(signals, data + offset * chansize, format, count, 255.0, swap);
break;
case GL_FLOAT:
perform_sig2pix<GLfloat>(signals, data + offset * chansize, format, count, 1.0);
perform_sig2pix<GLfloat>(signals, data + offset * chansize, format, count, 1.0, swap);
break;
case GL_DOUBLE:
perform_sig2pix<GLdouble>(signals, data + offset * chansize, format, count, 1.0);
perform_sig2pix<GLdouble>(signals, data + offset * chansize, format, count, 1.0, swap);
break;
}
m_pixBlock.newimage = 1;
Expand Down

0 comments on commit c8bc5b5

Please sign in to comment.