⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ximatran.cpp

📁 用Cximage 库显示各种格式图片小程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	
	if (iDst) iDst->Transfer(imgDest);
	else Transfer(imgDest);
	
	return true;
}
////////////////////////////////////////////////////////////////////////////////
bool CxImage::Rotate180(CxImage* iDst)
{
	if (!pDib) return false;

	long wid = GetWidth();
	long ht = GetHeight();

	CxImage imgDest;
	imgDest.CopyInfo(*this);
	imgDest.Create(wid,ht,GetBpp(),GetType());
	imgDest.SetPalette(GetPalette());

#if CXIMAGE_SUPPORT_ALPHA
	if (AlphaIsValid())	imgDest.AlphaCreate();
#endif //CXIMAGE_SUPPORT_ALPHA

	long x,y,y2;
	for (y = 0; y < ht; y++){
		info.nProgress = (long)(100*y/ht); //<Anatoly Ivasyuk>
		y2=ht-y-1;
		for (x = 0; x < wid; x++){
			if(head.biClrUsed==0)//RGB
				imgDest.SetPixelColor(wid-x-1, y2, BlindGetPixelColor(x, y));
			else  //PALETTE
				imgDest.SetPixelIndex(wid-x-1, y2, BlindGetPixelIndex(x, y));

#if CXIMAGE_SUPPORT_ALPHA
			if (AlphaIsValid())	imgDest.AlphaSet(wid-x-1, y2,BlindAlphaGet(x, y));
#endif //CXIMAGE_SUPPORT_ALPHA

		}
	}

	//select the destination
	if (iDst) iDst->Transfer(imgDest);
	else Transfer(imgDest);
	return true;
}

////////////////////////////////////////////////////////////////////////////////
/**
 * Resizes the image. mode can be 0 for slow (bilinear) method ,
 * 1 for fast (nearest pixel) method, or 2 for accurate (bicubic spline interpolation) method.
 * The function is faster with 24 and 1 bpp images, slow for 4 bpp images and slowest for 8 bpp images.
 */
bool CxImage::Resample(long newx, long newy, int mode, CxImage* iDst)
{
	if (newx==0 || newy==0) return false;

	if (head.biWidth==newx && head.biHeight==newy){
		if (iDst) iDst->Copy(*this);
		return true;
	}

	float xScale, yScale, fX, fY;
	xScale = (float)head.biWidth  / (float)newx;
	yScale = (float)head.biHeight / (float)newy;

	CxImage newImage;
	newImage.CopyInfo(*this);
	newImage.Create(newx,newy,head.biBitCount,GetType());
	newImage.SetPalette(GetPalette());
	if (!newImage.IsValid()){
		strcpy(info.szLastError,newImage.GetLastError());
		return false;
	}

	switch (mode) {
	case 1: // nearest pixel
	{ 
		for(long y=0; y<newy; y++){
			info.nProgress = (long)(100*y/newy);
			if (info.nEscape) break;
			fY = y * yScale;
			for(long x=0; x<newx; x++){
				fX = x * xScale;
				newImage.SetPixelColor(x,y,GetPixelColor((long)fX,(long)fY));
			}
		}
		break;
	}
	case 2: // bicubic interpolation by Blake L. Carlson <blake-carlson(at)uiowa(dot)edu
	{
		float f_x, f_y, a, b, rr, gg, bb, r1, r2;
		int   i_x, i_y, xx, yy;
		RGBQUAD rgb;
		BYTE* iDst;
		for(long y=0; y<newy; y++){
			info.nProgress = (long)(100*y/newy);
			if (info.nEscape) break;
			f_y = (float) y * yScale - 0.5f;
			i_y = (int) floor(f_y);
			a   = f_y - (float)floor(f_y);
			for(long x=0; x<newx; x++){
				f_x = (float) x * xScale - 0.5f;
				i_x = (int) floor(f_x);
				b   = f_x - (float)floor(f_x);

				rr = gg = bb = 0.0f;
				for(int m=-1; m<3; m++) {
					r1 = KernelBSpline((float) m - a);
					yy = i_y+m;
					if (yy<0) yy=0;
					if (yy>=head.biHeight) yy = head.biHeight-1;
					for(int n=-1; n<3; n++) {
						r2 = r1 * KernelBSpline(b - (float)n);
						xx = i_x+n;
						if (xx<0) xx=0;
						if (xx>=head.biWidth) xx=head.biWidth-1;

						if (head.biClrUsed){
							rgb = GetPixelColor(xx,yy);
						} else {
							iDst  = info.pImage + yy*info.dwEffWidth + xx*3;
							rgb.rgbBlue = *iDst++;
							rgb.rgbGreen= *iDst++;
							rgb.rgbRed  = *iDst;
						}

						rr += rgb.rgbRed * r2;
						gg += rgb.rgbGreen * r2;
						bb += rgb.rgbBlue * r2;
					}
				}

				if (head.biClrUsed)
					newImage.SetPixelColor(x,y,RGB(rr,gg,bb));
				else {
					iDst = newImage.info.pImage + y*newImage.info.dwEffWidth + x*3;
					*iDst++ = (BYTE)bb;
					*iDst++ = (BYTE)gg;
					*iDst   = (BYTE)rr;
				}

			}
		}
		break;
	}
	default: // bilinear interpolation
		if (!(head.biWidth>newx && head.biHeight>newy && head.biBitCount==24)) {
			// (c) 1999 Steve McMahon (steve@dogma.demon.co.uk)
			long ifX, ifY, ifX1, ifY1, xmax, ymax;
			float ir1, ir2, ig1, ig2, ib1, ib2, dx, dy;
			BYTE r,g,b;
			RGBQUAD rgb1, rgb2, rgb3, rgb4;
			xmax = head.biWidth-1;
			ymax = head.biHeight-1;
			for(long y=0; y<newy; y++){
				info.nProgress = (long)(100*y/newy);
				if (info.nEscape) break;
				fY = y * yScale;
				ifY = (int)fY;
				ifY1 = min(ymax, ifY+1);
				dy = fY - ifY;
				for(long x=0; x<newx; x++){
					fX = x * xScale;
					ifX = (int)fX;
					ifX1 = min(xmax, ifX+1);
					dx = fX - ifX;
					// Interpolate using the four nearest pixels in the source
					if (head.biClrUsed){
						rgb1=GetPaletteColor(GetPixelIndex(ifX,ifY));
						rgb2=GetPaletteColor(GetPixelIndex(ifX1,ifY));
						rgb3=GetPaletteColor(GetPixelIndex(ifX,ifY1));
						rgb4=GetPaletteColor(GetPixelIndex(ifX1,ifY1));
					}
					else {
						BYTE* iDst;
						iDst = info.pImage + ifY*info.dwEffWidth + ifX*3;
						rgb1.rgbBlue = *iDst++;	rgb1.rgbGreen= *iDst++;	rgb1.rgbRed =*iDst;
						iDst = info.pImage + ifY*info.dwEffWidth + ifX1*3;
						rgb2.rgbBlue = *iDst++;	rgb2.rgbGreen= *iDst++;	rgb2.rgbRed =*iDst;
						iDst = info.pImage + ifY1*info.dwEffWidth + ifX*3;
						rgb3.rgbBlue = *iDst++;	rgb3.rgbGreen= *iDst++;	rgb3.rgbRed =*iDst;
						iDst = info.pImage + ifY1*info.dwEffWidth + ifX1*3;
						rgb4.rgbBlue = *iDst++;	rgb4.rgbGreen= *iDst++;	rgb4.rgbRed =*iDst;
					}
					// Interplate in x direction:
					ir1 = rgb1.rgbRed   + (rgb3.rgbRed   - rgb1.rgbRed)   * dy;
					ig1 = rgb1.rgbGreen + (rgb3.rgbGreen - rgb1.rgbGreen) * dy;
					ib1 = rgb1.rgbBlue  + (rgb3.rgbBlue  - rgb1.rgbBlue)  * dy;
					ir2 = rgb2.rgbRed   + (rgb4.rgbRed   - rgb2.rgbRed)   * dy;
					ig2 = rgb2.rgbGreen + (rgb4.rgbGreen - rgb2.rgbGreen) * dy;
					ib2 = rgb2.rgbBlue  + (rgb4.rgbBlue  - rgb2.rgbBlue)  * dy;
					// Interpolate in y:
					r = (BYTE)(ir1 + (ir2-ir1) * dx);
					g = (BYTE)(ig1 + (ig2-ig1) * dx);
					b = (BYTE)(ib1 + (ib2-ib1) * dx);
					// Set output
					newImage.SetPixelColor(x,y,RGB(r,g,b));
				}
			} 
		} else {
			//high resolution shrink, thanks to Henrik Stellmann <henrik.stellmann@volleynet.de>
			const long ACCURACY = 1000;
			long i,j; // index for faValue
			long x,y; // coordinates in  source image
			BYTE* pSource;
			BYTE* pDest = newImage.info.pImage;
			long* naAccu  = new long[3 * newx + 3];
			long* naCarry = new long[3 * newx + 3];
			long* naTemp;
			long  nWeightX,nWeightY;
			float fEndX;
			long nScale = (long)(ACCURACY * xScale * yScale);

			memset(naAccu,  0, sizeof(long) * 3 * newx);
			memset(naCarry, 0, sizeof(long) * 3 * newx);

			int u, v = 0; // coordinates in dest image
			float fEndY = yScale - 1.0f;
			for (y = 0; y < head.biHeight; y++){
				info.nProgress = (long)(100*y/head.biHeight); //<Anatoly Ivasyuk>
				if (info.nEscape) break;
				pSource = info.pImage + y * info.dwEffWidth;
				u = i = 0;
				fEndX = xScale - 1.0f;
				if ((float)y < fEndY) {       // complete source row goes into dest row
					for (x = 0; x < head.biWidth; x++){
						if ((float)x < fEndX){       // complete source pixel goes into dest pixel
							for (j = 0; j < 3; j++)	naAccu[i + j] += (*pSource++) * ACCURACY;
						} else {       // source pixel is splitted for 2 dest pixels
							nWeightX = (long)(((float)x - fEndX) * ACCURACY);
							for (j = 0; j < 3; j++){
								naAccu[i] += (ACCURACY - nWeightX) * (*pSource);
								naAccu[3 + i++] += nWeightX * (*pSource++);
							}
							fEndX += xScale;
							u++;
						}
					}
				} else {       // source row is splitted for 2 dest rows       
					nWeightY = (long)(((float)y - fEndY) * ACCURACY);
					for (x = 0; x < head.biWidth; x++){
						if ((float)x < fEndX){       // complete source pixel goes into 2 pixel
							for (j = 0; j < 3; j++){
								naAccu[i + j] += ((ACCURACY - nWeightY) * (*pSource));
								naCarry[i + j] += nWeightY * (*pSource++);
							}
						} else {       // source pixel is splitted for 4 dest pixels
							nWeightX = (int)(((float)x - fEndX) * ACCURACY);
							for (j = 0; j < 3; j++) {
								naAccu[i] += ((ACCURACY - nWeightY) * (ACCURACY - nWeightX)) * (*pSource) / ACCURACY;
								*pDest++ = (BYTE)(naAccu[i] / nScale);
								naCarry[i] += (nWeightY * (ACCURACY - nWeightX) * (*pSource)) / ACCURACY;
								naAccu[i + 3] += ((ACCURACY - nWeightY) * nWeightX * (*pSource)) / ACCURACY;
								naCarry[i + 3] = (nWeightY * nWeightX * (*pSource)) / ACCURACY;
								i++;
								pSource++;
							}
							fEndX += xScale;
							u++;
						}
					}
					if (u < newx){ // possibly not completed due to rounding errors
						for (j = 0; j < 3; j++) *pDest++ = (BYTE)(naAccu[i++] / nScale);
					}
					naTemp = naCarry;
					naCarry = naAccu;
					naAccu = naTemp;
					memset(naCarry, 0, sizeof(int) * 3);    // need only to set first pixel zero
					pDest = newImage.info.pImage + (++v * newImage.info.dwEffWidth);
					fEndY += yScale;
				}
			}
			if (v < newy){	// possibly not completed due to rounding errors
				for (i = 0; i < 3 * newx; i++) *pDest++ = (BYTE)(naAccu[i] / nScale);
			}
			delete [] naAccu;
			delete [] naCarry;
		}
	}

#if CXIMAGE_SUPPORT_ALPHA
	if (AlphaIsValid()){
		newImage.AlphaCreate();
		for(long y=0; y<newy; y++){
			fY = y * yScale;
			for(long x=0; x<newx; x++){
				fX = x * xScale;
				newImage.AlphaSet(x,y,AlphaGet((long)fX,(long)fY));
			}
		}
	}
#endif //CXIMAGE_SUPPORT_ALPHA

	//select the destination
	if (iDst) iDst->Transfer(newImage);
	else Transfer(newImage);

	return true;
}
////////////////////////////////////////////////////////////////////////////////
/**
 * New simpler resample. Adds new interpolation methods and simplifies code (using GetPixelColorInterpolated
 * and GetAreaColorInterpolated). It also (unlike old method) interpolates alpha layer. 
 *
 * \param  newx, newy - size of resampled image
 * \param  inMethod - interpolation method to use (see comments at GetPixelColorInterpolated)
 *              If image size is being reduced, averaging is used instead (or simultaneously with) inMethod.
 * \param  ofMethod - what to replace outside pixels by (only significant for bordering pixels of enlarged image)
 * \param  iDst - pointer to destination CxImage or NULL.
 * \param  disableAveraging - force no averaging when shrinking images (Produces aliasing.
 *                      You probably just want to leave this off...)
 *
 * \author ***bd*** 2.2004
 */
