Ejemplo n.º 1
0
void mexFunction( int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] ) {
  int *ns, ms[3], nDims, d, m, r, s; float *A, *B, p;
  mxClassID id; char type[1024];

  // error checking on arguments
  if(nrhs!=4) mexErrMsgTxt("Four inputs required.");
  if(nlhs > 1) mexErrMsgTxt("One output expected.");
  nDims = mxGetNumberOfDimensions(prhs[1]);
  id = mxGetClassID(prhs[1]);
  ns = (int*) mxGetDimensions(prhs[1]);
  d = (nDims == 3) ? ns[2] : 1;
  m = (ns[0] < ns[1]) ? ns[0] : ns[1];
  if( (nDims!=2 && nDims!=3) || id!=mxSINGLE_CLASS || m<4 )
    mexErrMsgTxt("A must be a 4x4 or bigger 2D or 3D float array.");

  // extract inputs
  if(mxGetString(prhs[0],type,1024))
    mexErrMsgTxt("Failed to get type.");
  A = (float*) mxGetData(prhs[1]);
  p = (float) mxGetScalar(prhs[2]);
  r = (int) mxGetScalar(prhs[2]);
  s = (int) mxGetScalar(prhs[3]);
  if( s<1 ) mexErrMsgTxt("Invalid sampling value s");
  if( r<0 ) mexErrMsgTxt("Invalid radius r");

  // create output array (w/o initializing to 0)
  ms[0]=ns[0]/s; ms[1]=ns[1]/s; ms[2]=d;
  B = (float*) mxMalloc(ms[0]*ms[1]*d*sizeof(float));
  plhs[0] = mxCreateNumericMatrix(0, 0, mxSINGLE_CLASS, mxREAL);
  mxSetData(plhs[0], B); mxSetDimensions(plhs[0],(mwSize*)ms,nDims);

  // perform appropriate type of convolution
  if(!strcmp(type,"convBox")) {
    if(r>=m/2) mexErrMsgTxt("mask larger than image (r too large)");
    convBox( A, B, ns[0], ns[1], d, r, s );
  } else if(!strcmp(type,"convTri")) {
    if(r>=m/2) mexErrMsgTxt("mask larger than image (r too large)");
    convTri( A, B, ns[0], ns[1], d, r, s );
  } else if(!strcmp(type,"conv11")) {
    if( s>2 ) mexErrMsgTxt("conv11 can sample by at most s=2");
    conv11( A, B, ns[0], ns[1], d, r, s );
  } else if(!strcmp(type,"convTri1")) {
    if( s>2 ) mexErrMsgTxt("convTri1 can sample by at most s=2");
    convTri1( A, B, ns[0], ns[1], d, p, s );
  } else if(!strcmp(type,"convMax")) {
    if( s>1 ) mexErrMsgTxt("convMax cannot sample");
    convMax( A, B, ns[0], ns[1], d, r );
  } else {
    mexErrMsgTxt("Invalid type.");
  }
}
Ejemplo n.º 2
0
	//---------------------------------------------------------------------
	FIBITMAP* FreeImageCodec::encode(MemoryDataStreamPtr& input, CodecDataPtr& pData) const
	{
		// Set error handler
		FreeImage_SetOutputMessage(FreeImageSaveErrorHandler);

		FIBITMAP* ret = 0;

		ImageData* pImgData = static_cast< ImageData * >( pData.getPointer() );
		PixelBox src(pImgData->width, pImgData->height, pImgData->depth, pImgData->format, input->getPtr());

		// The required format, which will adjust to the format
		// actually supported by FreeImage.
		PixelFormat requiredFormat = pImgData->format;

		// determine the settings
		FREE_IMAGE_TYPE imageType;
		PixelFormat determiningFormat = pImgData->format;

		switch(determiningFormat)
		{
		case PF_R5G6B5:
		case PF_B5G6R5:
		case PF_R8G8B8:
		case PF_B8G8R8:
		case PF_A8R8G8B8:
		case PF_X8R8G8B8:
		case PF_A8B8G8R8:
		case PF_X8B8G8R8:
		case PF_B8G8R8A8:
		case PF_R8G8B8A8:
		case PF_A4L4:
		case PF_BYTE_LA:
		case PF_R3G3B2:
		case PF_A4R4G4B4:
		case PF_A1R5G5B5:
		case PF_A2R10G10B10:
		case PF_A2B10G10R10:
			// I'd like to be able to use r/g/b masks to get FreeImage to load the data
			// in it's existing format, but that doesn't work, FreeImage needs to have
			// data in RGB[A] (big endian) and BGR[A] (little endian), always.
			if (PixelUtil::hasAlpha(determiningFormat))
			{
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				requiredFormat = PF_BYTE_RGBA;
#else
				requiredFormat = PF_BYTE_BGRA;
#endif
			}
			else
			{
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				requiredFormat = PF_BYTE_RGB;
#else
				requiredFormat = PF_BYTE_BGR;
#endif
			}
			// fall through
		case PF_L8:
		case PF_A8:
			imageType = FIT_BITMAP;
			break;

		case PF_L16:
			imageType = FIT_UINT16;
			break;

		case PF_SHORT_GR:
			requiredFormat = PF_SHORT_RGB;
			// fall through
		case PF_SHORT_RGB:
			imageType = FIT_RGB16;
			break;

		case PF_SHORT_RGBA:
			imageType = FIT_RGBA16;
			break;

		case PF_FLOAT16_R:
			requiredFormat = PF_FLOAT32_R;
			// fall through
		case PF_FLOAT32_R:
			imageType = FIT_FLOAT;
			break;

		case PF_FLOAT16_GR:
		case PF_FLOAT16_RGB:
		case PF_FLOAT32_GR:
			requiredFormat = PF_FLOAT32_RGB;
			// fall through
		case PF_FLOAT32_RGB:
			imageType = FIT_RGBF;
			break;

		case PF_FLOAT16_RGBA:
			requiredFormat = PF_FLOAT32_RGBA;
			// fall through
		case PF_FLOAT32_RGBA:
			imageType = FIT_RGBAF;
			break;

		default:
			OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Invalid image format", "FreeImageCodec::encode");
		};

		// Check support for this image type & bit depth
		if (!FreeImage_FIFSupportsExportType((FREE_IMAGE_FORMAT)mFreeImageType, imageType) ||
			!FreeImage_FIFSupportsExportBPP((FREE_IMAGE_FORMAT)mFreeImageType, (int)PixelUtil::getNumElemBits(requiredFormat)))
		{
			// Ok, need to allocate a fallback
			// Only deal with RGBA -> RGB for now
			switch (requiredFormat)
			{
			case PF_BYTE_RGBA:
				requiredFormat = PF_BYTE_RGB;
				break;
			case PF_BYTE_BGRA:
				requiredFormat = PF_BYTE_BGR;
				break;
			default:
				break;
			};

		}

		bool conversionRequired = false;

		unsigned char* srcData = input->getPtr();

		// Check BPP
		unsigned bpp = static_cast<unsigned>(PixelUtil::getNumElemBits(requiredFormat));
		if (!FreeImage_FIFSupportsExportBPP((FREE_IMAGE_FORMAT)mFreeImageType, (int)bpp))
		{
			if (bpp == 32 && PixelUtil::hasAlpha(pImgData->format) && FreeImage_FIFSupportsExportBPP((FREE_IMAGE_FORMAT)mFreeImageType, 24))
			{
				// drop to 24 bit (lose alpha)
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
				requiredFormat = PF_BYTE_RGB;
#else
				requiredFormat = PF_BYTE_BGR;
#endif
				bpp = 24;
			}
			else if (bpp == 128 && PixelUtil::hasAlpha(pImgData->format) && FreeImage_FIFSupportsExportBPP((FREE_IMAGE_FORMAT)mFreeImageType, 96))
			{
				// drop to 96-bit floating point
				requiredFormat = PF_FLOAT32_RGB;
			}
		}

		PixelBox convBox(pImgData->width, pImgData->height, 1, requiredFormat);
		if (requiredFormat != pImgData->format)
		{
			conversionRequired = true;
			// Allocate memory
			convBox.data = OGRE_ALLOC_T(uchar, convBox.getConsecutiveSize(), MEMCATEGORY_GENERAL);
			// perform conversion and reassign source
			PixelBox src(pImgData->width, pImgData->height, 1, pImgData->format, input->getPtr());
			PixelUtil::bulkPixelConversion(src, convBox);
			srcData = static_cast<unsigned char*>(convBox.data);

		}


		ret = FreeImage_AllocateT(
			imageType, 
			static_cast<int>(pImgData->width), 
			static_cast<int>(pImgData->height), 
			bpp);

		if (!ret)
		{
			if (conversionRequired)
				OGRE_FREE(convBox.data, MEMCATEGORY_GENERAL);

			OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
				"FreeImage_AllocateT failed - possibly out of memory. ", 
				__FUNCTION__);
		}

		if (requiredFormat == PF_L8 || requiredFormat == PF_A8)
		{
			// Must explicitly tell FreeImage that this is greyscale by setting
			// a "grey" palette (otherwise it will save as a normal RGB
			// palettized image).
			FIBITMAP *tmp = FreeImage_ConvertToGreyscale(ret);
			FreeImage_Unload(ret);
			ret = tmp;
		}
		
		size_t dstPitch = FreeImage_GetPitch(ret);
		size_t srcPitch = pImgData->width * PixelUtil::getNumElemBytes(requiredFormat);


		// Copy data, invert scanlines and respect FreeImage pitch
		uchar* pSrc;
		uchar* pDst = FreeImage_GetBits(ret);
		for (size_t y = 0; y < pImgData->height; ++y)
		{
			pSrc = srcData + (pImgData->height - y - 1) * srcPitch;
			memcpy(pDst, pSrc, srcPitch);
			pDst += dstPitch;
		}

		if (conversionRequired)
		{
			// delete temporary conversion area
			OGRE_FREE(convBox.data, MEMCATEGORY_GENERAL);
		}

		return ret;
	}