/// <summary> /// Return a subvolume of this PixelBox. /// </summary> /// <param name="def"> Defines the bounds of the subregion to return </param> /// <returns> A pixel box describing the region and the data in it </returns> /// <remarks> /// This function does not copy any data, it just returns a PixelBox object with a data pointer pointing somewhere inside the data of object. Throws an Exception if def is not fully contained. /// </remarks> public PixelBox GetSubVolume(BasicBox def) { if (Compressed(this.format)) { if (def.Left == left && def.Top == top && def.Front == front && def.Right == right && def.Bottom == bottom && def.Back == back) { // Entire buffer is being queried return(this); } throw new Exception("Cannot return subvolume of compressed PixelBuffer, in PixelBox.GetSubVolume"); } if (!Contains(def)) { throw new Exception("Bounds out of range, in PixelBox.GetSubVolume"); } var elemSize = PixelUtil.GetNumElemBytes(this.format); // Calculate new data origin var rval = new PixelBox(def, this.format, this.data); rval.offset = (((def.Left - left) * elemSize) + ((def.Top - top) * this.rowPitch * elemSize) + ((def.Front - front) * this.slicePitch * elemSize)); rval.rowPitch = this.rowPitch; rval.slicePitch = this.slicePitch; rval.format = this.format; return(rval); }
unsafe private static void B8G8R8toR8G8B8(PixelBox src, PixelBox dst) { Col3b *srcptr = (Col3b *)(src.Data.ToPointer()); Col3b *dstptr = (Col3b *)(dst.Data.ToPointer()); int srcSliceSkip = src.SliceSkip; int dstSliceSkip = dst.SliceSkip; int k = src.Right - src.Left; for (int z = src.Front; z < src.Back; z++) { for (int y = src.Top; y < src.Bottom; y++) { for (int x = 0; x < k; x++) { Col3b inp = srcptr[x]; dstptr[x].x = inp.z; dstptr[x].y = inp.y; dstptr[x].z = inp.x; } srcptr += src.RowPitch; dstptr += dst.RowPitch; } srcptr += srcSliceSkip; dstptr += dstSliceSkip; } }
public static void Convert(PixelBox src, PixelBox dst, IPixelConverter pixelConverter) { { var srcptr = (BufferBase)src.Data.Clone(); var dstptr = (BufferBase)dst.Data.Clone(); var srcSliceSkip = src.SliceSkip; var dstSliceSkip = dst.SliceSkip; var k = src.Right - src.Left; for (var z = src.Front; z < src.Back; z++) { for (var y = src.Top; y < src.Bottom; y++) { for (var x = 0; x < k; x++) { pixelConverter.Convert(srcptr, dstptr, x); } srcptr.Ptr += src.RowPitch * PixelUtil.GetNumElemBytes(src.Format); dstptr.Ptr += dst.RowPitch * PixelUtil.GetNumElemBytes(dst.Format); } srcptr.Ptr += srcSliceSkip; dstptr.Ptr += dstSliceSkip; } } }
unsafe private static void R8G8B8toB8G8R8A8(PixelBox src, PixelBox dst) { Col3b *srcptr = (Col3b *)(src.Data.ToPointer()); uint * dstptr = (uint *)(dst.Data.ToPointer()); int xshift = 8; int yshift = 16; int zshift = 24; int ashift = 0; int srcSliceSkip = src.SliceSkip; int dstSliceSkip = dst.SliceSkip; int k = src.Right - src.Left; for (int z = src.Front; z < src.Back; z++) { for (int y = src.Top; y < src.Bottom; y++) { for (int x = 0; x < k; x++) { Col3b inp = srcptr[x]; #if BIG_ENDIAN dstptr[x] = ((uint)(0xFF << ashift)) | (((uint)inp.x) << xshift) | (((uint)inp.y) << yshift) | (((uint)inp.z) << zshift); #else dstptr[x] = ((uint)(0xFF << ashift)) | (((uint)inp.x) << zshift) | (((uint)inp.y) << yshift) | (((uint)inp.z) << xshift); #endif } srcptr += src.RowPitch; dstptr += dst.RowPitch; } srcptr += srcSliceSkip; dstptr += dstSliceSkip; } }
unsafe private static void A8R8G8B8toB8G8R8(PixelBox src, PixelBox dst) { uint * srcptr = (uint *)(src.Data.ToPointer()); Col3b *dstptr = (Col3b *)(dst.Data.ToPointer()); int srcSliceSkip = src.SliceSkip; int dstSliceSkip = dst.SliceSkip; int k = src.Right - src.Left; for (int z = src.Front; z < src.Back; z++) { for (int y = src.Top; y < src.Bottom; y++) { for (int x = 0; x < k; x++) { uint inp = srcptr[x]; dstptr[x].x = (byte)((inp >> 0) & 0xFF); dstptr[x].y = (byte)((inp >> 8) & 0xFF); dstptr[x].z = (byte)((inp >> 16) & 0xFF); } srcptr += src.RowPitch; dstptr += dst.RowPitch; } srcptr += srcSliceSkip; dstptr += dstSliceSkip; } }
public override void CopyContentsToMemory( PixelBox dst, RenderTarget.FrameBuffer buffer ) { if ( buffer == FrameBuffer.Auto ) buffer = FrameBuffer.Front; if ( buffer != FrameBuffer.Front ) { throw new Exception( "Invalid buffer." ); } pixelBuffer.BlitToMemory( dst ); }
public static bool DoOptimizedConversion(PixelBox src, PixelBox dst) { var conversion = ((int)src.Format << 8) | (int)dst.Format; if (_supportedConversions.ContainsKey(conversion)) { PixelBoxConverter.Convert(src, dst, _supportedConversions[conversion]); return(true); } return(false); }
///<summary> /// Convert consecutive pixels from one format to another. No dithering or filtering is being done. /// Converting from RGB to luminance takes the R channel. In case the source and destination format match, /// just a copy is done. ///</summary> ///<param name="srcBytes">Pointer to source region</param> ///<param name="srcFormat">Pixel format of source region</param> ///<param name="dstBytes">Pointer to destination region</param> ///<param name="dstFormat">Pixel format of destination region</param> public static void BulkPixelConversion(IntPtr srcBytes, int srcOffset, PixelFormat srcFormat, IntPtr dstBytes, int dstOffset, PixelFormat dstFormat, int count) { PixelBox src = new PixelBox(count, 1, 1, srcFormat, srcBytes); src.Offset = srcOffset; PixelBox dst = new PixelBox(count, 1, 1, dstFormat, dstBytes); dst.Offset = dstOffset; BulkPixelConversion(src, dst); }
//----------------------------------------------------------------------- public void ILUtil.FromAxiom(PixelBox src) { // ilTexImage http://openil.sourceforge.net/docs/il/f00059.htm ILFormat ifmt = OgreFormat2ilFormat(src.format); if (src.isConsecutive() && ifmt.isValid()) { // The easy case, the buffer is laid out in memory just like // we want it to be and is in a format DevIL can understand directly // We could even save the copy if DevIL would let us Il.ilTexImage(src.Width, src.Height, src.Depth, ifmt.numberOfChannels, ifmt.format, ifmt.type, src.data); } else if (ifmt.isValid()) { // The format can be understood directly by DevIL. The only // problem is that ilTexImage expects our image data consecutively // so we cannot use that directly. // Let DevIL allocate the memory for us, and copy the data consecutively // to its memory ilTexImage(static_cast <ILuint>(src.getWidth()), static_cast <ILuint>(src.getHeight()), static_cast <ILuint>(src.getDepth()), ifmt.numberOfChannels, ifmt.format, ifmt.type, 0); PixelBox dst(src.getWidth(), src.getHeight(), src.getDepth(), src.format, ilGetData()); PixelUtil::bulkPixelConversion(src, dst); } else { // Here it gets ugly. We're stuck with a pixel format that DevIL // can't do anything with. We will do a bulk pixel conversion and // then feed it to DevIL anyway. The problem is finding the best // format to convert to. // most general format supported by OGRE and DevIL PixelFormat fmt = PixelUtil::hasAlpha(src.format)?PF_FLOAT32_RGBA:PF_FLOAT32_RGB; // Make up a pixel format // We don't have to consider luminance formats as they have // straight conversions to DevIL, just weird permutations of RGBA an LA int depths[4];
/// <summary> /// </summary> public static void Scale(PixelBox src, PixelBox dst, int elementSize) { // assert(src.format == dst.format); // srcdata stays at beginning, pdst is a moving pointer //byte* srcdata = (byte*)src.Data; //byte* pdst = (byte*)dst.Data; var dstOffset = 0; // sx_48,sy_48,sz_48 represent current position in source // using 16/48-bit fixed precision, incremented by steps var stepx = ((ulong)src.Width << 48) / (ulong)dst.Width; var stepy = ((ulong)src.Height << 48) / (ulong)dst.Height; var stepz = ((ulong)src.Depth << 48) / (ulong)dst.Depth; // note: ((stepz>>1) - 1) is an extra half-step increment to adjust // for the center of the destination pixel, not the top-left corner var sz_48 = (stepz >> 1) - 1; for (var z = (uint)dst.Front; z < dst.Back; z++, sz_48 += stepz) { var srczoff = (uint)(sz_48 >> 48) * (uint)src.SlicePitch; var sy_48 = (stepy >> 1) - 1; for (var y = (uint)dst.Top; y < dst.Bottom; y++, sy_48 += stepy) { var srcyoff = (uint)(sy_48 >> 48) * (uint)src.RowPitch; var sx_48 = (stepx >> 1) - 1; for (var x = (uint)dst.Left; x < dst.Right; x++, sx_48 += stepx) { Memory.Copy(src.Data, dst.Data, (int)(elementSize * ((uint)(sx_48 >> 48) + srcyoff + srczoff)), dstOffset, elementSize); dstOffset += elementSize; } dstOffset += elementSize * dst.RowSkip; } dstOffset += elementSize * dst.SliceSkip; } }
/// <summary> /// </summary> public static void Scale( PixelBox src, PixelBox dst, int elementSize ) { // assert(src.format == dst.format); // srcdata stays at beginning, pdst is a moving pointer //byte* srcdata = (byte*)src.Data; //byte* pdst = (byte*)dst.Data; var dstOffset = 0; // sx_48,sy_48,sz_48 represent current position in source // using 16/48-bit fixed precision, incremented by steps var stepx = ( (ulong)src.Width << 48 )/(ulong)dst.Width; var stepy = ( (ulong)src.Height << 48 )/(ulong)dst.Height; var stepz = ( (ulong)src.Depth << 48 )/(ulong)dst.Depth; // note: ((stepz>>1) - 1) is an extra half-step increment to adjust // for the center of the destination pixel, not the top-left corner var sz_48 = ( stepz >> 1 ) - 1; for ( var z = (uint)dst.Front; z < dst.Back; z++, sz_48 += stepz ) { var srczoff = (uint)( sz_48 >> 48 )*(uint)src.SlicePitch; var sy_48 = ( stepy >> 1 ) - 1; for ( var y = (uint)dst.Top; y < dst.Bottom; y++, sy_48 += stepy ) { var srcyoff = (uint)( sy_48 >> 48 )*(uint)src.RowPitch; var sx_48 = ( stepx >> 1 ) - 1; for ( var x = (uint)dst.Left; x < dst.Right; x++, sx_48 += stepx ) { Memory.Copy( src.Data, dst.Data, (int)( elementSize*( (uint)( sx_48 >> 48 ) + srcyoff + srczoff ) ), dstOffset, elementSize ); dstOffset += elementSize; } dstOffset += elementSize*dst.RowSkip; } dstOffset += elementSize*dst.SliceSkip; } }
unsafe private static void L16toL8(PixelBox src, PixelBox dst) { ushort *srcptr = (ushort *)(src.Data.ToPointer()); byte * dstptr = (byte *)(dst.Data.ToPointer()); int srcSliceSkip = src.SliceSkip; int dstSliceSkip = dst.SliceSkip; int k = src.Right - src.Left; for (int z = src.Front; z < src.Back; z++) { for (int y = src.Top; y < src.Bottom; y++) { for (int x = 0; x < k; x++) { ushort inp = srcptr[x]; dstptr[x] = (byte)(inp >> 8); } srcptr += src.RowPitch; dstptr += dst.RowPitch; } srcptr += srcSliceSkip; dstptr += dstSliceSkip; } }
unsafe private static void X8B8G8R8toR8G8B8A8(PixelBox src, PixelBox dst) { uint *srcptr = (uint *)(src.Data.ToPointer()); uint *dstptr = (uint *)(dst.Data.ToPointer()); int srcSliceSkip = src.SliceSkip; int dstSliceSkip = dst.SliceSkip; int k = src.Right - src.Left; for (int z = src.Front; z < src.Back; z++) { for (int y = src.Top; y < src.Bottom; y++) { for (int x = 0; x < k; x++) { uint inp = srcptr[x]; dstptr[x] = ((inp & 0x0000FF) << 24) | ((inp & 0xFF0000) >> 8) | ((inp & 0x00FF00) << 8) | 0x000000FF; } srcptr += src.RowPitch; dstptr += dst.RowPitch; } srcptr += srcSliceSkip; dstptr += dstSliceSkip; } }
unsafe private static void L8toB8G8R8A8(PixelBox src, PixelBox dst) { byte *srcptr = (byte *)(src.Data.ToPointer()); uint *dstptr = (uint *)(dst.Data.ToPointer()); int srcSliceSkip = src.SliceSkip; int dstSliceSkip = dst.SliceSkip; int k = src.Right - src.Left; for (int z = src.Front; z < src.Back; z++) { for (int y = src.Top; y < src.Bottom; y++) { for (int x = 0; x < k; x++) { byte inp = srcptr[x]; dstptr[x] = 0x000000FF | (((uint)inp) << 8) | (((uint)inp) << 16) | (((uint)inp) << 24); } srcptr += src.RowPitch; dstptr += dst.RowPitch; } srcptr += srcSliceSkip; dstptr += dstSliceSkip; } }
protected static System.Drawing.Rectangle ToD3DRectangleExtent( PixelBox lockBox ) { Debug.Assert( lockBox.Depth == 1 ); var r = new System.Drawing.Rectangle(); r.X = 0; r.Width = lockBox.Width; r.X = 0; r.Height = lockBox.Height; return r; }
public void Bind( D3D9.Device dev, D3D9.Volume volume, D3D9.BaseTexture mipTex ) { //Entering critical section LockDeviceAccess(); var bufferResources = GetBufferResources( dev ); var isNewBuffer = false; if ( bufferResources == null ) { bufferResources = new BufferResources(); this.mapDeviceToBufferResources.Add( dev, bufferResources ); isNewBuffer = true; } bufferResources.MipTex = mipTex; bufferResources.Volume = volume; var desc = volume.Description; width = desc.Width; height = desc.Height; depth = desc.Depth; format = D3D9Helper.ConvertEnum( desc.Format ); // Default rowPitch = Width; slicePitch = Height*Width; sizeInBytes = PixelUtil.GetMemorySize( Width, Height, Depth, Format ); if ( isNewBuffer && this.ownerTexture.IsManuallyLoaded ) { foreach ( var it in this.mapDeviceToBufferResources ) { if ( it.Value != bufferResources && it.Value.Volume != null && it.Key.TestCooperativeLevel().Success && dev.TestCooperativeLevel().Success ) { var fullBufferBox = new BasicBox( 0, 0, 0, Width, Height, Depth ); var dstBox = new PixelBox( fullBufferBox, Format ); var data = new byte[sizeInBytes]; using ( var d = BufferBase.Wrap( data ) ) { dstBox.Data = d; BlitToMemory( fullBufferBox, dstBox, it.Value, it.Key ); BlitFromMemory( dstBox, fullBufferBox, bufferResources ); Array.Clear( data, 0, sizeInBytes ); } break; } } } //Leaving critical section UnlockDeviceAccess(); }
public GLESHardwarePixelBuffer( int width, int height, int depth, PixelFormat format, BufferUsage usage ) : base( width, height, depth, format, usage, false, false ) { _buffer = new PixelBox( width, height, depth, format ); _glInternalFormat = 0; }
/// <summary> /// /// </summary> /// <param name="src"></param> /// <param name="dstBox"></param> public override void BlitFromMemory( PixelBox src, Media.BasicBox dstBox ) { if ( !_buffer.Contains( dstBox ) ) { throw new ArgumentOutOfRangeException( "Destination box out of range, GLESHardwarePixelBuffer.BlitToMemory" ); } PixelBox scaled; if ( src.Width != dstBox.Width || src.Height != dstBox.Height || src.Depth != dstBox.Depth ) { LogManager.Instance.Write( "[GLESHardwarePixelBuffer] Scale to destination size." ); // Scale to destination size. Use DevIL and not iluScale because ILU screws up for // floating point textures and cannot cope with 3D images. // This also does pixel format conversion if needed AllocateBuffer(); scaled = _buffer.GetSubVolume( dstBox ); Image.Scale( src, scaled, ImageFilter.Bilinear ); } else if ( ( src.Format != Format ) || ( ( GLESPixelUtil.GetGLOriginFormat( src.Format ) == 0 ) && ( src.Format != PixelFormat.R8G8B8 ) ) ) { LogManager.Instance.Write( "[GLESHardwarePixelBuffer] Extents match, but format is not accepted as valid source format for GL." ); LogManager.Instance.Write( "[GLESHardwarePixelBuffer] Source.Format = {0}, Format = {1}, GLOriginFormat = {2}", src.Format, Format, GLESPixelUtil.GetGLOriginFormat( src.Format ) ); // Extents match, but format is not accepted as valid source format for GL // do conversion in temporary buffer AllocateBuffer(); scaled = _buffer.GetSubVolume( dstBox ); PixelConverter.BulkPixelConversion( src, scaled ); } else { LogManager.Instance.Write( "[GLESHardwarePixelBuffer] No scaling or conversion needed." ); scaled = src; if ( src.Format == PixelFormat.R8G8B8 ) { scaled.Format = PixelFormat.R8G8B8; PixelConverter.BulkPixelConversion( src, scaled ); } // No scaling or conversion needed // Set extents for upload scaled.Left = dstBox.Left; scaled.Right = dstBox.Right; scaled.Top = dstBox.Top; scaled.Bottom = dstBox.Bottom; scaled.Front = dstBox.Front; scaled.Back = dstBox.Back; } Upload( scaled, dstBox ); FreeBuffer(); }
/// <summary> /// /// </summary> /// <param name="data"></param> protected virtual void Download( PixelBox data ) { throw new AxiomException( "Download not possible for this pixelbuffer type" ); }
public abstract void CopyContentsToMemory(PixelBox pb, FrameBuffer buffer);
public static bool DoOptimizedConversion(PixelBox src, PixelBox dst) { switch (((int)src.Format << 8) + (int)dst.Format) { case ((int)PixelFormat.A8R8G8B8 << 8) + (int)PixelFormat.A8B8G8R8: A8R8G8B8toA8B8G8R8(src, dst); break; case ((int)PixelFormat.A8R8G8B8 << 8) + (int)PixelFormat.B8G8R8A8: A8R8G8B8toB8G8R8A8(src, dst); break; case ((int)PixelFormat.A8R8G8B8 << 8) + (int)PixelFormat.R8G8B8A8: A8R8G8B8toR8G8B8A8(src, dst); break; case ((int)PixelFormat.A8B8G8R8 << 8) + (int)PixelFormat.A8R8G8B8: A8B8G8R8toA8R8G8B8(src, dst); break; case ((int)PixelFormat.A8B8G8R8 << 8) + (int)PixelFormat.B8G8R8A8: A8B8G8R8toB8G8R8A8(src, dst); break; case ((int)PixelFormat.A8B8G8R8 << 8) + (int)PixelFormat.R8G8B8A8: A8B8G8R8toR8G8B8A8(src, dst); break; case ((int)PixelFormat.B8G8R8A8 << 8) + (int)PixelFormat.A8R8G8B8: B8G8R8A8toA8R8G8B8(src, dst); break; case ((int)PixelFormat.B8G8R8A8 << 8) + (int)PixelFormat.A8B8G8R8: B8G8R8A8toA8B8G8R8(src, dst); break; case ((int)PixelFormat.B8G8R8A8 << 8) + (int)PixelFormat.R8G8B8A8: B8G8R8A8toR8G8B8A8(src, dst); break; //case ((int)PixelFormat.R8G8B8A8 << 8) + (int)PixelFormat.A8R8G8B8: // R8G8B8A8toA8R8G8B8(src, dst); // break; case ((int)PixelFormat.R8G8B8A8 << 8) + (int)PixelFormat.A8B8G8R8: R8G8B8A8toA8B8G8R8(src, dst); break; case ((int)PixelFormat.R8G8B8A8 << 8) + (int)PixelFormat.B8G8R8A8: R8G8B8A8toB8G8R8A8(src, dst); break; case ((int)PixelFormat.A8B8G8R8 << 8) + (int)PixelFormat.L8: A8B8G8R8toL8(src, dst); break; case ((int)PixelFormat.L8 << 8) + (int)PixelFormat.A8B8G8R8: L8toA8B8G8R8(src, dst); break; case ((int)PixelFormat.A8R8G8B8 << 8) + (int)PixelFormat.L8: A8R8G8B8toL8(src, dst); break; case ((int)PixelFormat.L8 << 8) + (int)PixelFormat.A8R8G8B8: L8toA8R8G8B8(src, dst); break; case ((int)PixelFormat.B8G8R8A8 << 8) + (int)PixelFormat.L8: B8G8R8A8toL8(src, dst); break; case ((int)PixelFormat.L8 << 8) + (int)PixelFormat.B8G8R8A8: L8toB8G8R8A8(src, dst); break; case ((int)PixelFormat.L8 << 8) + (int)PixelFormat.L16: L8toL16(src, dst); break; case ((int)PixelFormat.L16 << 8) + (int)PixelFormat.L8: L16toL8(src, dst); break; case ((int)PixelFormat.B8G8R8 << 8) + (int)PixelFormat.R8G8B8: B8G8R8toR8G8B8(src, dst); break; case ((int)PixelFormat.R8G8B8 << 8) + (int)PixelFormat.B8G8R8: R8G8B8toB8G8R8(src, dst); break; case ((int)PixelFormat.R8G8B8 << 8) + (int)PixelFormat.A8R8G8B8: R8G8B8toA8R8G8B8(src, dst); break; case ((int)PixelFormat.B8G8R8 << 8) + (int)PixelFormat.A8R8G8B8: B8G8R8toA8R8G8B8(src, dst); break; case ((int)PixelFormat.R8G8B8 << 8) + (int)PixelFormat.A8B8G8R8: R8G8B8toA8B8G8R8(src, dst); break; case ((int)PixelFormat.B8G8R8 << 8) + (int)PixelFormat.A8B8G8R8: B8G8R8toA8B8G8R8(src, dst); break; case ((int)PixelFormat.R8G8B8 << 8) + (int)PixelFormat.B8G8R8A8: R8G8B8toB8G8R8A8(src, dst); break; case ((int)PixelFormat.B8G8R8 << 8) + (int)PixelFormat.B8G8R8A8: B8G8R8toB8G8R8A8(src, dst); break; case ((int)PixelFormat.A8R8G8B8 << 8) + (int)PixelFormat.R8G8B8: A8R8G8B8toR8G8B8(src, dst); break; case ((int)PixelFormat.A8R8G8B8 << 8) + (int)PixelFormat.B8G8R8: A8R8G8B8toB8G8R8(src, dst); break; case ((int)PixelFormat.X8R8G8B8 << 8) + (int)PixelFormat.A8R8G8B8: X8R8G8B8toA8R8G8B8(src, dst); break; case ((int)PixelFormat.X8R8G8B8 << 8) + (int)PixelFormat.A8B8G8R8: X8R8G8B8toA8B8G8R8(src, dst); break; case ((int)PixelFormat.X8R8G8B8 << 8) + (int)PixelFormat.B8G8R8A8: X8R8G8B8toB8G8R8A8(src, dst); break; case ((int)PixelFormat.X8R8G8B8 << 8) + (int)PixelFormat.R8G8B8A8: X8R8G8B8toR8G8B8A8(src, dst); break; case ((int)PixelFormat.X8B8G8R8 << 8) + (int)PixelFormat.A8R8G8B8: X8B8G8R8toA8R8G8B8(src, dst); break; case ((int)PixelFormat.X8B8G8R8 << 8) + (int)PixelFormat.A8B8G8R8: X8B8G8R8toA8B8G8R8(src, dst); break; case ((int)PixelFormat.X8B8G8R8 << 8) + (int)PixelFormat.B8G8R8A8: X8B8G8R8toB8G8R8A8(src, dst); break; case ((int)PixelFormat.X8B8G8R8 << 8) + (int)PixelFormat.R8G8B8A8: X8B8G8R8toR8G8B8A8(src, dst); break; default: return(false); } return(true); }
//----------------------------------------------------------------------- public static void ToAxiom(PixelBox dst) { if (!dst.Consecutive) { throw new NotImplementedException("Destination must currently be consecutive"); } if (dst.Width != Il.ilGetInteger(Il.IL_IMAGE_WIDTH) || dst.Height != Il.ilGetInteger(Il.IL_IMAGE_HEIGHT) || dst.Depth != Il.ilGetInteger(Il.IL_IMAGE_DEPTH)) { throw new AxiomException("Destination dimensions must equal IL dimension"); } int ilfmt = Il.ilGetInteger(Il.IL_IMAGE_FORMAT); int iltp = Il.ilGetInteger(Il.IL_IMAGE_TYPE); // Check if in-memory format just matches // If yes, we can just copy it and save conversion ILFormat ifmt = ILUtil.ConvertToILFormat(dst.Format); if (ifmt.format == ilfmt && ILabs(ifmt.type) == ILabs(iltp)) { int size = Il.ilGetInteger(Il.IL_IMAGE_SIZE_OF_DATA); // Copy from the IL structure to our buffer PixelUtil.CopyBytes(dst.Data, dst.Offset, Il.ilGetData(), 0, size); return; } // Try if buffer is in a known OGRE format so we can use OGRE its // conversion routines PixelFormat bufFmt = ILUtil.ConvertFromILFormat(ilfmt, iltp); ifmt = ILUtil.ConvertToILFormat(bufFmt); if (ifmt.format == ilfmt && ILabs(ifmt.type) == ILabs(iltp)) { // IL format matches another OGRE format PixelBox src = new PixelBox(dst.Width, dst.Height, dst.Depth, bufFmt, Il.ilGetData()); PixelUtil.BulkPixelConversion(src, dst); return; } #if NOT // The extremely slow method if (iltp == Il.IL_UNSIGNED_BYTE || iltp == Il.IL_BYTE) { ilToOgreInternal(static_cast <uint8 *>(dst.data), dst.format, (uint8)0x00, (uint8)0x00, (uint8)0x00, (uint8)0xFF); } else if (iltp == IL_FLOAT) { ilToOgreInternal(static_cast <uint8 *>(dst.data), dst.format, 0.0f, 0.0f, 0.0f, 1.0f); } else if (iltp == IL_SHORT || iltp == IL_UNSIGNED_SHORT) { ilToOgreInternal(static_cast <uint8 *>(dst.data), dst.format, (uint16)0x0000, (uint16)0x0000, (uint16)0x0000, (uint16)0xFFFF); } else { OGRE_EXCEPT(Exception::UNIMPLEMENTED_FEATURE, "Cannot convert this DevIL type", "ILUtil::ilToOgre"); } #else throw new NotImplementedException("Cannot convert this DevIL type"); #endif }
public void Scale(PixelBox src, PixelBox dst) { // assert(src.format == dst.format); // only optimized for 2D if (src.Depth > 1 || dst.Depth > 1) { (new LinearResampler()).Scale(src, dst); return; } #if !AXIOM_SAFE_ONLY unsafe #endif { // srcdata stays at beginning of slice, pdst is a moving pointer var srcdata = src.Data.ToBytePointer(); var dstData = dst.Data.ToBytePointer(); var pdst = 0; // sx_48,sy_48 represent current position in source // using 16/48-bit fixed precision, incremented by steps var stepx = (UInt64)((src.Width << 48) / dst.Width); var stepy = (UInt64)((src.Height << 48) / dst.Height); // bottom 28 bits of temp are 16/12 bit fixed precision, used to // adjust a source coordinate backwards by half a pixel so that the // integer bits represent the first sample (eg, sx1) and the // fractional bits are the blend weight of the second sample uint temp; var sy_48 = (stepy >> 1) - 1; for (var y = (uint)dst.Top; y < dst.Bottom; y++, sy_48 += stepy) { temp = (uint)(sy_48 >> 36); temp = (temp > 0x800) ? temp - 0x800 : 0; var syf = temp & 0xFFF; var sy1 = temp >> 12; var sy2 = (uint)System.Math.Min(sy1 + 1, src.Bottom - src.Top - 1); var syoff1 = (uint)(sy1 * src.RowPitch); var syoff2 = (uint)(sy2 * src.RowPitch); var sx_48 = (stepx >> 1) - 1; for (var x = (uint)dst.Left; x < dst.Right; x++, sx_48 += stepx) { temp = (uint)(sx_48 >> 36); temp = (temp > 0x800) ? temp - 0x800 : 0; var sxf = temp & 0xFFF; var sx1 = temp >> 12; var sx2 = (uint)System.Math.Min(sx1 + 1, src.Right - src.Left - 1); var sxfsyf = sxf * syf; for (uint k = 0; k < this._channels; k++) { var accum = (uint) (srcdata[(int)((sx1 + syoff1) * this._channels + k)] * (char)(0x1000000 - (sxf << 12) - (syf << 12) + sxfsyf) + srcdata[(int)((sx2 + syoff1) * this._channels + k)] * (char)((sxf << 12) - sxfsyf) + srcdata[(int)((sx1 + syoff2) * this._channels + k)] * (char)((syf << 12) - sxfsyf) + srcdata[(int)((sx2 + syoff2) * this._channels + k)] * (char)sxfsyf); // accum is computed using 8/24-bit fixed-point math // (maximum is 0xFF000000; rounding will not cause overflow) dstData[pdst++] = (byte)((accum + 0x800000) >> 24); } } pdst += this._channels * dst.RowSkip; } } }
private void Unpack(ref ColorEx dst, int x, int y, int z, PixelFormat format, BufferBase src, PixelBox srcbox, int elemsize) { var data = src + (elemsize * ((x) + (y) * srcbox.RowPitch + (z) * srcbox.SlicePitch)); dst = PixelConverter.UnpackColor(format, data); }
protected PixelBox LockBuffer( BufferResources bufferResources, BasicBox lockBox, D3D9.LockFlags flags ) { // Set extents and format // Note that we do not carry over the left/top/front here, since the returned // PixelBox will be re-based from the locking point onwards var rval = new PixelBox( lockBox.Width, lockBox.Height, lockBox.Depth, Format ); if ( bufferResources.Surface != null ) { //Surface DX.DataRectangle lrect; // Filled in by D3D if ( lockBox.Left == 0 && lockBox.Top == 0 && lockBox.Right == Width && lockBox.Bottom == Height ) { // Lock whole surface lrect = bufferResources.Surface.LockRectangle( flags ); } else { var prect = ToD3DRectangle( lockBox ); lrect = bufferResources.Surface.LockRectangle( prect, flags ); } FromD3DLock( rval, lrect ); } else if ( bufferResources.Volume != null ) { // Volume var pbox = ToD3DBox( lockBox ); // specify range to lock var lbox = bufferResources.Volume.LockBox( pbox, flags ); FromD3DLock( rval, lbox ); } return rval; }
/// <summary> /// </summary> /// <param name="src"> </param> /// <param name="temp"> </param> public static void Scale(PixelBox src, PixelBox temp) { Scale(src, temp, PixelUtil.GetNumElemBytes(src.Format)); }
protected void BlitFromMemory( PixelBox src, BasicBox dstBox, BufferResources dstBufferResources ) { // for scoped deletion of conversion buffer var converted = src; var bufSize = 0; // convert to pixelbuffer's native format if necessary if ( D3D9Helper.ConvertEnum( src.Format ) == D3D9.Format.Unknown ) { bufSize = PixelUtil.GetMemorySize( src.Width, src.Height, src.Depth, Format ); var newBuffer = new byte[bufSize]; using ( var data = BufferBase.Wrap( newBuffer ) ) { converted = new PixelBox( src.Width, src.Height, src.Depth, Format, data ); } PixelConverter.BulkPixelConversion( src, converted ); } int rowWidth = 0; if ( PixelUtil.IsCompressed( converted.Format ) ) { rowWidth = converted.RowPitch/4; // D3D wants the width of one row of cells in bytes if ( converted.Format == PixelFormat.DXT1 ) { // 64 bits (8 bytes) per 4x4 block rowWidth *= 8; } else { // 128 bits (16 bytes) per 4x4 block rowWidth *= 16; } } else { rowWidth = converted.RowPitch*PixelUtil.GetNumElemBytes( converted.Format ); } if ( dstBufferResources.Surface != null ) { var srcRect = ToD3DRectangle( converted ); var destRect = ToD3DRectangle( dstBox ); bufSize = PixelUtil.GetMemorySize( converted.Width, converted.Height, converted.Depth, converted.Format ); var data = new byte[bufSize]; using ( var dest = BufferBase.Wrap( data ) ) { Memory.Copy( converted.Data, dest, bufSize ); } try { D3D9.Surface.FromMemory( dstBufferResources.Surface, data, D3D9.Filter.Default, 0, D3D9Helper.ConvertEnum( converted.Format ), rowWidth, srcRect, destRect ); } catch ( Exception e ) { throw new AxiomException( "D3D9.Surface.FromMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e ); } } else if ( dstBufferResources.Volume != null ) { var srcBox = ToD3DBox( converted ); var destBox = ToD3DBox( dstBox ); var sliceWidth = 0; if ( PixelUtil.IsCompressed( converted.Format ) ) { sliceWidth = converted.SlicePitch/16; // D3D wants the width of one slice of cells in bytes if ( converted.Format == PixelFormat.DXT1 ) { // 64 bits (8 bytes) per 4x4 block sliceWidth *= 8; } else { // 128 bits (16 bytes) per 4x4 block sliceWidth *= 16; } } else { sliceWidth = converted.SlicePitch*PixelUtil.GetNumElemBytes( converted.Format ); } bufSize = PixelUtil.GetMemorySize( converted.Width, converted.Height, converted.Depth, converted.Format ); var data = new byte[ bufSize ]; using ( var dest = BufferBase.Wrap( data ) ) { Memory.Copy( converted.Data, dest, bufSize ); } try { using ( var srcData = BufferBase.Wrap( data ) ) { var srcMemoryPtr = new IntPtr( srcData.Ptr ); dstBufferResources.Volume.LoadFromMemory( null, destBox, srcMemoryPtr, D3D9Helper.ConvertEnum( converted.Format ), rowWidth, slicePitch, null, srcBox, D3D9.Filter.Default, 0 ); } } catch ( Exception e ) { throw new AxiomException( "D3D9.Volume.FromFileInMemory failed in D3D9HardwarePixelBuffer.BlitFromMemory", e ); } } if ( this.doMipmapGen ) { GenMipmaps( dstBufferResources.MipTex ); } }
static public void ConvertFromIL( PixelBox dst ) { if ( !dst.IsConsecutive ) throw new Exception( "Destination must currently be consecutive" ); if ( dst.Width != Il.ilGetInteger( Il.IL_IMAGE_WIDTH ) || dst.Height != Il.ilGetInteger( Il.IL_IMAGE_HEIGHT ) || dst.Depth != Il.ilGetInteger( Il.IL_IMAGE_DEPTH ) ) throw new Exception( "Destination dimensions must equal IL dimension" ); int ilfmt = Il.ilGetInteger( Il.IL_IMAGE_FORMAT ); int iltp = Il.ilGetInteger( Il.IL_IMAGE_TYPE ); // Check if in-memory format just matches // If yes, we can just copy it and save conversion ILFormat ifmt = Convert( dst.Format ); if ( ifmt.Format == ilfmt && ILabs( ifmt.Type ) == ILabs( iltp ) ) { Memory.Copy( Il.ilGetData(), dst.Data, Il.ilGetInteger( Il.IL_IMAGE_SIZE_OF_DATA ) ); return; } // Try if buffer is in a known Axiom format so we can use its conversion routines PixelFormat bufFmt = Convert( (int)ilfmt, (int)iltp ); ifmt = Convert( bufFmt ); if ( ifmt.Format == ilfmt && ILabs( ifmt.Type ) == ILabs( iltp ) ) { // IL format matches another Axiom format PixelBox src = new PixelBox( dst.Width, dst.Height, dst.Depth, bufFmt, Il.ilGetData() ); PixelConverter.BulkPixelConversion( src, dst ); return; } // Thee extremely slow method if ( iltp == Il.IL_UNSIGNED_BYTE || iltp == Il.IL_BYTE ) { throw new NotImplementedException( "Cannot convert this DevIL type." ); //ilToOgreInternal( static_cast<uint8*>( dst.data ), dst.format, (uint8)0x00, (uint8)0x00, (uint8)0x00, (uint8)0xFF ); } else if ( iltp == Il.IL_FLOAT ) { throw new NotImplementedException( "Cannot convert this DevIL type." ); //ilToOgreInternal( static_cast<uint8*>( dst.data ), dst.format, 0.0f, 0.0f, 0.0f, 1.0f ); } else if ( iltp == Il.IL_SHORT || iltp == Il.IL_UNSIGNED_SHORT ) { throw new NotImplementedException( "Cannot convert this DevIL type." ); //ilToOgreInternal( static_cast<uint8*>( dst.data ), dst.format, (uint16)0x0000, (uint16)0x0000, (uint16)0x0000, (uint16)0xFFFF ); } else { throw new Exception( "Cannot convert this DevIL type." ); } }
public void CopyContentsToMemory(PixelBox pb) { CopyContentsToMemory(pb, FrameBuffer.Auto); }
static public void ConvertToIL( PixelBox src ) { // ilTexImage http://openil.sourceforge.net/docs/il/f00059.htm ILFormat ifmt = Convert( src.Format ); if ( src.IsConsecutive && ifmt.IsValid ) { // The easy case, the buffer is laid out in memory just like // we want it to be and is in a format DevIL can understand directly // We could even save the copy if DevIL would let us Il.ilTexImage( src.Width, src.Height, src.Depth, (byte)ifmt.Channels, ifmt.Format, ifmt.Type, src.Data ); } else if ( ifmt.IsValid ) { // The format can be understood directly by DevIL. The only // problem is that ilTexImage expects our image data consecutively // so we cannot use that directly. // Let DevIL allocate the memory for us, and copy the data consecutively // to its memory Il.ilTexImage( src.Width, src.Height, src.Depth, (byte)ifmt.Channels, ifmt.Format, ifmt.Type, IntPtr.Zero ); PixelBox dst = new PixelBox( src.Width, src.Height, src.Depth, src.Format, Il.ilGetData() ); PixelConverter.BulkPixelConversion( src, dst ); } else { // Here it gets ugly. We're stuck with a pixel format that DevIL // can't do anything with. We will do a bulk pixel conversion and // then feed it to DevIL anyway. The problem is finding the best // format to convert to. // most general format supported by Axiom and DevIL PixelFormat fmt = PixelUtil.HasAlpha( src.Format ) ? PixelFormat.FLOAT32_RGBA : PixelFormat.FLOAT32_RGB; // Make up a pixel format // We don't have to consider luminance formats as they have // straight conversions to DevIL, just weird permutations of RGBA an LA int[] depths = PixelUtil.GetBitDepths( src.Format ); // Native endian format with all bit depths<8 can safely and quickly be // converted to 24/32 bit if ( PixelUtil.IsNativeEndian( src.Format ) && depths[ 0 ] <= 8 && depths[ 1 ] <= 8 && depths[ 2 ] <= 8 && depths[ 3 ] <= 8 ) { if ( PixelUtil.HasAlpha( src.Format ) ) { fmt = PixelFormat.A8R8G8B8; } else { fmt = PixelFormat.R8G8B8; } } // Let DevIL allocate the memory for us, then do the conversion ourselves ifmt = Convert( fmt ); Il.ilTexImage( src.Width, src.Height, src.Depth, (byte)ifmt.Channels, ifmt.Format, ifmt.Type, IntPtr.Zero ); // TAO 2.0 //Il.ilTexImage( src.Width, src.Height, src.Depth, (byte)ifmt.Channels, ifmt.Format, ifmt.Type, null ); IntPtr data = Il.ilGetData(); PixelBox dst = new PixelBox( src.Width, src.Height, src.Depth, fmt, data ); PixelConverter.BulkPixelConversion( src, dst ); } }
/// <summary> /// /// </summary> /// <param name="data"></param> /// <param name="dest"></param> protected virtual void Upload( PixelBox data, BasicBox dest ) { throw new AxiomException( "Upload not possible for this pixelbuffer type" ); }
public void WriteContentsToFile( string fileName ) { var pf = SuggestPixelFormat(); var data = new byte[Width*Height*PixelUtil.GetNumElemBytes( pf )]; var buf = BufferBase.Wrap( data ); var pb = new PixelBox( Width, Height, 1, pf, buf ); CopyContentsToMemory( pb ); ( new Image() ).FromDynamicImage( data, Width, Height, 1, pf, false, 1, 0 ).Save( fileName ); buf.Dispose(); }
/// <summary> /// /// </summary> /// <param name="srcBox"></param> /// <param name="dst"></param> public override void BlitToMemory( BasicBox srcBox, PixelBox dst ) { if ( !_buffer.Contains( srcBox ) ) { throw new ArgumentOutOfRangeException( "source boux out of range" ); } if ( srcBox.Left == 0 && srcBox.Right == Width && srcBox.Top == 0 && srcBox.Bottom == Height && srcBox.Front == 0 && srcBox.Back == Depth && dst.Width == Width && dst.Height == Height && dst.Depth == Depth && GLESPixelUtil.GetGLOriginFormat( dst.Format ) != 0 ) { // The direct case: the user wants the entire texture in a format supported by GL // so we don't need an intermediate buffer Download( dst ); } else { // Use buffer for intermediate copy AllocateBuffer(); //download entire buffer Download( _buffer ); if ( srcBox.Width != dst.Width || srcBox.Height != dst.Height || srcBox.Depth != dst.Depth ) { // we need scaling Image.Scale( _buffer.GetSubVolume( srcBox ), dst, ImageFilter.Bilinear ); } else { // Just copy the bit that we need PixelConverter.BulkPixelConversion( _buffer.GetSubVolume( srcBox ), dst ); } FreeBuffer(); } }
protected void BlitToMemory( BasicBox srcBox, PixelBox dst, BufferResources srcBufferResources, D3D9.Device d3d9Device ) { // Decide on pixel format of temp surface PixelFormat tmpFormat = Format; if ( D3D9Helper.ConvertEnum( dst.Format ) != D3D9.Format.Unknown ) { tmpFormat = dst.Format; } if ( srcBufferResources.Surface != null ) { Debug.Assert( srcBox.Depth == 1 && dst.Depth == 1 ); var srcDesc = srcBufferResources.Surface.Description; var temppool = D3D9.Pool.Scratch; // if we're going to try to use GetRenderTargetData, need to use system mem pool var tryGetRenderTargetData = false; if ( ( ( srcDesc.Usage & D3D9.Usage.RenderTarget ) != 0 ) && ( srcBox.Width == dst.Width ) && ( srcBox.Height == dst.Height ) && ( srcBox.Width == Width ) && ( srcBox.Height == Height ) && ( Format == tmpFormat ) ) { tryGetRenderTargetData = true; temppool = D3D9.Pool.SystemMemory; } // Create temp texture var tmp = new D3D9.Texture( d3d9Device, dst.Width, dst.Height, 1, // 1 mip level ie topmost, generate no mipmaps 0, D3D9Helper.ConvertEnum( tmpFormat ), temppool ); var surface = tmp.GetSurfaceLevel( 0 ); // Copy texture to this temp surface var srcRect = ToD3DRectangle( srcBox ); var destRect = ToD3DRectangle( dst ); // Get the real temp surface format var dstDesc = surface.Description; tmpFormat = D3D9Helper.ConvertEnum( dstDesc.Format ); // Use fast GetRenderTargetData if we are in its usage conditions var fastLoadSuccess = false; if ( tryGetRenderTargetData ) { var result = d3d9Device.GetRenderTargetData( srcBufferResources.Surface, surface ); fastLoadSuccess = result.Success; } if ( !fastLoadSuccess ) { var res = D3D9.Surface.FromSurface( surface, srcBufferResources.Surface, D3D9.Filter.Default, 0, srcRect, destRect ); if ( res.Failure ) { surface.SafeDispose(); tmp.SafeDispose(); throw new AxiomException( "D3D9.Surface.FromSurface failed in D3D9HardwarePixelBuffer.BlitToMemory" ); } } // Lock temp surface and copy it to memory var lrect = surface.LockRectangle( D3D9.LockFlags.ReadOnly ); // Copy it var locked = new PixelBox( dst.Width, dst.Height, dst.Depth, tmpFormat ); FromD3DLock( locked, lrect ); PixelConverter.BulkPixelConversion( locked, dst ); surface.UnlockRectangle(); // Release temporary surface and texture surface.SafeDispose(); tmp.SafeDispose(); } else if ( srcBufferResources.Volume != null ) { // Create temp texture var tmp = new D3D9.VolumeTexture( d3d9Device, dst.Width, dst.Height, dst.Depth, 0, 0, D3D9Helper.ConvertEnum( tmpFormat ), D3D9.Pool.Scratch ); var surface = tmp.GetVolumeLevel( 0 ); // Volume var ddestBox = ToD3DBoxExtent( dst ); var dsrcBox = ToD3DBox( srcBox ); var res = D3D9.Volume.FromVolume( surface, srcBufferResources.Volume, D3D9.Filter.Default, 0, dsrcBox, ddestBox ); if ( res.Failure ) { surface.SafeDispose(); tmp.SafeDispose(); throw new AxiomException( "D3D9.Surface.FromVolume failed in D3D9HardwarePixelBuffer.BlitToMemory" ); } // Lock temp surface and copy it to memory var lbox = surface.LockBox( D3D9.LockFlags.ReadOnly ); // Filled in by D3D // Copy it var locked = new PixelBox( dst.Width, dst.Height, dst.Depth, tmpFormat ); FromD3DLock( locked, lbox ); PixelConverter.BulkPixelConversion( locked, dst ); surface.UnlockBox(); // Release temporary surface and texture surface.SafeDispose(); tmp.SafeDispose(); } }
/// <summary> /// Called to destroy this buffer. /// </summary> protected override void dispose( bool disposeManagedResources ) { if ( !IsDisposed ) { if ( disposeManagedResources ) { if ( data != null ) { Memory.UnpinObject( data ); data = null; _buffer.Data = IntPtr.Zero; _buffer = null; } } } // If it is available, make the call to the // base class's Dispose(Boolean) method base.dispose( disposeManagedResources ); }
public override void EncodeToFile( Stream input, string outFileName, Codec.CodecData codecData ) { int imageID; // create and bind a new image Il.ilGenImages( 1, out imageID ); Il.ilBindImage( imageID ); var buffer = new byte[input.Length]; input.Read( buffer, 0, buffer.Length ); var imgData = (ImageData)codecData; PixelBox src; using ( var bufHandle = BufferBase.Wrap( buffer ) ) { src = new PixelBox( imgData.width, imgData.height, imgData.depth, imgData.format, bufHandle ); } try { // Convert image from Axiom to current IL image ILUtil.ConvertToIL( src ); } catch ( Exception ex ) { LogManager.Instance.Write( "IL Failed image conversion :", ex.Message ); } // flip the image Ilu.iluFlipImage(); // save the image to file Il.ilSaveImage( outFileName ); var error = Il.ilGetError(); if ( error != Il.IL_NO_ERROR ) { LogManager.Instance.Write( "IL Error, could not save file: {0} : {1}", outFileName, Ilu.iluErrorString( error ) ); } Il.ilDeleteImages( 1, ref imageID ); }
public override object Decode(Stream input, Stream output, params object[] args) { ImageData data = new ImageData(); int imageID; int format, bytesPerPixel, imageType; // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); // Put it right side up Il.ilEnable(Il.IL_ORIGIN_SET); Il.ilSetInteger(Il.IL_ORIGIN_MODE, Il.IL_ORIGIN_UPPER_LEFT); // Keep DXTC(compressed) data if present Il.ilSetInteger(Il.IL_KEEP_DXTC_DATA, Il.IL_TRUE); // create a temp buffer and write the stream into it byte[] buffer = new byte[input.Length]; input.Read(buffer, 0, buffer.Length); // load the data into DevIL Il.ilLoadL(this.ILType, buffer, buffer.Length); // check for an error int ilError = Il.ilGetError(); if(ilError != Il.IL_NO_ERROR) { throw new AxiomException("Error while decoding image data: '{0}'", Ilu.iluErrorString(ilError)); } format = Il.ilGetInteger(Il.IL_IMAGE_FORMAT); imageType = Il.ilGetInteger(Il.IL_IMAGE_TYPE); //bytesPerPixel = Math.Max(Il.ilGetInteger(Il.IL_IMAGE_BPC), // Il.ilGetInteger(Il.IL_IMAGE_BYTES_PER_PIXEL)); // Convert image if ImageType is incompatible with us (double or long) if (imageType != Il.IL_BYTE && imageType != Il.IL_UNSIGNED_BYTE && imageType != Il.IL_FLOAT && imageType != Il.IL_UNSIGNED_SHORT && imageType != Il.IL_SHORT) { Il.ilConvertImage(format, Il.IL_FLOAT); imageType = Il.IL_FLOAT; } // Converted paletted images if (format == Il.IL_COLOUR_INDEX) { Il.ilConvertImage(Il.IL_BGRA, Il.IL_UNSIGNED_BYTE); format = Il.IL_BGRA; imageType = Il.IL_UNSIGNED_BYTE; } bytesPerPixel = Il.ilGetInteger(Il.IL_IMAGE_BYTES_PER_PIXEL); // populate the image data data.format = ILUtil.ConvertFromILFormat(format, imageType); data.width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); data.height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); data.depth = Il.ilGetInteger(Il.IL_IMAGE_DEPTH); data.numMipMaps = Il.ilGetInteger(Il.IL_NUM_MIPMAPS); data.flags = 0; if (data.format == PixelFormat.Unknown) { Il.ilDeleteImages(1, ref imageID); throw new AxiomException("Unsupported DevIL format: ImageFormat = {0:x} ImageType = {1:x}", format, imageType); } // Check for cubemap // int cubeflags = Il.ilGetInteger(Il.IL_IMAGE_CUBEFLAGS); int numFaces = Il.ilGetInteger(Il.IL_NUM_IMAGES) + 1; if (numFaces == 6) data.flags |= ImageFlags.CubeMap; else numFaces = 1; // Support only 1 or 6 face images for now // Keep DXT data (if present at all and the GPU supports it) int dxtFormat = Il.ilGetInteger(Il.IL_DXTC_DATA_FORMAT); if (dxtFormat != Il.IL_DXT_NO_COMP && Root.Instance.RenderSystem.Caps.CheckCap(Axiom.Graphics.Capabilities.TextureCompressionDXT)) { data.format = ILUtil.ConvertFromILFormat(dxtFormat, imageType); data.flags |= ImageFlags.Compressed; // Validate that this devil version saves DXT mipmaps if (data.numMipMaps > 0) { Il.ilBindImage(imageID); Il.ilActiveMipmap(1); if (Il.ilGetInteger(Il.IL_DXTC_DATA_FORMAT) != dxtFormat) { data.numMipMaps = 0; LogManager.Instance.Write("Warning: Custom mipmaps for compressed image were ignored because they are not loaded by this DevIL version"); } } } // Calculate total size from number of mipmaps, faces and size data.size = Image.CalculateSize(data.numMipMaps, numFaces, data.width, data.height, data.depth, data.format); // set up buffer for the decoded data buffer = new byte[data.size]; // Pin the buffer, so we can use our PixelBox methods on it GCHandle bufGCHandle = new GCHandle(); bufGCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned); IntPtr bufPtr = bufGCHandle.AddrOfPinnedObject(); int offset = 0; // Dimensions of current mipmap int width = data.width; int height = data.height; int depth = data.depth; // Transfer data for (int mip=0; mip <= data.numMipMaps; ++mip) { for (int i = 0; i < numFaces; ++i) { Il.ilBindImage(imageID); if (numFaces > 1) Il.ilActiveImage(i); if (data.numMipMaps > 0) Il.ilActiveMipmap(mip); /// Size of this face int imageSize = PixelUtil.GetMemorySize(width, height, depth, data.format); if ((data.flags & ImageFlags.Compressed) != 0) { // Compare DXT size returned by DevIL with our idea of the compressed size if (imageSize == Il.ilGetDXTCData(IntPtr.Zero, 0, dxtFormat)) { // Retrieve data from DevIL byte[] tmpBuffer = new byte[imageSize]; Il.ilGetDXTCData(tmpBuffer, imageSize, dxtFormat); // Copy the data into our output buffer Array.Copy(tmpBuffer, 0, buffer, offset, tmpBuffer.Length); } else { LogManager.Instance.Write("Warning: compressed image size mismatch, devilsize={0} oursize={1}", Il.ilGetDXTCData(IntPtr.Zero, 0, dxtFormat), imageSize); } } else { /// Retrieve data from DevIL PixelBox dst = new PixelBox(width, height, depth, data.format, bufPtr); dst.Offset = offset; ILUtil.ToAxiom(dst); } offset += imageSize; } /// Next mip if (width != 1) width /= 2; if (height != 1) height /= 2; if (depth != 1) depth /= 2; } // Restore IL state Il.ilDisable(Il.IL_ORIGIN_SET); Il.ilDisable(Il.IL_FORMAT_SET); // we won't be needing this anymore Il.ilDeleteImages(1, ref imageID); output.Write(buffer, 0, buffer.Length); // Free the buffer we allocated for the conversion. // I used bufPtr to store my data while I converted it. // I need to free it here. This invalidates bufPtr. // My data has already been copied to output. if (bufGCHandle.IsAllocated) bufGCHandle.Free(); return data; }
public override object Decode(Stream input, Stream output, params object[] args) { ImageData data = new ImageData(); int imageID; int format, bytesPerPixel, imageType; // create and bind a new image Il.ilGenImages(1, out imageID); Il.ilBindImage(imageID); // Put it right side up Il.ilEnable(Il.IL_ORIGIN_SET); Il.ilSetInteger(Il.IL_ORIGIN_MODE, Il.IL_ORIGIN_UPPER_LEFT); // Keep DXTC(compressed) data if present Il.ilSetInteger(Il.IL_KEEP_DXTC_DATA, Il.IL_TRUE); // create a temp buffer and write the stream into it byte[] buffer = new byte[input.Length]; input.Read(buffer, 0, buffer.Length); // load the data into DevIL Il.ilLoadL(this.ILType, buffer, buffer.Length); // check for an error int ilError = Il.ilGetError(); if (ilError != Il.IL_NO_ERROR) { throw new AxiomException("Error while decoding image data: '{0}'", Ilu.iluErrorString(ilError)); } format = Il.ilGetInteger(Il.IL_IMAGE_FORMAT); imageType = Il.ilGetInteger(Il.IL_IMAGE_TYPE); //bytesPerPixel = Math.Max(Il.ilGetInteger(Il.IL_IMAGE_BPC), // Il.ilGetInteger(Il.IL_IMAGE_BYTES_PER_PIXEL)); // Convert image if ImageType is incompatible with us (double or long) if (imageType != Il.IL_BYTE && imageType != Il.IL_UNSIGNED_BYTE && imageType != Il.IL_FLOAT && imageType != Il.IL_UNSIGNED_SHORT && imageType != Il.IL_SHORT) { Il.ilConvertImage(format, Il.IL_FLOAT); imageType = Il.IL_FLOAT; } // Converted paletted images if (format == Il.IL_COLOUR_INDEX) { Il.ilConvertImage(Il.IL_BGRA, Il.IL_UNSIGNED_BYTE); format = Il.IL_BGRA; imageType = Il.IL_UNSIGNED_BYTE; } bytesPerPixel = Il.ilGetInteger(Il.IL_IMAGE_BYTES_PER_PIXEL); // populate the image data data.format = ILUtil.ConvertFromILFormat(format, imageType); data.width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); data.height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); data.depth = Il.ilGetInteger(Il.IL_IMAGE_DEPTH); data.numMipMaps = Il.ilGetInteger(Il.IL_NUM_MIPMAPS); data.flags = 0; if (data.format == PixelFormat.Unknown) { Il.ilDeleteImages(1, ref imageID); throw new AxiomException("Unsupported DevIL format: ImageFormat = {0:x} ImageType = {1:x}", format, imageType); } // Check for cubemap // int cubeflags = Il.ilGetInteger(Il.IL_IMAGE_CUBEFLAGS); int numFaces = Il.ilGetInteger(Il.IL_NUM_IMAGES) + 1; if (numFaces == 6) { data.flags |= ImageFlags.CubeMap; } else { numFaces = 1; // Support only 1 or 6 face images for now } // Keep DXT data (if present at all and the GPU supports it) int dxtFormat = Il.ilGetInteger(Il.IL_DXTC_DATA_FORMAT); if (dxtFormat != Il.IL_DXT_NO_COMP && Root.Instance.RenderSystem.Caps.CheckCap(Axiom.Graphics.Capabilities.TextureCompressionDXT)) { data.format = ILUtil.ConvertFromILFormat(dxtFormat, imageType); data.flags |= ImageFlags.Compressed; // Validate that this devil version saves DXT mipmaps if (data.numMipMaps > 0) { Il.ilBindImage(imageID); Il.ilActiveMipmap(1); if (Il.ilGetInteger(Il.IL_DXTC_DATA_FORMAT) != dxtFormat) { data.numMipMaps = 0; LogManager.Instance.Write("Warning: Custom mipmaps for compressed image were ignored because they are not loaded by this DevIL version"); } } } // Calculate total size from number of mipmaps, faces and size data.size = Image.CalculateSize(data.numMipMaps, numFaces, data.width, data.height, data.depth, data.format); // set up buffer for the decoded data buffer = new byte[data.size]; // Pin the buffer, so we can use our PixelBox methods on it GCHandle bufGCHandle = new GCHandle(); bufGCHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned); IntPtr bufPtr = bufGCHandle.AddrOfPinnedObject(); int offset = 0; // Dimensions of current mipmap int width = data.width; int height = data.height; int depth = data.depth; // Transfer data for (int mip = 0; mip <= data.numMipMaps; ++mip) { for (int i = 0; i < numFaces; ++i) { Il.ilBindImage(imageID); if (numFaces > 1) { Il.ilActiveImage(i); } if (data.numMipMaps > 0) { Il.ilActiveMipmap(mip); } /// Size of this face int imageSize = PixelUtil.GetMemorySize(width, height, depth, data.format); if ((data.flags & ImageFlags.Compressed) != 0) { // Compare DXT size returned by DevIL with our idea of the compressed size if (imageSize == Il.ilGetDXTCData(IntPtr.Zero, 0, dxtFormat)) { // Retrieve data from DevIL byte[] tmpBuffer = new byte[imageSize]; Il.ilGetDXTCData(tmpBuffer, imageSize, dxtFormat); // Copy the data into our output buffer Array.Copy(tmpBuffer, 0, buffer, offset, tmpBuffer.Length); } else { LogManager.Instance.Write("Warning: compressed image size mismatch, devilsize={0} oursize={1}", Il.ilGetDXTCData(IntPtr.Zero, 0, dxtFormat), imageSize); } } else { /// Retrieve data from DevIL PixelBox dst = new PixelBox(width, height, depth, data.format, bufPtr); dst.Offset = offset; ILUtil.ToAxiom(dst); } offset += imageSize; } /// Next mip if (width != 1) { width /= 2; } if (height != 1) { height /= 2; } if (depth != 1) { depth /= 2; } } // Restore IL state Il.ilDisable(Il.IL_ORIGIN_SET); Il.ilDisable(Il.IL_FORMAT_SET); // we won't be needing this anymore Il.ilDeleteImages(1, ref imageID); output.Write(buffer, 0, buffer.Length); // Free the buffer we allocated for the conversion. // I used bufPtr to store my data while I converted it. // I need to free it here. This invalidates bufPtr. // My data has already been copied to output. if (bufGCHandle.IsAllocated) { bufGCHandle.Free(); } return(data); }
protected static void FromD3DLock( PixelBox rval, DX.DataBox lbox ) { var bpp = PixelUtil.GetNumElemBytes( rval.Format ); var size = 0; if ( bpp != 0 ) { rval.RowPitch = lbox.RowPitch/bpp; rval.SlicePitch = lbox.SlicePitch/bpp; Debug.Assert( ( lbox.RowPitch%bpp ) == 0 ); Debug.Assert( ( lbox.SlicePitch%bpp ) == 0 ); size = lbox.RowPitch*rval.Height; } else if ( PixelUtil.IsCompressed( rval.Format ) ) { rval.RowPitch = rval.Width; rval.SlicePitch = rval.Width*rval.Height; size = rval.Width*rval.Height; } else { throw new AxiomException( "Invalid pixel format" ); } rval.Data = BufferBase.Wrap( lbox.DataPointer, size ); }
/// <summary> /// /// </summary> /// <param name="src"></param> /// <param name="dst"></param> public void Scale( PixelBox src, PixelBox dst ) { int srcelemsize = PixelUtil.GetNumElemBytes( src.Format ); int dstelemsize = PixelUtil.GetNumElemBytes( dst.Format ); int dstOffset = 0; // sx_48,sy_48,sz_48 represent current position in source // using 16/48-bit fixed precision, incremented by steps UInt64 stepx = ( (UInt64)src.Width << 48 ) / (UInt64)dst.Width; UInt64 stepy = ( (UInt64)src.Height << 48 ) / (UInt64)dst.Height; UInt64 stepz = ( (UInt64)src.Depth << 48 ) / (UInt64)dst.Depth; // temp is 16/16 bit fixed precision, used to adjust a source // coordinate (x, y, or z) backwards by half a pixel so that the // integer bits represent the first sample (eg, sx1) and the // fractional bits are the blend weight of the second sample uint temp; // note: ((stepz>>1) - 1) is an extra half-step increment to adjust // for the center of the destination pixel, not the top-left corner UInt64 sz_48 = ( stepz >> 1 ) - 1; for ( int z = dst.Front; z < dst.Back; z++, sz_48 += stepz ) { temp = (uint)( sz_48 >> 32 ); temp = ( temp > 0x8000 ) ? temp - 0x8000 : 0; int sz1 = (int)( temp >> 16 ); int sz2 = System.Math.Min( sz1 + 1, src.Depth - 1 ); float szf = ( temp & 0xFFFF ) / 65536f; UInt64 sy_48 = ( stepy >> 1 ) - 1; for ( int y = dst.Top; y < dst.Bottom; y++, sy_48 += stepy ) { temp = (uint)( sy_48 >> 32 ); temp = ( temp > 0x8000 ) ? temp - 0x8000 : 0; int sy1 = (int)( temp >> 16 ); // src x #1 int sy2 = System.Math.Min( sy1 + 1, src.Height - 1 ); // src x #2 float syf = ( temp & 0xFFFF ) / 65536f; // weight of #2 UInt64 sx_48 = ( stepx >> 1 ) - 1; for ( int x = dst.Left; x < dst.Right; x++, sx_48 += stepx ) { temp = (uint)( sy_48 >> 32 ); temp = ( temp > 0x8000 ) ? temp - 0x8000 : 0; int sx1 = (int)( temp >> 16 ); // src x #1 int sx2 = System.Math.Min( sx1 + 1, src.Width - 1 ); // src x #2 float sxf = ( temp & 0xFFFF ) / 65536f; // weight of #2 ColorEx x1y1z1 = ColorEx.White, x2y1z1 = ColorEx.White, x1y2z1 = ColorEx.White, x2y2z1 = ColorEx.White; ColorEx x1y1z2 = ColorEx.White, x2y1z2 = ColorEx.White, x1y2z2 = ColorEx.White, x2y2z2 = ColorEx.White; Unpack( ref x1y1z1, sx1, sy1, sz1, src.Format, src.Data, src, srcelemsize ); Unpack( ref x2y1z1, sx2, sy1, sz1, src.Format, src.Data, src, srcelemsize ); Unpack( ref x1y2z1, sx1, sy2, sz1, src.Format, src.Data, src, srcelemsize ); Unpack( ref x2y2z1, sx2, sy2, sz1, src.Format, src.Data, src, srcelemsize ); Unpack( ref x1y1z2, sx1, sy1, sz2, src.Format, src.Data, src, srcelemsize ); Unpack( ref x2y1z2, sx2, sy1, sz2, src.Format, src.Data, src, srcelemsize ); Unpack( ref x1y2z2, sx1, sy2, sz2, src.Format, src.Data, src, srcelemsize ); Unpack( ref x2y2z2, sx2, sy2, sz2, src.Format, src.Data, src, srcelemsize ); ColorEx accum = x1y1z1 * ( ( 1.0f - sxf ) * ( 1.0f - syf ) * ( 1.0f - szf ) ) + x2y1z1 * ( sxf * ( 1.0f - syf ) * ( 1.0f - szf ) ) + x1y2z1 * ( ( 1.0f - sxf ) * syf * ( 1.0f - szf ) ) + x2y2z1 * ( sxf * syf * ( 1.0f - szf ) ) + x1y1z2 * ( ( 1.0f - sxf ) * ( 1.0f - syf ) * szf ) + x2y1z2 * ( sxf * ( 1.0f - syf ) * szf ) + x1y2z2 * ( ( 1.0f - sxf ) * syf * szf ) + x2y2z2 * ( sxf * syf * szf ); PixelConverter.PackColor( accum, dst.Format, new IntPtr( dst.Data.ToInt32() + dstOffset ) ); dstOffset += dstelemsize; } dstOffset += dstelemsize * dst.RowSkip; } dstOffset += dstelemsize * dst.SliceSkip; } }
protected static D3D9.Box ToD3DBoxExtent( PixelBox lockBox ) { var pbox = new D3D9.Box(); pbox.Left = 0; pbox.Right = lockBox.Width; pbox.Top = 0; pbox.Bottom = lockBox.Height; pbox.Front = 0; pbox.Back = lockBox.Depth; return pbox; }
/// <summary> /// </summary> /// <param name="pb"> </param> /// <param name="buffer"> </param> public override void CopyContentsToMemory( PixelBox pb, RenderTarget.FrameBuffer buffer ) { throw new NotImplementedException(); }
public override void BlitFromMemory( PixelBox src, BasicBox dstBox ) { //Entering critical section LockDeviceAccess(); foreach ( var it in this.mapDeviceToBufferResources ) { BlitFromMemory( src, dstBox, it.Value ); } //Leaving critical section UnlockDeviceAccess(); }
public void WriteContentsToFile(string fileName) { var pf = SuggestPixelFormat(); var data = new byte[Width * Height * PixelUtil.GetNumElemBytes(pf)]; var bufGcHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var pb = new PixelBox(Width, Height, 1, pf, bufGcHandle.AddrOfPinnedObject()); CopyContentsToMemory(pb); (new Image()).FromDynamicImage(data, Width, Height, 1, pf, false, 1, 0).Save(fileName); if (bufGcHandle.IsAllocated) bufGcHandle.Free(); }
public override void BlitToMemory( BasicBox srcBox, PixelBox dst ) { //Entering critical section LockDeviceAccess(); var pair = this.mapDeviceToBufferResources.First(); BlitToMemory( srcBox, dst, pair.Value, pair.Key ); //Leaving critical section UnlockDeviceAccess(); }
/// <summary> /// </summary> /// <param name="src"> </param> /// <param name="dst"> </param> public void Scale(PixelBox src, PixelBox dst) { var srcelemsize = PixelUtil.GetNumElemBytes(src.Format); var dstelemsize = PixelUtil.GetNumElemBytes(dst.Format); var dstOffset = 0; // sx_48,sy_48,sz_48 represent current position in source // using 16/48-bit fixed precision, incremented by steps var stepx = ((UInt64)src.Width << 48) / (UInt64)dst.Width; var stepy = ((UInt64)src.Height << 48) / (UInt64)dst.Height; var stepz = ((UInt64)src.Depth << 48) / (UInt64)dst.Depth; // temp is 16/16 bit fixed precision, used to adjust a source // coordinate (x, y, or z) backwards by half a pixel so that the // integer bits represent the first sample (eg, sx1) and the // fractional bits are the blend weight of the second sample uint temp; // note: ((stepz>>1) - 1) is an extra half-step increment to adjust // for the center of the destination pixel, not the top-left corner var sz_48 = (stepz >> 1) - 1; for (var z = dst.Front; z < dst.Back; z++, sz_48 += stepz) { temp = (uint)(sz_48 >> 32); temp = (temp > 0x8000) ? temp - 0x8000 : 0; var sz1 = (int)(temp >> 16); var sz2 = System.Math.Min(sz1 + 1, src.Depth - 1); var szf = (temp & 0xFFFF) / 65536f; var sy_48 = (stepy >> 1) - 1; for (var y = dst.Top; y < dst.Bottom; y++, sy_48 += stepy) { temp = (uint)(sy_48 >> 32); temp = (temp > 0x8000) ? temp - 0x8000 : 0; var sy1 = (int)(temp >> 16); // src x #1 var sy2 = System.Math.Min(sy1 + 1, src.Height - 1); // src x #2 var syf = (temp & 0xFFFF) / 65536f; // weight of #2 var sx_48 = (stepx >> 1) - 1; for (var x = dst.Left; x < dst.Right; x++, sx_48 += stepx) { temp = (uint)(sy_48 >> 32); temp = (temp > 0x8000) ? temp - 0x8000 : 0; var sx1 = (int)(temp >> 16); // src x #1 var sx2 = System.Math.Min(sx1 + 1, src.Width - 1); // src x #2 var sxf = (temp & 0xFFFF) / 65536f; // weight of #2 ColorEx x1y1z1 = ColorEx.White, x2y1z1 = ColorEx.White, x1y2z1 = ColorEx.White, x2y2z1 = ColorEx.White; ColorEx x1y1z2 = ColorEx.White, x2y1z2 = ColorEx.White, x1y2z2 = ColorEx.White, x2y2z2 = ColorEx.White; Unpack(ref x1y1z1, sx1, sy1, sz1, src.Format, src.Data, src, srcelemsize); Unpack(ref x2y1z1, sx2, sy1, sz1, src.Format, src.Data, src, srcelemsize); Unpack(ref x1y2z1, sx1, sy2, sz1, src.Format, src.Data, src, srcelemsize); Unpack(ref x2y2z1, sx2, sy2, sz1, src.Format, src.Data, src, srcelemsize); Unpack(ref x1y1z2, sx1, sy1, sz2, src.Format, src.Data, src, srcelemsize); Unpack(ref x2y1z2, sx2, sy1, sz2, src.Format, src.Data, src, srcelemsize); Unpack(ref x1y2z2, sx1, sy2, sz2, src.Format, src.Data, src, srcelemsize); Unpack(ref x2y2z2, sx2, sy2, sz2, src.Format, src.Data, src, srcelemsize); var accum = x1y1z1 * ((1.0f - sxf) * (1.0f - syf) * (1.0f - szf)) + x2y1z1 * (sxf * (1.0f - syf) * (1.0f - szf)) + x1y2z1 * ((1.0f - sxf) * syf * (1.0f - szf)) + x2y2z1 * (sxf * syf * (1.0f - szf)) + x1y1z2 * ((1.0f - sxf) * (1.0f - syf) * szf) + x2y1z2 * (sxf * (1.0f - syf) * szf) + x1y2z2 * ((1.0f - sxf) * syf * szf) + x2y2z2 * (sxf * syf * szf); PixelConverter.PackColor(accum, dst.Format, dst.Data + dstOffset); dstOffset += dstelemsize; } dstOffset += dstelemsize * dst.RowSkip; } dstOffset += dstelemsize * dst.SliceSkip; } }
/// <summary> /// Save our texture to a stream /// </summary> /// <param name="stream"></param> /// <param name="requestedFormat"></param> public override void Save(System.IO.Stream stream, PixelFormat requestedFormat) { // First try to see if we can use the fast method to save this image. // TODO: I should be able to make the common path closer to this in performance ([email protected]) if (pixelBuffer.Format == PixelFormat.A8R8G8B8) { if (requestedFormat == PixelFormat.A8B8G8R8 || requestedFormat == PixelFormat.B8G8R8) { SimpleSave(stream, requestedFormat); return; } } int bufSize = PixelUtil.GetMemorySize(pixelBuffer.Width, pixelBuffer.Height, pixelBuffer.Depth, requestedFormat); byte[] buffer = new byte[bufSize]; // Pin down the byte array GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); IntPtr address = handle.AddrOfPinnedObject(); PixelBox box = new PixelBox(pixelBuffer.Width, pixelBuffer.Height, pixelBuffer.Depth, requestedFormat, address); pixelBuffer.BlitToMemory(box); handle.Free(); // I need to flip this image, since it was upside down in the // internal buffers. I could do this in the save pass, which // would make this more efficient, but I don't currently think // that efficiency is that important. Image image = Image.FromDynamicImage(buffer, pixelBuffer.Width, pixelBuffer.Height, pixelBuffer.Depth, requestedFormat); image.FlipAroundX(); // Ok, now the data in buffer has been flipped. // Go ahead and discard the image image.Dispose(); // write the data to the stream provided stream.Write(buffer, 0, bufSize); }
///<summary> /// Convert pixels from one format to another. No dithering or filtering is being done. Converting /// from RGB to luminance takes the R channel. ///</summary> ///<param name="src">PixelBox containing the source pixels, pitches and format</param> ///<param name="dst">PixelBox containing the destination pixels, pitches and format</param> ///<remarks> /// The source and destination boxes must have the same /// dimensions. In case the source and destination format match, a plain copy is done. ///</remarks> public static void BulkPixelConversion(PixelBox src, PixelBox dst) { Debug.Assert(src.Width == dst.Width && src.Height == dst.Height && src.Depth == dst.Depth); // Check for compressed formats, we don't support decompression, compression or recoding if (PixelBox.Compressed(src.Format) || PixelBox.Compressed(dst.Format)) { if (src.Format == dst.Format) { CopyBytes(dst.Data, dst.Offset, src.Data, src.Offset, src.ConsecutiveSize); return; } else { throw new Exception("This method can not be used to compress or decompress images, in PixelBox.BulkPixelConversion"); } } // The easy case if (src.Format == dst.Format) { // Everything consecutive? if (src.Consecutive && dst.Consecutive) { CopyBytes(dst.Data, dst.Offset, src.Data, src.Offset, src.ConsecutiveSize); return; } unsafe { byte *srcBytes = (byte *)src.Data.ToPointer(); byte *dstBytes = (byte *)dst.Data.ToPointer(); byte *srcptr = srcBytes + src.Offset; byte *dstptr = dstBytes + dst.Offset; int srcPixelSize = PixelUtil.GetNumElemBytes(src.Format); int dstPixelSize = PixelUtil.GetNumElemBytes(dst.Format); // Calculate pitches+skips in bytes int srcRowPitchBytes = src.RowPitch * srcPixelSize; //int srcRowSkipBytes = src.RowSkip * srcPixelSize; int srcSliceSkipBytes = src.SliceSkip * srcPixelSize; int dstRowPitchBytes = dst.RowPitch * dstPixelSize; //int dstRowSkipBytes = dst.RowSkip * dstPixelSize; int dstSliceSkipBytes = dst.SliceSkip * dstPixelSize; // Otherwise, copy per row int rowSize = src.Width * srcPixelSize; for (int z = src.Front; z < src.Back; z++) { for (int y = src.Top; y < src.Bottom; y++) { byte *s = srcptr; byte *d = dstptr; for (int i = 0; i < rowSize; i++) { *d++ = *s++; } srcptr += srcRowPitchBytes; dstptr += dstRowPitchBytes; } srcptr += srcSliceSkipBytes; dstptr += dstSliceSkipBytes; } } return; } if (PixelConversionLoops.DoOptimizedConversion(src, dst)) { // If so, good return; } unsafe { byte *srcBytes = (byte *)src.Data.ToPointer(); byte *dstBytes = (byte *)dst.Data.ToPointer(); byte *srcptr = srcBytes + src.Offset; byte *dstptr = dstBytes + dst.Offset; int srcPixelSize = PixelUtil.GetNumElemBytes(src.Format); int dstPixelSize = PixelUtil.GetNumElemBytes(dst.Format); // Calculate pitches+skips in bytes int srcRowSkipBytes = src.RowSkip * srcPixelSize; int srcSliceSkipBytes = src.SliceSkip * srcPixelSize; int dstRowSkipBytes = dst.RowSkip * dstPixelSize; int dstSliceSkipBytes = dst.SliceSkip * dstPixelSize; // The brute force fallback float r, g, b, a; for (int z = src.Front; z < src.Back; z++) { for (int y = src.Top; y < src.Bottom; y++) { for (int x = src.Left; x < src.Right; x++) { UnpackColor(out r, out g, out b, out a, src.Format, srcptr); PackColor(r, g, b, a, dst.Format, dstptr); srcptr += srcPixelSize; dstptr += dstPixelSize; } srcptr += srcRowSkipBytes; dstptr += dstRowSkipBytes; } srcptr += srcSliceSkipBytes; dstptr += dstSliceSkipBytes; } } }
public override Codec.DecodeResult Decode( Stream input ) { var imgData = new ImageData(); var output = new MemoryStream(); int imageID; int imageFormat, bytesPerPixel; // create and bind a new image Il.ilGenImages( 1, out imageID ); Il.ilBindImage( imageID ); // create a temp buffer and write the stream into it var buffer = new byte[input.Length]; input.Read( buffer, 0, buffer.Length ); // Put it right side up Il.ilEnable( Il.IL_ORIGIN_SET ); Il.ilSetInteger( Il.IL_ORIGIN_MODE, Il.IL_ORIGIN_UPPER_LEFT ); // Keep DXTC(compressed) data if present Il.ilSetInteger( Il.IL_KEEP_DXTC_DATA, Il.IL_TRUE ); // load the data into DevIL Il.ilLoadL( this._ilType, buffer, buffer.Length ); // check for an error var ilError = Il.ilGetError(); if ( ilError != Il.IL_NO_ERROR ) { throw new AxiomException( "Error while decoding image data: '{0}'", Ilu.iluErrorString( ilError ) ); } imageFormat = Il.ilGetInteger( Il.IL_IMAGE_FORMAT ); var imageType = Il.ilGetInteger( Il.IL_IMAGE_TYPE ); // Convert image if imageType is incompatible with us (double or long) if ( imageType != Il.IL_BYTE && imageType != Il.IL_UNSIGNED_BYTE && imageType != Il.IL_FLOAT && imageType != Il.IL_UNSIGNED_SHORT && imageType != Il.IL_SHORT ) { Il.ilConvertImage( imageFormat, Il.IL_FLOAT ); imageType = Il.IL_FLOAT; } // Converted paletted images if ( imageFormat == Il.IL_COLOR_INDEX ) { Il.ilConvertImage( Il.IL_BGRA, Il.IL_UNSIGNED_BYTE ); imageFormat = Il.IL_BGRA; imageType = Il.IL_UNSIGNED_BYTE; } // populate the image data bytesPerPixel = Il.ilGetInteger( Il.IL_IMAGE_BYTES_PER_PIXEL ); imgData.format = ILUtil.Convert( imageFormat, imageType ); imgData.width = Il.ilGetInteger( Il.IL_IMAGE_WIDTH ); imgData.height = Il.ilGetInteger( Il.IL_IMAGE_HEIGHT ); imgData.depth = Il.ilGetInteger( Il.IL_IMAGE_DEPTH ); imgData.numMipMaps = Il.ilGetInteger( Il.IL_NUM_MIPMAPS ); if ( imgData.format == PixelFormat.Unknown ) { throw new AxiomException( "Unsupported devil format ImageFormat={0} ImageType={1}", imageFormat, imageType ); } // Check for cubemap var numFaces = Il.ilGetInteger( Il.IL_NUM_IMAGES ) + 1; if ( numFaces == 6 ) { imgData.flags |= ImageFlags.CubeMap; } else { numFaces = 1; // Support only 1 or 6 face images for now } // Keep DXT data (if present at all and the GPU supports it) var dxtFormat = Il.ilGetInteger( Il.IL_DXTC_DATA_FORMAT ); if ( dxtFormat != Il.IL_DXT_NO_COMP && Root.Instance.RenderSystem.Capabilities.HasCapability( Axiom.Graphics.Capabilities.TextureCompressionDXT ) ) { imgData.format = ILUtil.Convert( dxtFormat, imageType ); imgData.flags |= ImageFlags.Compressed; // Validate that this devil version loads DXT mipmaps if ( imgData.numMipMaps > 0 ) { Il.ilBindImage( imageID ); Il.ilActiveMipmap( 1 ); if ( (uint)Il.ilGetInteger( Il.IL_DXTC_DATA_FORMAT ) != dxtFormat ) { imgData.numMipMaps = 0; LogManager.Instance.Write( "Warning: Custom mipmaps for compressed image were ignored because they are not loaded by this DevIL version." ); } } } // Calculate total size from number of mipmaps, faces and size imgData.size = Image.CalculateSize( imgData.numMipMaps, numFaces, imgData.width, imgData.height, imgData.depth, imgData.format ); // get the decoded data BufferBase BufferHandle; // Dimensions of current mipmap var width = imgData.width; var height = imgData.height; var depth = imgData.depth; // Transfer data for ( var mip = 0; mip <= imgData.numMipMaps; ++mip ) { for ( var i = 0; i < numFaces; ++i ) { Il.ilBindImage( imageID ); if ( numFaces > 1 ) { Il.ilActiveImage( i ); } if ( imgData.numMipMaps > 0 ) { Il.ilActiveMipmap( mip ); } // Size of this face var imageSize = PixelUtil.GetMemorySize( width, height, depth, imgData.format ); buffer = new byte[imageSize]; if ( ( imgData.flags & ImageFlags.Compressed ) != 0 ) { // Compare DXT size returned by DevIL with our idea of the compressed size if ( imageSize == Il.ilGetDXTCData( IntPtr.Zero, 0, dxtFormat ) ) { // Retrieve data from DevIL using ( BufferHandle = BufferBase.Wrap( buffer ) ) { Il.ilGetDXTCData( BufferHandle.Pin(), imageSize, dxtFormat ); BufferHandle.UnPin(); } } else { LogManager.Instance.Write( "Warning: compressed image size mismatch, devilsize={0} oursize={1}", Il.ilGetDXTCData( IntPtr.Zero, 0, dxtFormat ), imageSize ); } } else { // Retrieve data from DevIL using ( BufferHandle = BufferBase.Wrap( buffer ) ) { var dst = new PixelBox( width, height, depth, imgData.format, BufferHandle ); ILUtil.ConvertFromIL( dst ); } } // write the decoded data to the output stream output.Write( buffer, 0, buffer.Length ); } // Next mip if ( width != 1 ) { width /= 2; } if ( height != 1 ) { height /= 2; } if ( depth != 1 ) { depth /= 2; } } // Restore IL state Il.ilDisable( Il.IL_ORIGIN_SET ); Il.ilDisable( Il.IL_FORMAT_SET ); Il.ilDeleteImages( 1, ref imageID ); return new DecodeResult( output, imgData ); }
void Unpack( ref ColorEx dst, int x, int y, int z, PixelFormat format, IntPtr src, PixelBox srcbox, int elemsize ) { unsafe { byte* pSrc = (byte*)src; IntPtr data = (IntPtr)( pSrc + elemsize * ( ( x ) + ( y ) * srcbox.RowPitch + ( z ) * srcbox.SlicePitch ) ); dst = PixelConverter.UnpackColor( format, data ); } }