Пример #1
0
void computeDSI(CByteImage im1,       // source (reference) image
		CByteImage im2,       // destination (match) image
		MRF::CostVal *&dsi,   // computed cost volume
		int nD,               // number of disparities
		int birchfield,       // use Birchfield/Tomasi costs
		int squaredDiffs,     // use squared differences
		int truncDiffs)       // truncated differences
{
    CShape sh = im1.Shape();
    int width = sh.width, height = sh.height, nB = sh.nBands;
    dsi = new MRF::CostVal[width * height * nD];

    int nColors = __min(3, nB);

    // worst value for sumdiff below 
    int worst_match = nColors * (squaredDiffs ? 255 * 255 : 255);
    // truncation threshold - NOTE: if squared, don't multiply by nColors (Eucl. dist.)
    int maxsumdiff = squaredDiffs ? truncDiffs * truncDiffs : nColors * abs(truncDiffs);
    // value for out-of-bounds matches
    int badcost = __min(worst_match, maxsumdiff);

    int dsiIndex = 0;
    for (int y = 0; y < height; y++) {
	for (int x = 0; x < width; x++) {
	    uchar *pix1 = &im1.Pixel(x, y, 0);
	    for (int d = 0; d < nD; d++) {
		int x2 = x-d;
		int dsiValue;
                if (x2 >= 0 && d < nD) { // in bounds
		    uchar *pix2 = &im2.Pixel(x2, y, 0);
                    int sumdiff = 0;
                    for (int b = 0; b < nColors; b++) {
			int diff = 0;
			if (birchfield) {
			    // Birchfield/Tomasi cost
			    int im1c = pix1[b];
			    int im1l = x == 0?   im1c : (im1c + pix1[b - nB]) / 2;
			    int im1r = x == width-1? im1c : (im1c + pix1[b + nB]) / 2;
			    int im2c = pix2[b];
			    int im2l = x2 == 0?   im2c : (im2c + pix2[b - nB]) / 2;
			    int im2r = x2 == width-1? im2c : (im2c + pix2[b + nB]) / 2;
			    int min1 = __min(im1c, __min(im1l, im1r));
			    int max1 = __max(im1c, __max(im1l, im1r));
			    int min2 = __min(im2c, __min(im2l, im2r));
			    int max2 = __max(im2c, __max(im2l, im2r));
			    int di1 = __max(0, __max(im1c - max2, min2 - im1c));
			    int di2 = __max(0, __max(im2c - max1, min1 - im2c));
			    diff = __min(di1, di2);
			} else {
			    // simple absolute difference
			    int di = pix1[b] - pix2[b];
			    diff = abs(di);
			}
			// square diffs if requested (Birchfield too...)
			sumdiff += (squaredDiffs ? diff * diff : diff);
                    }
		    // truncate diffs
		    dsiValue = __min(sumdiff, maxsumdiff);
                } else { // out of bounds: use maximum truncated cost
		    dsiValue = badcost;
		}
		//int x0=-140, y0=-150;
		//if (x==x0 && y==y0)
		//    printf("dsi(%d,%d,%2d)=%3d\n", x, y, d, dsiValue); 

		// The cost of pixel p and label l is stored at dsi[p*nLabels+l]
		dsi[dsiIndex++] = dsiValue;
	    }
	}
    }
    //exit(1);
}
Пример #2
0
void evaldisp(CFloatImage disp, CFloatImage gtdisp, CByteImage mask, float badthresh, int maxdisp, int rounddisp)
{
    CShape sh = gtdisp.Shape();
    CShape sh2 = disp.Shape();
    CShape msh = mask.Shape();
    int width = sh.width, height = sh.height;
    int width2 = sh2.width, height2 = sh2.height;
    int scale = width / width2;

    if ((!(scale == 1 || scale == 2 || scale == 4))
	|| (scale * width2 != width)
	|| (scale * height2 != height)) {
	printf("   disp size = %4d x %4d\n", width2, height2);
	printf("GT disp size = %4d x %4d\n", width,  height);
	throw CError("GT disp size must be exactly 1, 2, or 4 * disp size");
    }

    int usemask = (msh.width > 0 && msh.height > 0);
    if (usemask && (msh != sh))
	throw CError("mask image must have same size as GT\n");

    int n = 0;
    int bad = 0;
    int invalid = 0;
    float serr = 0;
    for (int y = 0; y < height; y++) {
	for (int x = 0; x < width; x++) {
	    float gt = gtdisp.Pixel(x, y, 0);
	    if (gt == INFINITY) // unknown
		continue;
	    float d = scale * disp.Pixel(x / scale, y / scale, 0);
		float maxd = scale * maxdisp; // max disp range
	    int valid = (d != INFINITY && d <= maxd * 1000);
	    if (valid) {
		d = __max(0, __min(maxd, d)); // clip disps to max disp range
	    }
	    if (valid && rounddisp)
		d = round(d);
	    float err = fabs(d - gt);
	    if (usemask && mask.Pixel(x, y, 0) != 255) { // don't evaluate pixel
	    } else {
		n++;
		if (valid) {
		    serr += err;
		    if (err > badthresh) {
			bad++;
		    }
		} else {// invalid (i.e. hole in sparse disp map)
		    invalid++;
		}
	    }
	}
    }
    float badpercent =  100.0*bad/n;
    float invalidpercent =  100.0*invalid/n;
    float totalbadpercent =  100.0*(bad+invalid)/n;
    float avgErr = serr / (n - invalid); // CHANGED 10/14/2014 -- was: serr / n
    //printf("mask  bad%.1f  invalid  totbad   avgErr\n", badthresh);
    printf("%4.1f  %6.2f  %6.2f   %6.2f  %6.2f\n",   100.0*n/(width * height),
	   badpercent, invalidpercent, totalbadpercent, avgErr);
}
Пример #3
0
Feature 
HOGFeatureExtractor::operator()(const CByteImage& img_) const
{
	/******** BEGIN TODO ********/
	// Compute the Histogram of Oriented Gradients feature
	// Steps are:
	// 1) Compute gradients in x and y directions. We provide the 
	//    derivative kernel proposed in the paper in _kernelDx and
	//    _kernelDy.
	// 2) Compute gradient magnitude and orientation
	// 3) Add contribution each pixel to HOG cells whose
	//    support overlaps with pixel. Each cell has a support of size
	//    _cellSize and each histogram has _nAngularBins.
	// 4) Normalize HOG for each cell. One simple strategy that is
	//    is also used in the SIFT descriptor is to first threshold
	//    the bin values so that no bin value is larger than some
	//    threshold (we leave it up to you do find this value) and
	//    then re-normalize the histogram so that it has norm 1. A more 
	//    elaborate normalization scheme is proposed in Dalal & Triggs
	//    paper but we leave that as extra credit.
	// 
	// Useful functions:
	// convertRGB2GrayImage, TypeConvert, WarpGlobal, Convolve

	
	int xCells = ceil(1.*img_.Shape().width  / _cellSize);
	int yCells = ceil(1.*img_.Shape().height / _cellSize);

	CFloatImage HOGHist(xCells, yCells, _nAngularBins);
	HOGHist.ClearPixels();

	CByteImage gray(img_.Shape());
	CFloatImage grayF(img_.Shape().width, img_.Shape().height, 1);

	convertRGB2GrayImage(img_, gray);
	TypeConvert(gray, grayF);

	CFloatImage diffX( img_.Shape()), diffY( img_.Shape());

	Convolve(grayF, diffX, _kernelDx);
	Convolve(grayF, diffY, _kernelDy);
	
	CFloatImage grad(grayF.Shape()), grad2(grayF.Shape());
	CFloatImage angl(grayF.Shape()), angl2(grayF.Shape());
	
	for (int y = 0; y <grayF.Shape().height; y++){
		for (int x = 0; x<grayF.Shape().width; x++) {
			grad2.Pixel(x,y,0) = (diffX.Pixel(x,y,0) * diffX.Pixel(x,y,0) +
							     diffY.Pixel(x,y,0) * diffY.Pixel(x,y,0));
			angl2.Pixel(x,y,0) = atan(diffY.Pixel(x,y,0) / abs(diffY.Pixel(x,y,0)));
		}
	}

	// Bilinear Filter
	ConvolveSeparable(grad2, grad, ConvolveKernel_121,ConvolveKernel_121,1);
	ConvolveSeparable(angl2, angl, ConvolveKernel_121,ConvolveKernel_121,1);
	//WriteFile(diffX, "angle.tga");
	//WriteFile(diffY, "angleG.tga");

	for (int y = 0; y <grayF.Shape().height; y++){
		for (int x = 0; x<grayF.Shape().width; x++) {
			// Fit in the bins
			int a = angl.Pixel(x,y,0) / 3.14 * (_nAngularBins) + _nAngularBins/2;		
			// Histogram
			HOGHist.Pixel(floor(1.*x / _cellSize),
						  floor(1.*y / _cellSize),
						  a) += grad.Pixel(x,y,0);
		}
	}
	
	// Normalization 
	float threshold = 0.7;
	for (int y = 0; y < yCells; y++){
		for (int x = 0; x < xCells; x++){
			float total = 0;
			for (int a = 0; a < _nAngularBins; a++) {
				if (HOGHist.Pixel(x,y,a) > threshold)
					HOGHist.Pixel(x,y,a) = threshold;
				// Sum for normalization
				total += HOGHist.Pixel(x,y,a);
			}
			for (int a = 0;a< _nAngularBins; a++) {
				HOGHist.Pixel(x,y,a) /= total;
				
			}
		}
	}
	
	return HOGHist;
	/******** END TODO ********/

}
Пример #4
0
/******************* TO DO *********************
* AccumulateBlend:
*	INPUT:
*		img: a new image to be added to acc
*		acc: portion of the accumulated image where img is to be added
*       M: the transformation mapping the input image 'img' into the output panorama 'acc'
*		blendWidth: width of the blending function (horizontal hat function;
*	    try other blending functions for extra credit)
*	OUTPUT:
*		add a weighted copy of img to the subimage specified in acc
*		the first 3 band of acc records the weighted sum of pixel colors
*		the fourth band of acc records the sum of weight
*/
static void AccumulateBlend(CByteImage& img, CFloatImage& acc, CTransform3x3 M, float blendWidth)
{
    // BEGIN TODO
    // Fill in this routine
	// get shape of acc and img
	CShape sh = img.Shape();
    int width = sh.width;
    int height = sh.height;
	CShape shacc = acc.Shape();
    int widthacc = shacc.width;
    int heightacc = shacc.height;
	
	// get the bounding box of img in acc
	int min_x, min_y, max_x, max_y;
	ImageBoundingBox(img, M, min_x, min_y, max_x, max_y);

	CVector3 p;
	double newx, newy;

	// Exposure Compensation
	double lumaScale = 1.0;
	double lumaAcc = 0.0;
	double lumaImg = 0.0;
	int cnt = 0;

	for (int ii = min_x; ii < max_x; ii++)
		for (int jj = min_y; jj < max_y; jj++)
		{
			// flag: current pixel black or not
			bool flag = false;
			p[0] = ii; p[1] = jj; p[2] = 1;
			p = M.Inverse() * p;
			newx = p[0] / p[2];
			newy = p[1] / p[2];
			// If in the overlapping region
			if (newx >=0 && newx < width && newy >=0 && newy < height)
			{
				if (acc.Pixel(ii,jj,0) == 0 &&
					acc.Pixel(ii,jj,1) == 0 &&
					acc.Pixel(ii,jj,2) == 0)
					flag = true;
				if (img.PixelLerp(newx,newy,0) == 0 &&
					img.PixelLerp(newx,newy,1) == 0 &&
					img.PixelLerp(newx,newy,2) == 0)
					flag = true;
				if (!flag)
				{
					// Compute Y using RGB (RGB -> YUV)
					lumaAcc = 0.299 * acc.Pixel(ii,jj,0) +
							   0.587 * acc.Pixel(ii,jj,1) +
							   0.114 * acc.Pixel(ii,jj,2);
					lumaImg = 0.299 * img.PixelLerp(newx,newy,0) +
							   0.587 * img.PixelLerp(newx,newy,1) +
							   0.114 * img.PixelLerp(newx,newy,2);
					
					if (lumaImg != 0)
					{
						double scale = lumaAcc / lumaImg;
						if (scale > 0.5 && scale < 2)
						{
							lumaScale += lumaAcc / lumaImg;
							cnt++;
						}
					}
				}
			}
		}

	if (cnt != 0)
		lumaScale = lumaScale / (double)cnt;
	else lumaScale = 1.0;

	// add every pixel in img to acc, feather the region withing blendwidth to the bounding box,
	// pure black pixels (caused by warping) are not added
	double weight;
	
	for (int ii = min_x; ii < max_x; ii++)
		for (int jj = min_y; jj < max_y; jj++)
		{
			p[0] = ii; p[1] = jj; p[2] = 1;
			p = M.Inverse() * p;
			newx = p[0] / p[2];
			newy = p[1] / p[2];
			if ((newx >= 0) && (newx < width-1) && (newy >= 0) && (newy < height-1))
			{
				weight = 1.0;
				if ( (ii >= min_x) && (ii < (min_x+blendWidth)) )
					weight = (ii-min_x) / blendWidth;
				if ( (ii <= max_x) && (ii > (max_x-blendWidth)) )
					weight = (max_x-ii) / blendWidth;
				if (img.Pixel(iround(newx),iround(newy),0) == 0 &&
					img.Pixel(iround(newx),iround(newy),1) == 0 &&
					img.Pixel(iround(newx),iround(newy),2) == 0)
					weight = 0.0;

				double LerpR = img.PixelLerp(newx, newy, 0);
				double LerpG = img.PixelLerp(newx, newy, 1);
				double LerpB = img.PixelLerp(newx, newy, 2);
				
				double r = LerpR*lumaScale > 255.0 ? 255.0 : LerpR*lumaScale;
				double g = LerpG*lumaScale > 255.0 ? 255.0 : LerpG*lumaScale;
				double b = LerpB*lumaScale > 255.0 ? 255.0 : LerpB*lumaScale;
				acc.Pixel(ii,jj,0) += r * weight;
				acc.Pixel(ii,jj,1) += g * weight;
				acc.Pixel(ii,jj,2) += b * weight;
				acc.Pixel(ii,jj,3) += weight;
			}
		}
	
	printf("AccumulateBlend\n"); 

    // END TODO
}
Пример #5
0
void ReadFileTGA(CByteImage& img, const char* filename)
{
    // Open the file and read the header
    FILE *stream = fopen(filename, "rb");
    if (stream == 0)
        throw CError("ReadFileTGA: could not open %s", filename);
    CTargaHead h;
    if (fread(&h, sizeof(CTargaHead), 1, stream) != 1)
	    throw CError("ReadFileTGA(%s): file is too short", filename);

    // Throw away the image descriptor
    if (h.idLength > 0)
    {
        char* tmp = new char[h.idLength];
        int nread = fread(tmp, sizeof(uchar), h.idLength, stream);
        delete tmp;   // throw away this data
        if (nread != h.idLength)
	        throw CError("ReadFileTGA(%s): file is too short", filename);
    }
    bool isRun = (h.imageType & 8) != 0;
    bool reverseRows = (h.descriptor & TargaScreenOrigin) != 0;
    int fileBytes = (h.pixelSize + 7) / 8;

    // Read the colormap
    uchar colormap[TargaCMapSize][TargaCMapBands];
    int cMapSize = 0;
    bool grayRamp = false;
    if (h.colorMapType == 1)
    {
        cMapSize = (h.cMapLength[1] << 8) + h.cMapLength[0];
        if (h.cMapBits != 24)
            throw CError("ReadFileTGA(%s): only 24-bit colormap currently supported", filename);
	    int l = fileBytes * cMapSize;
        if (l > TargaCMapSize * TargaCMapBands)
	        throw CError("ReadFileTGA(%s): colormap is too large", filename);
	    if (fread(colormap, sizeof(uchar), l, stream) != l)
	        throw CError("ReadFileTGA(%s): could not read the colormap", filename);

        // Check if it's just a standard gray ramp
	int i;
        for (i = 0; i < cMapSize; i++) {
            for (int j = 0; j < TargaCMapBands; j++)
                if (colormap[i][j] != i)
                    break;
        }
        grayRamp = (i == cMapSize);    // didn't break out too soon
    }
    bool isGray = 
        h.imageType == TargaRawBW || h.imageType == TargaRunBW ||
        grayRamp &&
        (h.imageType == TargaRawColormap || h.imageType == TargaRunColormap);
    bool isRaw = h.imageType == TargaRawBW || h.imageType == TargaRawRGB ||
        h.imageType == TargaRawRGB && isGray;

    // Determine the image shape
    CShape sh(h.width, h.height, (isGray) ? 1 : 4);
    
    // Allocate the image if necessary
    img.ReAllocate(sh, false);

    // Construct a run-length code reader
    CTargaRLC rlc(! isRaw);

    // Read in the rows
    for (int y = 0; y < sh.height; y++)
    {
        int yr = reverseRows ? sh.height-1-y : y;
        uchar* ptr = (uchar *) img.PixelAddress(0, yr, 0);
        if (fileBytes == sh.nBands && isRaw)
        {
            // Special case for raw image, same as destination
            int n = sh.width*sh.nBands;
    	    if (fread(ptr, sizeof(uchar), n, stream) != n)
    	        throw CError("ReadFileTGA(%s): file is too short", filename);
        }
        else
        {
            // Read one pixel at a time
            for (int x = 0; x < sh.width; x++, ptr += sh.nBands)
            {
                uchar* buf = rlc.getBytes(fileBytes, stream);
                if (fileBytes == 1 && sh.nBands == 1)
                {
                    ptr[0] = buf[0];
                }
                else if (fileBytes == 1 && sh.nBands == 4)
                {
                    for (int i = 0; i < 3; i++)
                        ptr[i] = (isGray) ? buf[0] : colormap[buf[0]][i];
                    ptr[3] = 255;   // full alpha;
                }
                else if ((fileBytes == 3 || fileBytes == 4) && sh.nBands == 4)
                {
                    int i;
                    for (i = 0; i < fileBytes; i++)
                        ptr[i] = buf[i];
                    if (i == 3) // missing alpha channel
                        ptr[3] = 255;   // full alpha;
                }
                else
            	    throw CError("ReadFileTGA(%s): unhandled pixel depth or # of bands", filename);
            }
        }
    }

    if (fclose(stream))
        throw CError("ReadFileTGA(%s): error closing file", filename);
}
Пример #6
0
// TODO: the following function should go somewhere else, perhaps in ImageIO.cpp
// Make sure the image has the smallest number of bands before writing.
// That is, if it's 4 bands with full alpha, reduce to 3 bands.  
// If it's 3 bands with constant colors, make it 1-band.
CByteImage removeRedundantBands(CByteImage img)
{
    CShape sh = img.Shape();
	int w = sh.width, h = sh.height, nB = sh.nBands;
	int x, y;
	if (nB < 3)
		return img;

	// check if full alpha if alpha channel present
	bool fullAlpha = true;
	if (nB == 4) {
		for (y = 0; y < h && fullAlpha; y++) {
			uchar *pix = &img.Pixel(0, y, 0);
			for (x = 0; x < w; x++) {
				if (pix[3] != 255) {
					fullAlpha = false;
					break;
				}
				pix += nB;
			}
		}
	}
	if (!fullAlpha)
		return img;

	// check for equal colors
	bool equalColors = true;
	for (y = 0; y < h && equalColors; y++) {
		uchar *pix = &img.Pixel(0, y, 0);
		for (x = 0; x < w; x++) {
			if (pix[0] != pix[1] ||
				pix[0] != pix[2] ||
				pix[1] != pix[2]) {
					equalColors = false;
					break;
				}
				pix += nB;
		}
	}
	// at this point, if nB == 4 we can reduce to at least 3 bands,
	// and if equalColors we can reduce to 1 band.
	if (! equalColors && nB < 4)
		return img;

	int newNB = equalColors ? 1 : 3;

	if (DEBUG_ImageIOpng)
		fprintf(stderr, "reducing from %d to %d bands\n", nB, newNB);

	CShape sh2(w, h, newNB);
	CByteImage img2(sh2);
	
	for (y = 0; y < h; y++) {
		uchar *pix = &img.Pixel(0, y, 0);
		uchar *pix2 = &img2.Pixel(0, y, 0);
		for (x = 0; x < w; x++) {
			for (int b = 0; b < newNB; b++) {
				pix2[b] = pix[b];
			}
			pix += nB;
			pix2 += newNB;
		}
	}

	return img2;
}
Пример #7
0
void WriteFilePNG(CByteImage img, const char* filename)
{
	img = removeRedundantBands(img);

    CShape sh = img.Shape();
    int width = sh.width, height = sh.height, nBands = sh.nBands;

	// Make sure the image has the smallest number of bands before writing.
	// That is, if it's 4 bands with full alpha, reduce to 3 bands.  
	// If it's 3 bands with constant colors, make it 1-band.

    FILE *stream = fopen(filename, "wb");
    if (stream == 0)
        throw CError("WriteFilePNG: could not open %s", filename);

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
      (png_error_ptr)pngfile_error, (png_error_ptr)NULL);

	if (!png_ptr) {
        fclose(stream);
		throw CError("WriteFilePNG: error creating png structure");
	}

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        fclose(stream);
		throw CError("WriteFilePNG: error creating png structure");
    }

	png_init_io(png_ptr, stream);

	int bits = 8;
	int colortype =
		nBands == 1 ? PNG_COLOR_TYPE_GRAY :
		nBands == 3 ? PNG_COLOR_TYPE_RGB :
	                  PNG_COLOR_TYPE_RGB_ALPHA;
	png_set_IHDR(png_ptr, info_ptr, width, height, 
		bits, colortype,
		PNG_INTERLACE_NONE, 
		PNG_COMPRESSION_TYPE_DEFAULT, 
		PNG_FILTER_TYPE_DEFAULT);

	// write the file header information
	png_write_info(png_ptr, info_ptr);

	// swap the BGR pixels in the DiData structure to RGB
	png_set_bgr(png_ptr);

	//  allocate a vector of row pointers
	std::vector<uchar *> rowPtrs;
	rowPtrs.resize(height);
	for (int y = 0; y<height; y++)
		rowPtrs[y] = &img.Pixel(0, y, 0);

	// write the whole image
	png_write_image(png_ptr, &rowPtrs[0]);

	// write the additional chunks to the PNG file (not really needed)
	png_write_end(png_ptr, info_ptr);

	png_destroy_write_struct(&png_ptr, (png_infopp) NULL);

    fclose (stream);
}
Пример #8
0
void ReadFilePNG(CByteImage& img, const char* filename)
{
    // open the PNG input file
    FILE *stream = fopen(filename, "rb");
    if (stream == 0)
        throw CError("ReadFilePNG: could not open %s", filename);

    // first check the eight byte PNG signature
    png_byte pbSig[8];
    fread(pbSig, 1, 8, stream);
	if (!png_check_sig(pbSig, 8)) {
        fclose(stream);
        throw CError("ReadFilePNG: invalid PNG signature");
	}

    // create the two png(-info) structures
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
      (png_error_ptr)pngfile_error, (png_error_ptr)NULL);

	if (!png_ptr) {
        fclose(stream);
		throw CError("ReadFilePNG: error creating png structure");
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_read_struct(&png_ptr, NULL, NULL);
        fclose(stream);
		throw CError("ReadFilePNG: error creating png structure");
	}

	png_init_io(png_ptr, stream);
	png_set_sig_bytes(png_ptr, 8);

	// read all PNG info up to image data
	png_read_info(png_ptr, info_ptr);

	// get width, height, bit-depth and color-type
	int width, height, bits, colorType, nBands;

	png_uint_32 pwidth, pheight;

	png_get_IHDR(png_ptr, info_ptr, 
		     &pwidth, &pheight,
		     //(png_uint_32 *)&width, (png_uint_32 *)&height,
		     &bits, &colorType, NULL, NULL, NULL);

	width = pwidth;
	height = pheight;

	nBands = (int)png_get_channels(png_ptr, info_ptr);

	if (DEBUG_ImageIOpng)
	fprintf(stderr, " w=%d, h=%d, %2d bits, %s, nB=%d",
		width, height, bits, 
		colorType == PNG_COLOR_TYPE_GRAY ? "gray" :
		colorType == PNG_COLOR_TYPE_PALETTE ? "plt " :
		colorType == PNG_COLOR_TYPE_RGB ? "rgb " :
		colorType == PNG_COLOR_TYPE_RGB_ALPHA ? "rgba" :
		colorType == PNG_COLOR_TYPE_GRAY_ALPHA ? "gr-a" : "??? ",
		nBands);


	// get rid of lower-order byte in 16-bit images
	// TODO: could allow this and read in IntImage in this case...
	if (bits == 16)
		png_set_strip_16(png_ptr);

	// change palette color into RGB
	if (colorType == PNG_COLOR_TYPE_PALETTE)
		png_set_expand(png_ptr);

	// want at least 8 bits
	if (bits < 8)
		png_set_expand(png_ptr);

	// if there is a transparent palette entry, create alpha channel
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_expand(png_ptr);

	// make gray images with alpha channel into RGBA -- TODO: or just ignore alpha?
	if (colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
		// colorType == PNG_COLOR_TYPE_GRAY       // but leave gray images alone
		png_set_gray_to_rgb(png_ptr);

	// set the background color to draw transparent and alpha images over.
	// only needed for gray images with alpha 
	if (colorType == PNG_COLOR_TYPE_GRAY_ALPHA ||
		colorType == PNG_COLOR_TYPE_GRAY) {
		png_color_16 *pBackground;
		if (png_get_bKGD(png_ptr, info_ptr, &pBackground))
			png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
		}

	// if required set gamma conversion
	// this seems to cause problems, so let's just leave gamma alone.
	//double gamma;
	//if (png_get_gAMA(png_ptr, info_ptr, &gamma)) {
	// //fprintf(stderr, "\n reading gamma %lf\n", gamma);
	//png_set_gamma(png_ptr, 1.0, gamma);
	//}

	// we need colors in BGR order, not RGB
	png_set_bgr(png_ptr);

	// always convert 3-band to 4-band images (add alpha):
	if (colorType == PNG_COLOR_TYPE_RGB)
		png_set_add_alpha(png_ptr, 255, PNG_FILLER_AFTER);

	// after the transformations have been registered update info_ptr data
	png_read_update_info(png_ptr, info_ptr);

	// get again width, height and the new bit-depth and color-type

	png_get_IHDR(png_ptr, info_ptr, 
		     &pwidth, &pheight,
		     //(png_uint_32 *)&width, (png_uint_32 *)&height,
		     &bits, &colorType, NULL, NULL, NULL);
	
	width = pwidth;
	height = pheight;

	nBands = (int)png_get_channels(png_ptr, info_ptr);

	if (DEBUG_ImageIOpng)
	fprintf(stderr, "  -> w=%d, h=%d, %2d bits, %s, nB=%d\n",
		width, height, bits,
		colorType == PNG_COLOR_TYPE_GRAY ? "gray" :
		colorType == PNG_COLOR_TYPE_PALETTE ? "plt " :
		colorType == PNG_COLOR_TYPE_RGB ? "rgb " :
		colorType == PNG_COLOR_TYPE_RGB_ALPHA ? "rgba" :
		colorType == PNG_COLOR_TYPE_GRAY_ALPHA ? "gr-a" : "??? ",
		nBands);
	

	if (! (nBands==1 || nBands==3 || nBands==4)) {
        fclose(stream);
		throw CError("ReadFilePNG: Can't handle nBands=%d", nBands);
	}

	// Set the image shape
	CShape sh(width, height, nBands);

	// Allocate the image if necessary
	img.ReAllocate(sh);

	//  allocate a vector of row pointers
	std::vector<uchar *> rowPtrs;
	rowPtrs.resize(height);
	for (int y = 0; y<height; y++)
		rowPtrs[y] = &img.Pixel(0, y, 0);

	// read the whole image
	png_read_image(png_ptr, &rowPtrs[0]);

 	// read the additional chunks in the PNG file (not really needed)
	png_read_end(png_ptr, NULL);

	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

	fclose(stream);
}
Пример #9
0
int BlendPairs(int argc, const char *argv[])
{
    // Blend a sequence of images given the pairwise transformations
    if (argc < 5)
    {
        printf("usage: %s pairlist.txt outimg.tga blendWidth\n", argv[1]);
        return -1;
    }
    const char *pairlist= argv[2];
    const char *outfile = argv[3];
    float blendWidth    = (float) atof(argv[4]);

    // Open the list of image pairs
    FILE *stream = fopen(pairlist, "r");
    if (stream == 0)
        throw CError("%s: could not open the file %s", argv[1], pairlist);

    // Construct the list of images and translations
    CImagePositionV ipList;
    char line[1024], infile1[1024], infile2[1024];
    // float rel_t[2];
    CTransform3x3 M;

    int n;
    for (n = 0; fgets(line, 1024, stream); n++)
    {
        // Compute the position from the PREVIOUS displacement
        CImagePosition ip;

		if (n == 0) {
			ip.position = CTransform3x3::Translation(0.0, 0.0); /* Ident matrix */
			// ip.position = CTransform3x3::Rotation(45.0); /* Ident matrix */
		} else {
			ip.position = M * ipList[n-1].position;
		}

        // for (int k = 0; k < 2; k++)
        //    ip.position[k] = (n > 0) ? ipList[n-1].position[k] - rel_t[k] : 0.0f;

        // Read the line and push the image onto the list
        // if (sscanf(line, "%s %s %f %f", infile1, infile2,
        //           &rel_t[0], &rel_t[1]) != 4)
        //    throw CError("%s: error reading %s", argv[1], pairlist);

#if 0
        if (sscanf(line, "%s %s %lf %lf", infile1, infile2,
			&(M[0][2]), &(M[1][2])) != 4)
			throw CError("%s: error reading %s\n", argv[1], pairlist);
#else
        if (sscanf(line, "%s %s %lf %lf %lf %lf %lf %lf %lf %lf %lf", infile1, infile2,
			&(M[0][0]), &(M[0][1]), &(M[0][2]), 
			&(M[1][0]), &(M[1][1]), &(M[1][2]), 
			&(M[2][0]), &(M[2][1]), &(M[2][2])) != 11)
			throw CError("%s: error reading %s\n", argv[1], pairlist);
#endif

		// The coordinate system of the ImageLib images has y reflected -- so let's fix that!

		// M[1][2] = -M[1][2];

		ip.imgName = std::string(infile1);
		CByteImage imgTmp;
		ReadFile(imgTmp, infile1);
		ip.img = CByteImage(imgTmp.Shape());
		FlipImage(imgTmp, ip.img);

		ipList.push_back(ip);
	}

	// Read in the last image
	CImagePosition ip;

	// for (int k = 0; k < 2; k++)
	//     ip.position[k] = ipList[n-1].position[k] - rel_t[k];
	ip.position = M * ipList[n-1].position;

	ip.imgName = std::string(infile2);
	CByteImage imgTmp;
	ReadFile(imgTmp, infile2);
	ip.img = CByteImage(imgTmp.Shape());
	FlipImage(imgTmp, ip.img);

	ipList.push_back(ip);
	fclose(stream);

	CByteImage resultTmp = BlendImages(ipList, blendWidth);

	// Flip again
	CByteImage result(resultTmp.Shape());
	FlipImage(resultTmp, result);

	WriteFile(result, outfile);
	return 0;
}