Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with .vtf file modification. #458

Closed
Mine228 opened this issue Jul 3, 2018 · 6 comments
Closed

Problem with .vtf file modification. #458

Mine228 opened this issue Jul 3, 2018 · 6 comments

Comments

@Mine228
Copy link

Mine228 commented Jul 3, 2018

So I've been trying to modify the contents of a .vtf file and then save it as a new file. I have this:

unsigned char * pSrcImage = pTex->ImageData( iFrame, iCubeFace, iMipLevel, 0, 0, z );

float * ImgArray = (float *)pSrcImage;

for (int i = 0; i < iWidth*iHeight * 3; i+=3)
{
	ImgArray[i] = 0.0f;
	ImgArray[i+1] = 1.0f;
	ImgArray[i+2] = 0.0f;
}

*pSrcImage = * (unsigned char *)ImgArray;

CUtlBuffer finBuf;
pTex->Serialize(finBuf);

FILE * fin;
fin = fopen("output.vtf", "w+b");

fwrite(finBuf.Base(), 1, srcVTFLength, fin);
fclose(fin);

This is meant to change the color of a particular bitmap to a green color.
It successfully creates a working vtf file but it doesn't seem to modify its contents. It says that ImageData() returns a pointer to the bitmap data of the vtf interface for the selected face,frame, etc. So I'm considering that this pointer should be replacing the data of the vtf that I'm modifying unless it makes a copy of the data and returns the pointer to the copied data. If anyone has any info on this it would be much appreciated.

@PatrickSHYee
Copy link

PatrickSHYee commented Jul 4, 2018 via email

@PatrickSHYee
Copy link

PatrickSHYee commented Jul 4, 2018 via email

@PatrickSHYee
Copy link

PatrickSHYee commented Jul 4, 2018 via email

@Mine228
Copy link
Author

Mine228 commented Jul 4, 2018

Oh so I found that the last bit of casting was unnecessary and I could just modify the value in the ImgArray and it would modify the vtf output. To answer your last question, pSrcImage is a pointer that points to whatever pTex->ImageData( iFrame, iCubeFace, iMipLevel, 0, 0, z ); returns.

FILE *vtfFp = fopen( pActualVTFFileName, "rb" );
	if( !vtfFp )
	{
		Error( "Can't open %s\n", pActualVTFFileName );
		exit( -1 );
	}

	fseek( vtfFp, 0, SEEK_END );
	int srcVTFLength = ftell( vtfFp );
	fseek( vtfFp, 0, SEEK_SET );

	CUtlBuffer buf;
	buf.EnsureCapacity( srcVTFLength );
	int nBytesRead = fread( buf.Base(), 1, srcVTFLength, vtfFp );
	fclose( vtfFp );
	buf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead );

	IVTFTexture *pTex = CreateVTFTexture();
	if (!pTex->Unserialize( buf ))
	{
		Error( "*** Error reading in .VTF file %s\n", pActualVTFFileName );
		exit(-1);
	}

@Mine228
Copy link
Author

Mine228 commented Jul 4, 2018

Ok, so the last bit of the problem is that if I output the array into a .pfm file using

PFMWrite(ImgArray, pTempNameBuf, iWidth, iHeight);
static void PFMWrite( float *pFloatImage, const char *pFilename, int width, int height )
{
	FILE *fp;
	fp = fopen( pFilename, "wb" );
	fprintf( fp, "PF\n%d %d\n-1.000000\n", width, height );
	int i;
	for( i = height-1; i >= 0; i-- )
	{
		float *pRow = &pFloatImage[3 * width * i];
		fwrite( pRow, width * sizeof( float ) * 3, 1, fp );
	}
	fclose( fp );
}

it outputs a correctly working .pfm file with the whole image being colored either red, green or blue based on the "for" loop, but the .vtf seems to be addressed differently: https://imgur.com/RDh2RUf

the first image being

for (int i = 0; i < iWidth*iHeight * 3; i+=3)
{
	ImgArray[i] = 1.0f;
	ImgArray[i+1] = 0.0f;
	ImgArray[i+2] = 0.0f;
}

the second

for (int i = 0; i < iWidth*iHeight * 3; i+=3)
{
	ImgArray[i] = 0.0f;
	ImgArray[i+1] = 1.0f;
	ImgArray[i+2] = 0.0f;
}

and the third

for (int i = 0; i < iWidth*iHeight * 3; i+=3)
{
	ImgArray[i] = 0.0f;
	ImgArray[i+1] = 0.0f;
	ImgArray[i+2] = 1.0f;
}

I'm not sure how to solve this, and the strange thing is that it only colors the green channel and not the red or blue one.

@Mine228
Copy link
Author

Mine228 commented Jul 5, 2018

Ok, so I figured it out. The image needs to be converted into an IMAGE_FORMAT_RGB323232F using
ImageLoader::ConvertImageFormat(), later you can modify its content like a normal rgb stream of data after converting to float (range 0.0-1.0), then if you want to output it into a .vtf file you need to convert the image to something other than 32bpp like for example in my case
IMAGE_FORMAT_RGBA16161616F, and it works perfectly.

@Mine228 Mine228 closed this as completed Jul 6, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants