locked
Issue with file handle, not getting released (Win8 Consumer Preview)

    Question

  • Any one tried using IWICStream with WICFactory and BitMapEncoder

    I noticed my file handles are not release after I am done calling BitMapEncoder->FlushAsync();

    Not sure how to explicitly close my file handles. When my function returns, I tried to open my modified BitMapImage, it says this file is being used by some other program ....

    This was working with 'Earlier Win 8 Build (Build Conference Build)'. With latest build 8250, my file handles are not getting released.

    Here is code snippet

    void WaterMarkHelperClass::WriteToFile(String^ imgFileNameWithPath, String^ fileName, String^ waterMarkText, bool bUseText)
    {
    	//WaterMarkHelperClass^  imgHlprCls = this;
    	StorageFolder^ storageFolder = KnownFolders::PicturesLibrary; 
    
    	task<StorageFolder^> wtrMarkFolderTask(storageFolder->CreateFolderAsync("WaterMarkedPictures", Windows::Storage::CreationCollisionOption::OpenIfExists));
    	wtrMarkFolderTask.then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText](StorageFolder^ wtrMarkFolder) 
    	{
    		return wtrMarkFolder->CreateFileAsync(fileName, Windows::Storage::CreationCollisionOption::ReplaceExisting);
    	}).then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText](StorageFile^ wtrMarkFile) 
    	{
    		return wtrMarkFile->OpenAsync(Windows::Storage::FileAccessMode::ReadWriteUnsafe);
    	}).then([&,this, imgFileNameWithPath, fileName, waterMarkText, bUseText](IRandomAccessStream^ writeStream) 
    	{
    		return BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, writeStream);
    	}).then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText](BitmapEncoder^ encoder)
    	{
    		ComPtr<IWICStream> fileStrm;
    		DX::ThrowIfFailed(this->m_wicFactory->CreateStream(&fileStrm));
    
    		DX::ThrowIfFailed(fileStrm->InitializeFromFilename(imgFileNameWithPath->Data(), GENERIC_READ));
    
    		ComPtr<IWICBitmapDecoder> decoder;
    		DX::ThrowIfFailed(this->m_wicFactory->CreateDecoderFromStream(fileStrm.Get(),	NULL, 
    			WICDecodeMetadataCacheOnDemand, &decoder)
    			);
    
    		ComPtr<IWICBitmapFrameDecode> frame;
    		DX::ThrowIfFailed(decoder->GetFrame(0, &frame));
    
    		ComPtr<IWICFormatConverter> converter;
    		DX::ThrowIfFailed(this->m_wicFactory->CreateFormatConverter(&converter));
    
    		DX::ThrowIfFailed(converter->Initialize(
    			frame.Get(), GUID_WICPixelFormat32bppPRGBA,	WICBitmapDitherTypeNone, NULL,
    			0.0f, WICBitmapPaletteTypeCustom )
    			);
    
    		UINT width;
    		UINT height;
    		DX::ThrowIfFailed(converter->GetSize(&width, &height));
    
    		ComPtr<IWICBitmap> wicBitMap;
    		DX::ThrowIfFailed(this->m_wicFactory->CreateBitmapFromSource(converter.Get(), WICBitmapCacheOnLoad, &wicBitMap));
    
    		ComPtr<ID2D1RenderTarget> bitMapRenderTarget;
    		D2D1_RENDER_TARGET_PROPERTIES renderProp = D2D1::RenderTargetProperties();
    		DX::ThrowIfFailed(this->m_d2dFactory->CreateWicBitmapRenderTarget(wicBitMap.Get(), &renderProp, &bitMapRenderTarget));
    
    		ComPtr<ID2D1SolidColorBrush> yellowBrush;
    		DX::ThrowIfFailed(bitMapRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red), &yellowBrush));
    
    		D2D1_RECT_F imageSize;
    		imageSize.left = 0;
    		imageSize.top = 0;
    		imageSize.right = static_cast<float>(width);
    		imageSize.bottom = static_cast<float>(height);
    
    		bitMapRenderTarget->BeginDraw();
    		if (bUseText)
    		{
    			bitMapRenderTarget->DrawText(waterMarkText->Data(), waterMarkText->Length(), 
    				this->m_textFormat.Get(), &imageSize, yellowBrush.Get());
    		}
    		else
    		{
    			D2D1_SIZE_F bitmapSize = this->m_wtrMarkBitMap->GetSize();
    			D2D1_RECT_F wtrMarkPos;
    			wtrMarkPos.left = (width - bitmapSize.width - 10);
    			wtrMarkPos.top = (height - bitmapSize.height - 10);
    			wtrMarkPos.right = (float)(width - 10);
    			wtrMarkPos.bottom = (float)(height - 10);
    			bitMapRenderTarget->DrawBitmap(this->m_wtrMarkBitMap, wtrMarkPos, 0.5, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
    		}
    		bitMapRenderTarget->EndDraw();
    
    		ComPtr<ID2D1Bitmap> d2dBitMap;
    		DX::ThrowIfFailed(bitMapRenderTarget->CreateBitmapFromWicBitmap(wicBitMap.Get(), &d2dBitMap));
    		FLOAT dpiX;
    		FLOAT dpiY;
    		d2dBitMap->GetDpi(&dpiX, &dpiY);
    
    		WICRect rcLock;
    		rcLock.X = 0;
    		rcLock.Y = 0;
    		rcLock.Width = width;
    		rcLock.Height = height;
    		ComPtr<IWICBitmapLock> pLock;
    		DX::ThrowIfFailed(wicBitMap->Lock(&rcLock, WICBitmapLockRead, &pLock));
    
    		UINT cbBufferSize = 0;
    		UINT cbStride = 0;
    		WICInProcPointer buf;
    
    		DX::ThrowIfFailed(pLock->GetStride(&cbStride));
    		DX::ThrowIfFailed(pLock->GetDataPointer(&cbBufferSize, &buf));
    
    		Platform::Array<BYTE>^ byteArray = ref new Platform::Array<BYTE>(cbBufferSize);
    		for (UINT indx = 0; indx < cbBufferSize; ++indx)
    		{
    			byteArray[indx] = buf[indx];
    		}
    
    		encoder->SetPixelData(BitmapPixelFormat::Rgba8, BitmapAlphaMode::Ignore, width, height, dpiX, dpiY, byteArray);
    		delete byteArray;
    		return encoder->FlushAsync();
    	}).then([this, fileName](task<void> doneFlushTask)
    	{
    		doneFlushTask.get();						
    		this->WaterMarkingCompleted(fileName);
    	});
    }
    

    Thank you

    PB

    Note: I posted same question on DirectX forum too, not sure where would this question fit into.

    Wednesday, February 29, 2012 10:14 PM

Answers

  • Wow finally I figured out which object to delete, I modified the code now it is working. This is kind of non trivial to me, but it works now. Modified code is in Bold letters and added 'delete wrtStrm' at the end.

    void WaterMarkHelperClass::WriteToFile(String^ imgFileNameWithPath, String^ fileName, String^ waterMarkText, bool bUseText)
    {
    	//WaterMarkHelperClass^  imgHlprCls = this;
    	StorageFolder^ storageFolder = KnownFolders::PicturesLibrary; 
    
    	task<StorageFolder^> wtrMarkFolderTask(storageFolder->CreateFolderAsync("WaterMarkedPictures", Windows::Storage::CreationCollisionOption::OpenIfExists));
    	wtrMarkFolderTask.then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText](StorageFolder^ wtrMarkFolder) 
    	{
    		return wtrMarkFolder->CreateFileAsync(fileName, Windows::Storage::CreationCollisionOption::ReplaceExisting);
    	}).then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText](StorageFile^ wtrMarkFile) 
    	{
    		return wtrMarkFile->OpenAsync(Windows::Storage::FileAccessMode::ReadWriteUnsafe);
    	}).then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText](IRandomAccessStream^ strm) 
    	{
    		IRandomAccessStream^ wrtStrm = strm;
    		task<BitmapEncoder^> encoderTask(BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, wrtStrm));
    		encoderTask.then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText, wrtStrm](BitmapEncoder^ encoder)
    		{
    			ComPtr<IWICStream> fileStrm;
    			DX::ThrowIfFailed(this->m_wicFactory->CreateStream(&fileStrm));
    
    			DX::ThrowIfFailed(fileStrm->InitializeFromFilename(imgFileNameWithPath->Data(), GENERIC_READ));
    
    			ComPtr<IWICBitmapDecoder> decoder;
    			DX::ThrowIfFailed(this->m_wicFactory->CreateDecoderFromStream(fileStrm.Get(),	NULL, 
    				WICDecodeMetadataCacheOnDemand, &decoder)
    				);
    
    			ComPtr<IWICBitmapFrameDecode> frame;
    			DX::ThrowIfFailed(decoder->GetFrame(0, &frame));
    
    			ComPtr<IWICFormatConverter> converter;
    			DX::ThrowIfFailed(this->m_wicFactory->CreateFormatConverter(&converter));
    
    			DX::ThrowIfFailed(converter->Initialize(
    				frame.Get(), GUID_WICPixelFormat32bppPRGBA,	WICBitmapDitherTypeNone, NULL,
    				0.0f, WICBitmapPaletteTypeCustom )
    				);
    
    			UINT width;
    			UINT height;
    			DX::ThrowIfFailed(converter->GetSize(&width, &height));
    
    			ComPtr<IWICBitmap> wicBitMap;
    			DX::ThrowIfFailed(this->m_wicFactory->CreateBitmapFromSource(converter.Get(), WICBitmapCacheOnLoad, &wicBitMap));
    
    			ComPtr<ID2D1RenderTarget> bitMapRenderTarget;
    			D2D1_RENDER_TARGET_PROPERTIES renderProp = D2D1::RenderTargetProperties();
    			DX::ThrowIfFailed(this->m_d2dFactory->CreateWicBitmapRenderTarget(wicBitMap.Get(), &renderProp, &bitMapRenderTarget));
    
    			ComPtr<ID2D1SolidColorBrush> yellowBrush;
    			DX::ThrowIfFailed(bitMapRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red), &yellowBrush));
    
    			D2D1_RECT_F imageSize;
    			imageSize.left = 0;
    			imageSize.top = 0;
    			imageSize.right = static_cast<float>(width);
    			imageSize.bottom = static_cast<float>(height);
    
    			bitMapRenderTarget->BeginDraw();
    			if (bUseText)
    			{
    				bitMapRenderTarget->DrawText(waterMarkText->Data(), waterMarkText->Length(), 
    					this->m_textFormat.Get(), &imageSize, yellowBrush.Get());
    			}
    			else
    			{
    				D2D1_SIZE_F bitmapSize = this->m_wtrMarkBitMap->GetSize();
    				D2D1_RECT_F wtrMarkPos;
    				wtrMarkPos.left = (width - bitmapSize.width - 10);
    				wtrMarkPos.top = (height - bitmapSize.height - 10);
    				wtrMarkPos.right = (float)(width - 10);
    				wtrMarkPos.bottom = (float)(height - 10);
    				bitMapRenderTarget->DrawBitmap(this->m_wtrMarkBitMap, wtrMarkPos, 0.5, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
    			}
    			bitMapRenderTarget->EndDraw();
    
    			ComPtr<ID2D1Bitmap> d2dBitMap;
    			DX::ThrowIfFailed(bitMapRenderTarget->CreateBitmapFromWicBitmap(wicBitMap.Get(), &d2dBitMap));
    			FLOAT dpiX;
    			FLOAT dpiY;
    			d2dBitMap->GetDpi(&dpiX, &dpiY);
    
    			WICRect rcLock;
    			rcLock.X = 0;
    			rcLock.Y = 0;
    			rcLock.Width = width;
    			rcLock.Height = height;
    			ComPtr<IWICBitmapLock> pLock;
    			DX::ThrowIfFailed(wicBitMap->Lock(&rcLock, WICBitmapLockRead, &pLock));
    
    			UINT cbBufferSize = 0;
    			UINT cbStride = 0;
    			WICInProcPointer buf;
    
    			DX::ThrowIfFailed(pLock->GetStride(&cbStride));
    			DX::ThrowIfFailed(pLock->GetDataPointer(&cbBufferSize, &buf));
    
    			Platform::Array<BYTE>^ byteArray = ref new Platform::Array<BYTE>(cbBufferSize);
    			for (UINT indx = 0; indx < cbBufferSize; ++indx)
    			{
    				byteArray[indx] = buf[indx];
    			}
    
    			encoder->SetPixelData(BitmapPixelFormat::Rgba8, BitmapAlphaMode::Ignore, width, height, dpiX, dpiY, byteArray);
    			delete byteArray;
    			return encoder->FlushAsync();
    		}).then([this, fileName, wrtStrm](task<void> doneFlushTask)
    		{
    			doneFlushTask.get();	
    			delete wrtStrm;
    			this->WaterMarkingCompleted(fileName);
    		});
    	});
    }


    • Edited by __PB Thursday, March 22, 2012 7:09 PM
    • Marked as answer by __PB Thursday, March 22, 2012 7:09 PM
    Thursday, March 22, 2012 7:07 PM

All replies

  • Hi PB,

    I deleted your duplicate post. In the future please just post once, but thank you for the heads up.

    Take a look at the section on Deterministic lifetime management of Windows Runtime objects in the //Build to Windows 8 Consumer Preview whitepaper to see if that answers your question. If not let us know and we can look at this in more detail.

    --Rob

    Thursday, March 01, 2012 12:20 AM
    Owner
  • Thanks Rob, it did not help.

    Here is what I did to above code

    IAsyncAction^ aa = encoder->FlushAsync();
    delete encoder;
    return aa;

    Thursday, March 01, 2012 7:29 AM
  • Wow finally I figured out which object to delete, I modified the code now it is working. This is kind of non trivial to me, but it works now. Modified code is in Bold letters and added 'delete wrtStrm' at the end.

    void WaterMarkHelperClass::WriteToFile(String^ imgFileNameWithPath, String^ fileName, String^ waterMarkText, bool bUseText)
    {
    	//WaterMarkHelperClass^  imgHlprCls = this;
    	StorageFolder^ storageFolder = KnownFolders::PicturesLibrary; 
    
    	task<StorageFolder^> wtrMarkFolderTask(storageFolder->CreateFolderAsync("WaterMarkedPictures", Windows::Storage::CreationCollisionOption::OpenIfExists));
    	wtrMarkFolderTask.then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText](StorageFolder^ wtrMarkFolder) 
    	{
    		return wtrMarkFolder->CreateFileAsync(fileName, Windows::Storage::CreationCollisionOption::ReplaceExisting);
    	}).then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText](StorageFile^ wtrMarkFile) 
    	{
    		return wtrMarkFile->OpenAsync(Windows::Storage::FileAccessMode::ReadWriteUnsafe);
    	}).then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText](IRandomAccessStream^ strm) 
    	{
    		IRandomAccessStream^ wrtStrm = strm;
    		task<BitmapEncoder^> encoderTask(BitmapEncoder::CreateAsync(BitmapEncoder::JpegEncoderId, wrtStrm));
    		encoderTask.then([this, imgFileNameWithPath, fileName, waterMarkText, bUseText, wrtStrm](BitmapEncoder^ encoder)
    		{
    			ComPtr<IWICStream> fileStrm;
    			DX::ThrowIfFailed(this->m_wicFactory->CreateStream(&fileStrm));
    
    			DX::ThrowIfFailed(fileStrm->InitializeFromFilename(imgFileNameWithPath->Data(), GENERIC_READ));
    
    			ComPtr<IWICBitmapDecoder> decoder;
    			DX::ThrowIfFailed(this->m_wicFactory->CreateDecoderFromStream(fileStrm.Get(),	NULL, 
    				WICDecodeMetadataCacheOnDemand, &decoder)
    				);
    
    			ComPtr<IWICBitmapFrameDecode> frame;
    			DX::ThrowIfFailed(decoder->GetFrame(0, &frame));
    
    			ComPtr<IWICFormatConverter> converter;
    			DX::ThrowIfFailed(this->m_wicFactory->CreateFormatConverter(&converter));
    
    			DX::ThrowIfFailed(converter->Initialize(
    				frame.Get(), GUID_WICPixelFormat32bppPRGBA,	WICBitmapDitherTypeNone, NULL,
    				0.0f, WICBitmapPaletteTypeCustom )
    				);
    
    			UINT width;
    			UINT height;
    			DX::ThrowIfFailed(converter->GetSize(&width, &height));
    
    			ComPtr<IWICBitmap> wicBitMap;
    			DX::ThrowIfFailed(this->m_wicFactory->CreateBitmapFromSource(converter.Get(), WICBitmapCacheOnLoad, &wicBitMap));
    
    			ComPtr<ID2D1RenderTarget> bitMapRenderTarget;
    			D2D1_RENDER_TARGET_PROPERTIES renderProp = D2D1::RenderTargetProperties();
    			DX::ThrowIfFailed(this->m_d2dFactory->CreateWicBitmapRenderTarget(wicBitMap.Get(), &renderProp, &bitMapRenderTarget));
    
    			ComPtr<ID2D1SolidColorBrush> yellowBrush;
    			DX::ThrowIfFailed(bitMapRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red), &yellowBrush));
    
    			D2D1_RECT_F imageSize;
    			imageSize.left = 0;
    			imageSize.top = 0;
    			imageSize.right = static_cast<float>(width);
    			imageSize.bottom = static_cast<float>(height);
    
    			bitMapRenderTarget->BeginDraw();
    			if (bUseText)
    			{
    				bitMapRenderTarget->DrawText(waterMarkText->Data(), waterMarkText->Length(), 
    					this->m_textFormat.Get(), &imageSize, yellowBrush.Get());
    			}
    			else
    			{
    				D2D1_SIZE_F bitmapSize = this->m_wtrMarkBitMap->GetSize();
    				D2D1_RECT_F wtrMarkPos;
    				wtrMarkPos.left = (width - bitmapSize.width - 10);
    				wtrMarkPos.top = (height - bitmapSize.height - 10);
    				wtrMarkPos.right = (float)(width - 10);
    				wtrMarkPos.bottom = (float)(height - 10);
    				bitMapRenderTarget->DrawBitmap(this->m_wtrMarkBitMap, wtrMarkPos, 0.5, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR);
    			}
    			bitMapRenderTarget->EndDraw();
    
    			ComPtr<ID2D1Bitmap> d2dBitMap;
    			DX::ThrowIfFailed(bitMapRenderTarget->CreateBitmapFromWicBitmap(wicBitMap.Get(), &d2dBitMap));
    			FLOAT dpiX;
    			FLOAT dpiY;
    			d2dBitMap->GetDpi(&dpiX, &dpiY);
    
    			WICRect rcLock;
    			rcLock.X = 0;
    			rcLock.Y = 0;
    			rcLock.Width = width;
    			rcLock.Height = height;
    			ComPtr<IWICBitmapLock> pLock;
    			DX::ThrowIfFailed(wicBitMap->Lock(&rcLock, WICBitmapLockRead, &pLock));
    
    			UINT cbBufferSize = 0;
    			UINT cbStride = 0;
    			WICInProcPointer buf;
    
    			DX::ThrowIfFailed(pLock->GetStride(&cbStride));
    			DX::ThrowIfFailed(pLock->GetDataPointer(&cbBufferSize, &buf));
    
    			Platform::Array<BYTE>^ byteArray = ref new Platform::Array<BYTE>(cbBufferSize);
    			for (UINT indx = 0; indx < cbBufferSize; ++indx)
    			{
    				byteArray[indx] = buf[indx];
    			}
    
    			encoder->SetPixelData(BitmapPixelFormat::Rgba8, BitmapAlphaMode::Ignore, width, height, dpiX, dpiY, byteArray);
    			delete byteArray;
    			return encoder->FlushAsync();
    		}).then([this, fileName, wrtStrm](task<void> doneFlushTask)
    		{
    			doneFlushTask.get();	
    			delete wrtStrm;
    			this->WaterMarkingCompleted(fileName);
    		});
    	});
    }


    • Edited by __PB Thursday, March 22, 2012 7:09 PM
    • Marked as answer by __PB Thursday, March 22, 2012 7:09 PM
    Thursday, March 22, 2012 7:07 PM