Example #1
0
int main(int  argc, char* argv[])
{

    int r, g, b;
    cmsUInt8Number RGB[3], RGB_OUT[3];
    cmsHTRANSFORM xform;
    cmsHPROFILE hProfile;
    double err, SumX=0, SumX2=0, Peak = 0, n = 0;


    if (argc != 2) {
        printf("roundtrip <RGB icc profile>\n");
        return 1;
    }

    hProfile = cmsOpenProfileFromFile(argv[1], "r");
    xform = cmsCreateTransform(hProfile,TYPE_RGB_8, hProfile, TYPE_RGB_8, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE);

    for (r=0; r< 256; r++) {
        printf("%d  \r", r);
        for (g=0; g < 256; g++) {
            for (b=0; b < 256; b++) {

                RGB[0] = r;
                RGB[1] = g;
                RGB[2] = b;

                cmsDoTransform(xform, RGB, RGB_OUT, 1);

                err = VecDist(RGB, RGB_OUT);

                SumX  += err;
                SumX2 += err * err;
                n += 1.0;
                if (err > Peak)
                    Peak = err;

            }
        }
    }

    printf("Average %g\n", SumX / n);
    printf("Max %g\n", Peak);
    printf("Std  %g\n", sqrt((n*SumX2 - SumX * SumX) / (n*(n-1))));
    cmsCloseProfile(hProfile);
    cmsDeleteTransform(xform);

    return 0;
}
Example #2
0
void QM_Subdivide( QM_Model *m, float maxShooterQuadEdgeLength, float maxGathererQuadEdgeLength )
	// Subdivide the original quads in the model to smaller
	// shooter quads and even-smaller gatherer quads.
	// Each shooter quad cannot have edge longer than maxShooterQuadEdgeLength, and
	// each gatherer quad cannot have edge longer than maxGathererQuadEdgeLength.
{
	if ( m == NULL || m->numSurfaces <= 0 ) return;

// Subdivide original quads to get shooter quads.

	int modelTotalShooters = 0;		// This will contain the total number of shooter quads in model.

	for ( int s = 0; s < m->numSurfaces; s++ )
	{
		QM_Surface *surface = &(m->surfaces[s]);

		// Find longest edge length of all original quads in the current surface.
		float maxEdgeLen = 0.0f;
		for ( int q = 0; q < surface->numOrigQuads; q++ )
		{
			QM_OrigQuad *origQuad = &(surface->origQuads[q]);
			float edgeLen;
			edgeLen = VecDist( origQuad->v[0], origQuad->v[1] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( origQuad->v[1], origQuad->v[2] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( origQuad->v[2], origQuad->v[3] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( origQuad->v[3], origQuad->v[0] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
		}

		// Compute how many regular segments to divide the longest edge into so that 
		// every resulting segment is not longer than maxShooterQuadEdgeLength.
		int numSegments = (int) ceil( maxEdgeLen / maxShooterQuadEdgeLength );

		// Each original quad on the current surface is going to be subdivided into
		// (numSegments*numSegments) shooter quads.
		// Therefore, the total number of shooter quads for this surface is...
		surface->numShooterQuads = surface->numOrigQuads * numSegments * numSegments;

		surface->shooters = (QM_ShooterQuad *) CheckedMalloc( sizeof(QM_ShooterQuad) * surface->numShooterQuads );
		int surfShootersCount = 0;  // This will contain the number of shooters in this surface.

		for ( int q = 0; q < surface->numOrigQuads; q++ )
		{
			QM_OrigQuad *origQuad = &(surface->origQuads[q]);

			for ( int y = 0; y < numSegments; y++ )
				for ( int x = 0; x < numSegments; x++ )
				{
					float newv[4][3];
					QuadBilinearInterpolate( newv[0], (float) x / numSegments, (float) y / numSegments, origQuad->v );
					QuadBilinearInterpolate( newv[1], (float) (x+1) / numSegments, (float) y / numSegments, origQuad->v );
					QuadBilinearInterpolate( newv[2], (float) (x+1) / numSegments, (float) (y+1) / numSegments, origQuad->v );
					QuadBilinearInterpolate( newv[3], (float) x / numSegments, (float) (y+1) / numSegments, origQuad->v );

					QM_ShooterQuad *shooterQuad = &(surface->shooters[ surfShootersCount ]);
					for ( int i = 0; i < 4; i++ ) CopyArray3( shooterQuad->v[i], newv[i] );
					QuadCentroid( shooterQuad->centroid, shooterQuad->v );
					CopyArray3( shooterQuad->normal, origQuad->normal );
					shooterQuad->area = QuadArea( shooterQuad->v );

					// Initialize the unshot power of the shooter quad.
					shooterQuad->unshotPower[0] = surface->emission[0] * shooterQuad->area;
					shooterQuad->unshotPower[1] = surface->emission[1] * shooterQuad->area;
					shooterQuad->unshotPower[2] = surface->emission[2] * shooterQuad->area;

					shooterQuad->surface = surface;
					surfShootersCount++;
					modelTotalShooters++;
				}
		}
	}


	// Build an array of pointers to all the shooters in the model.
	m->totalShooters = modelTotalShooters;
	m->shooters = (QM_ShooterQuad **) CheckedMalloc( sizeof(QM_ShooterQuad *) * modelTotalShooters );
	int modelTotalShootersCount = 0;

	for ( int s = 0; s < m->numSurfaces; s++ )
		for ( int q = 0; q < m->surfaces[s].numShooterQuads; q++ )
		{
			m->shooters[ modelTotalShootersCount ] = &(m->surfaces[s].shooters[q]);
			modelTotalShootersCount++;
		}



// Subdivide shooter quads to get gatherer quads.

	int modelTotalGatherers = 0;		// This will contain the total number of gatherers quads in model.

	for ( int s = 0; s < m->numSurfaces; s++ )
	{
		QM_Surface *surface = &(m->surfaces[s]);

		// Find longest edge length of all shooter quads in the current surface.
		float maxEdgeLen = 0.0f;
		for ( int q = 0; q < surface->numShooterQuads; q++ )
		{
			QM_ShooterQuad *shooterQuad = &(surface->shooters[q]);
			float edgeLen;
			edgeLen = VecDist( shooterQuad->v[0], shooterQuad->v[1] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( shooterQuad->v[1], shooterQuad->v[2] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( shooterQuad->v[2], shooterQuad->v[3] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
			edgeLen = VecDist( shooterQuad->v[3], shooterQuad->v[0] );
			if ( edgeLen > maxEdgeLen ) maxEdgeLen = edgeLen;
		}

		// Compute how many regular segments to divide the longest edge into so that 
		// every resulting segment is not longer than maxGathererQuadEdgeLength.
		int numSegments = (int) ceil( maxEdgeLen / maxGathererQuadEdgeLength );

		// Each shooter quad on the current surface is going to be subdivided into
		// (numSegments*numSegments) gatherer quads.
		// Therefore, the total number of gatherer quads for this surface is...
		surface->numGathererQuads = surface->numShooterQuads * numSegments * numSegments;

		surface->gatherers = (QM_GathererQuad *) CheckedMalloc( sizeof(QM_GathererQuad) * surface->numGathererQuads );
		int surfGatherersCount = 0;  // This will contain the number of gatherers in this surface.

		for ( int q = 0; q < surface->numShooterQuads; q++ )
		{
			QM_ShooterQuad *shooterQuad = &(surface->shooters[q]);

			for ( int y = 0; y < numSegments; y++ )
				for ( int x = 0; x < numSegments; x++ )
				{
					float newv[4][3];
					QuadBilinearInterpolate( newv[0], (float) x / numSegments, (float) y / numSegments, shooterQuad->v );
					QuadBilinearInterpolate( newv[1], (float) (x+1) / numSegments, (float) y / numSegments, shooterQuad->v );
					QuadBilinearInterpolate( newv[2], (float) (x+1) / numSegments, (float) (y+1) / numSegments, shooterQuad->v );
					QuadBilinearInterpolate( newv[3], (float) x / numSegments, (float) (y+1) / numSegments, shooterQuad->v );

					QM_GathererQuad *gathererQuad = &(surface->gatherers[ surfGatherersCount ]);
					for ( int i = 0; i < 4; i++ ) CopyArray3( gathererQuad->v[i], newv[i] );
					CopyArray3( gathererQuad->normal, shooterQuad->normal );
					gathererQuad->area = QuadArea( gathererQuad->v );

					// Initialize the radiosity of the gatherer quad.
					gathererQuad->radiosity[0] = surface->emission[0];
					gathererQuad->radiosity[1] = surface->emission[1];
					gathererQuad->radiosity[2] = surface->emission[2];

					CopyArray3( gathererQuad->vRadiosity[0], ZERO_VEC_3F );
					CopyArray3( gathererQuad->vRadiosity[1], ZERO_VEC_3F );
					CopyArray3( gathererQuad->vRadiosity[2], ZERO_VEC_3F );
					CopyArray3( gathererQuad->vRadiosity[3], ZERO_VEC_3F );

					gathererQuad->shooter = shooterQuad;
					gathererQuad->surface = surface;
					surfGatherersCount++;
					modelTotalGatherers++;
				}
		}
	}


	// Build an array of pointers to all the gatherers in the model.
	m->totalGatherers = modelTotalGatherers;
	m->gatherers = (QM_GathererQuad **) CheckedMalloc( sizeof(QM_GathererQuad *) * modelTotalGatherers );
	int modelTotalGatherersCount = 0;

	for ( int s = 0; s < m->numSurfaces; s++ )
		for ( int q = 0; q < m->surfaces[s].numGathererQuads; q++ )
		{
			m->gatherers[ modelTotalGatherersCount ] = &(m->surfaces[s].gatherers[q]);
			modelTotalGatherersCount++;
		}

	return;
}