Get a SUImageRef and write the texture with SUTextureWriteToFile

I’m trying to write the texture file coming from an Image. (SUImageRef)
It’s a little weird there is a transformation on outputed result (here enclosed)
Something seems shifted or scaled in resulting image and I don’t konw why.
Our export with previous sdk was using texture helper and was ok.
Just a remark : in original skp, there is no transformation like this one on the applied texture

Here is the code that build the texture from the image. something is probably missing.

Thanks in advance for any idea.

Philippe

void CXmlExporter::WriteImage(SUImageRef image)` {
	
	if (SUIsInvalid(image))
	return;

double width;
double height;
SUImageGetDimensions(image, &width, &height);

size_t pixel_width;
size_t pixel_height;
SUImageGetPixelDimensions(image, &pixel_width, &pixel_height);

size_t data_size_in_byte;
size_t bits_per_pixel;
SUImageGetDataSize(image, &data_size_in_byte, &bits_per_pixel);
std::vector<SUByte> pixel_data(data_size_in_byte);

CSUString file_name;
SUImageGetFileName(image, file_name);
SUImageGetData(image, data_size_in_byte, &pixel_data[0]);

SUTextureRef texture = SU_INVALID;
SUResult answer = SUTextureCreateFromImageData(&texture, pixel_width, pixel_height, bits_per_pixel, &pixel_data[0]);
if (answer != SU_ERROR_NONE)
	return;

SUTextureWriteToFile(texture, output_texture_file_path.c_str());

}

skp file from 3D warehouse “B214TD”
B214TD.skp (129.8 KB)

SDK 2015 : Image texture written :

Previous SDK : image written with texture helper

I must admit I’m still struggling with image writing.

Two other remarks :

1°) Image data size seems “strange”
image size is 577 x 399 pixels which is 690 669 px
SUImageGetDataSize returns 691 068 which is exactly (690 669 - 577)
So the difference is one line width (577 px).
There is some byte shift during pixel reading and I don’t understand why in my code.

I read some code about stride but I’m not sure it applies here.

2°) SUTextureWriterWriteAllTextures output correctly the image but code is hidden inside slapi.
There is for sure a difference between our code (SUTextureWriterWriteAllTextures versus WriteImage(SUImageRef image above) but I don’t know where.
So I will use this workaround until I get the solution.

Thanks for any idea.

Hi,
You might want to check out this thread. There is a padding for each row of bytes, which is not exposed by the API. That’s what’s causing this apparent “skew”.

Hi Bugra,

I’ve read the thread you noticed in your answer and thank for that.
You’re totally right it skew the resulting image.
But I don’t know how to deal with this padding.

First of all, for me, a padding is normaly all around the image (css).

In SU API context I only have one line. 577 pixels. The padding is not all around ?

So, I’ve tried to increase the height with just one row (which is the exact difference between SUImageGetDataSize and formula w * h * bpp)

SUTextureCreateFromImageData(&texture, pixel_width, pixel_height+1, bits_per_pixel, &pixel_data[0]);

No success

Is there a way actually to output correctly images with SUTextureCreateFromImageData ?

Many thanks for your previous answers

Hi Phillippe,
The padding here is at the end of each row. We forgot to expose the “bytes per row” value but it is easy to calculate:

The image has 399 rows and 577 columns of pixels. The data size is 691068 bytes so it is:
691068 / 399 = 1732 bytes per row.

SUImageGetDataSize tells you that there are 24 bits per pixel, i.e. 3 bytes per pixel. So you would have expected:
577 * 3 = 1731 bytes per row. So, clearly there is 1 byte of padding at the end of each row. You need to discard that byte since it is not actual image data.

I hope that helps.

2 Likes

Does it means we need to copy and filter the vector pixel_data retrieved by SUImageGetData ?

std::vector<SUByte> pixel_data(data_size_in_byte);
SUImageGetData(image, data_size_in_byte, &pixel_data[0]);

std::vector<SUByte> pixel_filtered(data_size_in_byte2);
{
// filter code copy <pixel_data> in  <pixel_filtered> except last byte 
//  to be done
}

Depends on how you are using this data. If you use an image handling library, it should let you specify bytes per row.

Just to be clear, we are aware of this shortcoming in the API. We should return a bytes per row value, or a padding value. And let you enter these in SUTextureCreateFromImageData. We had a regression in behavior from the old API when we changed our internal image handling library.

2 Likes

Because I’m not using an external image library, I actually simply use SUTextureCreateFromImageData, I will filter extra byte padding data as you proposed.

Thanks for your analysis time and advice.

1 Like

Note that this is a regression that happened in SU2014.