bool CxImage::Resample2(
  long newx, long newy, 
  InterpolationMethod const inMethod, 
  OverflowMethod const ofMethod, 
  CxImage* const iDst,
  bool const disableAveraging)
{
	if (newx<=0 || newy<=0 || !pDib) return false;
	
	if (head.biWidth==newx && head.biHeight==newy) {
		//image already correct size (just copy and return)
		if (iDst) iDst->Copy(*this);
		return true;
	}//if
	
	//calculate scale of new image (less than 1 for enlarge)
	float xScale, yScale;
	xScale = (float)head.biWidth  / (float)newx;    
	yScale = (float)head.biHeight / (float)newy;
	
	//create temporary destination image
	CxImage newImage;
	newImage.CopyInfo(*this);
	newImage.Create(newx,newy,head.biBitCount,GetType());
	newImage.SetPalette(GetPalette());
	if (!newImage.IsValid()){
		strcpy(info.szLastError,newImage.GetLastError());
		return false;
	}
	
	//and alpha channel if required
#if CXIMAGE_SUPPORT_ALPHA
	if (AlphaIsValid()) newImage.AlphaCreate();
	BYTE *pxptra = 0;	// destination alpha data
#endif
	
	float sX, sY;         //source location
	long dX,dY;           //destination pixel (int value)
	if ((xScale<=1 && yScale<=1) || disableAveraging) {
		//image is being enlarged (or interpolation on demand)
		if (!IsIndexed()) {
			//RGB24 image (optimized version with direct writes)
			RGBQUAD q;              //pixel colour
			BYTE *pxptr;            //pointer to destination pixel
			for(dY=0; dY<newy; dY++){
				info.nProgress = (long)(100*dY/newy);
				if (info.nEscape) break;
				sY = (dY + 0.5f) * yScale - 0.5f;
				pxptr=(BYTE*)(newImage.BlindGetPixelPointer(0,dY));
#if CXIMAGE_SUPPORT_ALPHA
				pxptra=newImage.AlphaGetPointer(0,dY);
#endif
				for(dX=0; dX<newx; dX++){
					sX = (dX + 0.5f) * xScale - 0.5f;
					q=GetPixelColorInterpolated(sX,sY,inMethod,ofMethod,0);
					*pxptr++=q.rgbBlue;
					*pxptr++=q.rgbGreen;
					*pxptr++=q.rgbRed;
#if CXIMAGE_SUPPORT_ALPHA
					if (pxptra) *pxptra++=q.rgbReserved;
#endif
				}//for dX
			}//for dY
		} else {
			//enlarge paletted image. Slower method.
			for(dY=0; dY<newy; dY++){
				info.nProgress = (long)(100*dY/newy);
				if (info.nEscape) break;
				sY = (dY + 0.5f) * yScale - 0.5f;
				for(dX=0; dX<newx; dX++){
					sX = (dX + 0.5f) * xScale - 0.5f;
					newImage.SetPixelColor(dX,dY,GetPixelColorInterpolated(sX,sY,inMethod,ofMethod,0),true);
				}//for x
			}//for y
		}//if
	} else {
		//image size is being reduced (averaging enabled)
		for(dY=0; dY<newy; dY++){
			info.nProgress = (long)(100*dY/newy); if (info.nEscape) break;
			sY = (dY+0.5f) * yScale - 0.5f;
			for(dX=0; dX<newx; dX++){
				sX = (dX+0.5f) * xScale - 0.5f;
				newImage.SetPixelColor(dX,dY,GetAreaColorInterpolated(sX, sY, xScale, yScale, inMethod, ofMethod,0),true);
			}//for x
		}//for y
	}//if

#if CXIMAGE_SUPPORT_ALPHA
	if (AlphaIsValid() && pxptra == 0){
		for(long y=0; y<newy; y++){
			dY = (long)(y * yScale);
			for(long x=0; x<newx; x++){
				dX = (long)(x * xScale);
				newImage.AlphaSet(x,y,AlphaGet(dX,dY));
			}
		}
	}
#endif //CXIMAGE_SUPPORT_ALPHA

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -