How to implement the conversion from Image to texture?

Hi Experts,

SketchUp allows to import an image into its application. For me, I want to convert sketchUp image into the texture in my application. So my question is: How to implement the conversion from image to texture in my application?

My thoughts are:

  1. create a face with physical width and height of image
  2. apply the transform into the newly created face
  3. tessellate the face into mesh by sketchUp SDK
  4. then whether or not there is a way to build the relationship between image and mesh so that we can get uv texture of image attached on the newly face?

Appreciated for your help.

Thanks
Phenix

Hi, it is not clear what you want to achieve (not how you want to proceed, but what the result should be). SketchUp allows to import image files either as textured material (“texture”) or as image entity (which is a component containing 4 edges and a textured face).

  • Could you instead directly import it as texture?
  • Do you want to turn an existing image entity into a textured rectangle (4 edges, 1 face with texture)?
  • Do you want to export an image file from the image entity to transfer it into your application?
1 Like

+1

When you say Image to Texture I’m a bit unclear what the intent is. Texture is SketchUp is an object associated with a material - materials are applied to entities.

Do you want the Image as a material in the model?
Or do you want the equivalent of exploding an Image using the UI?

Maybe some screenshots would help.

@Aerilius, @tt_su

For me, it is sketchup file with only image entities. In my application, it doesn’t have image concept, but has texture. So I want to read image entities from sketchup file and then try to convert image entities in my application in the form of texture.

@Aerilius @tt_su

Hi Experts,

I pasted my test codes to implement the conversion from sketchUp Image to the texture in my application.

bool SketchUpPart::LoadImageMaterial(SUEntitiesRef entities)
{
    size_t num_images = 0;
    if(SU_ERROR_NONE != SUEntitiesGetNumImages(entities, &num_images))
        return false;

    if (num_images == 0)
        return false;

    std::vector<SUImageRef> images(num_images);
    if (SU_ERROR_NONE != SUEntitiesGetImages(entities, num_images, &images[0], &num_images))
        return false;

    SUTextureWriterRef texture_writer = SU_INVALID;
    SUTextureWriterCreate(&texture_writer);
    if(SUIsInvalid(texture_writer))
        return false;

    for (size_t i = 0; i < num_images; i++) 
    {
        SUImageRef image = images[i];
        if (SUIsInvalid(image))
            continue;

        double width, height;
        if(SU_ERROR_NONE != SUImageGetDimensions(image, &width, &height))
            continue;
			
		Position posBL(0, 0, 0);
        Position posBR(width, 0, 0);
        Position posTR(width, height, 0);
        Position posTL(0, height, 0);

        SULoopInputRef outer_loop = SU_INVALID;
        SULoopInputCreate(&outer_loop);

        for (size_t i = 0; i < 4; ++i) {
            SULoopInputAddVertexIndex(outer_loop, i);
        }

        SUTransformation transform;
        SUImageGetTransform(image, &transform);
        Matrix3d imageMatrix;
        SketchUpUtil::SUMatrixToATFMatrix(transform, imageMatrix);

        const Transf* atfTrans = imageMatrix.GetTransf();
        Position translation = atfTrans->Translation().Pos();
        Vector vectorTranslation(translation.X(), translation.Y(), translation.Z());
        Matrix affineMatrix = atfTrans->Affine();
        posBL = /*affineMatrix**/(posBL + vectorTranslation);
        posBR = /*affineMatrix**/(posBR + vectorTranslation);
        posTR = /*affineMatrix**/(posTR + vectorTranslation);
        posTL = /*affineMatrix**/(posTL + vectorTranslation);

        // Create the face
        SUFaceRef face = SU_INVALID;
        SUPoint3D vertices[4] = {   { posBL.X(), posBL.Y(), posBL.Z()},
                                    { posBR.X(), posBR.Y(), posBR.Z()},
                                    { posTR.X(), posTR.Y(), posTR.Z()},
                                    { posTL.X(), posTL.Y(), posTL.Z()} 
                                };
        SUFaceCreate(&face, vertices, &outer_loop);

        // Add the face to the entities
        SUEntitiesAddFaces(entities, 1, &face);

        // Create a material from a texture from a file
        SUMaterialRef material = SU_INVALID;
        SUMaterialCreate(&material);

        SUTextureRef texture = SU_INVALID;
        //SUTextureCreateFromFile(&texture, "c:\\c.png", 1.0, 1.0);
        size_t pixelWidth(0), pixelHeight(0); 
        SUImageGetPixelDimensions(image, &pixelWidth, &pixelHeight);
        size_t bits_per_pixel(0);
        size_t data_size;
        SUImageGetDataSize(image, &data_size, &bits_per_pixel);

        SUByte* pixel_data = new SUByte[data_size];;
        SUImageGetData(image, data_size, pixel_data);
        SUTextureCreateFromImageData(&texture, pixelWidth, pixelHeight, bits_per_pixel, pixel_data);
        SUMaterialSetTexture(material, texture);
        delete []pixel_data;

        // Add the material to the face
        SUFaceSetFrontMaterial(face, material);
        SketchUpPolygonMesh* pMesh = SketchUpUtil::CreateMesh(face);
		//....
		//Other codes to load polygonmesh
    }
    return false;
}  

I met an issue. The image can be imported into my application in the form of texture. However, when I assign the new texture into the new face, i found i have no chance to know the s_scale/t_scale. It turns out that original image object in sketchup application like that:

But after using my conversion, it looks like that in my application:

When trying to convert the texture into face, how to get the s_scale/t_scale.

Thanks
Phenix

Wait - you are exporting from SKP, right? So why are you creating geometry in the SKP file?
Can’t you use the transformation for the Image entity and use that to recreate the “texture” in your target application’s format?
An Image always has the material stretched to fit it’s rectangular shape.

(Btw, can you edit your post and select all your code and mark it up as Pre-formatted text - otherwise we loose stuff in the formatting. )

Yes, I am exporting from SKP to my file format. In my file format, it doesn’t know what the Image is. I hope SketchUp Image object can be exported into texture in my file format. However, the newly created texture must be assigned to the certain face. So that’s why I am creating geometry in the SKP file.

“An Image always has the material stretched to fit it’s rectangular shape.” You are saying the SketchUp application’s behavior, right? You know, I don’t get any geometry information from toolkit if it is only SUImageRef object in SketchUp file.

I am using the function SUTextureCreateFromImageData( ) to recreate the “texture”; the texture is set into the newly created material, then the material will be assigned onto the certain geometry. If so, I can directly translate the newly created face with new material into my application.

However, when I tried to read STQ data from SKetchUp toolkit for the new face with the new material, I found that the STQ value of each vertex texture are the same as PolygonMesh Vertex value. I think the STQ value are wrong. So how to get STQ value correctly for the new face assigned by new material?

Thanks
Phenix

No, I only has sketchup file with image entities and want to export the image entities.

In my model, image files is as image entity. You mentioned it is a component 4 edges and a textured face. In fact I can’t get a textured face, and I only get a SUImageRef object. Do you know which function is to get a textured face from toolkit?

Yes, I want to export an image file from the image entity to transfer it into my application.

A SketchUp image has a component definition (although it is not a component instance, and the image’s definition is not visible in the UI component browser).
But I don’t see that the SDK exposes a way to get a definition from a SUImageRef (like the Ruby API has, Sketchup::Image#definition). Theoretically you could also iterate over all definitions ([SUModelGetComponentDefinitions][1]) and check the type of their instances, whether they are images, maybe @tt_su can say more.

(And in the Ruby API, from where stems Sketchup::Image#definition, I can’t find it documented, is it an official method?)
[1]: Homepage | SketchUp Developer

The C API hides the group and image definitions - unlike the Ruby API.

No - that is not an official method. The API has some typos here and there - but all official methods and classes are documented. If you cannot find it in the docs then it’s been added by something else.

I still don’t understand why you need your exporter to create geometry - this is very unusual.
So I understand you try to translate Image entities into Textures in your target applications. But why do you need the intermediate step of converting the Image entity into a face with material?

@tt_su

In fact it is decided by my conversion pattern. In my conversion pattern, there are three parts: producer, processor and consumer. SketchUp is a producer to produce SketchUp model/attribute etc. related data into the certain intermediate data defined by processor, my application is a consumer which only knows the certain intermediate data and don’t know the data type from the producer. In my processor, there is no image related definition. So i have to try to convert the image into a face with material. My processor has defined the material which has assigned to the certain polygonmesh.

Could you please tell me about how to assign the new material to the new face correctly by API?

Thanks
Phenix

I don’t understand why the transformation for the image entity can recreate the “texture”? Do you mean the transformation for the image entity can create a rectangular shape; and the texture created by an image data can be matched/stretched to the newly created rectangular?

Appreciated for your help.

Thanks
Phenix

Sorry for the late response - I was away on vacation last week.

The transformation will give you the position of the Image entity. Given that you can create a face in the same position. You would then need to export the Image’s texture and add that as a normal material to the model and apply that to the face. Image entities always have the texture stretched across the face, so the UVs would always be for each four vertices:

  • [0.0, 0.0]
  • [1.0, 0.0]
  • [1.0, 1.0]
  • [0.0, 1.0]

@tt_su, Thanks for your suggestions and sorry for late response. Now the image can be imported successfully. Considering the UVs would always be for each vertices:(0,0); (1,0), (1, 1),(0,1). Now i can directly construct an polygonmesh object plus uv texture value to convert image into polymesh with texture.

Again, thanks a lot for lots of support.

Thanks
Phenix

1 Like