How to save backbuffer to file in DirectX 10? - screenshot

I want to render a video frame-by-frame using DirectX 10. The frames would be processed later by some other tool like mencoder or ffmpeg.
I had no problems doing so in DX9 using D3DXSaveSurfaceToFile.
Now, in DX10 I've found D3DX10SaveTextureToFile, but had no luck using it to save my backbuffer.
I use the following code:
ID3D10Resource *backbufferRes;
_defaultRenderTargetView->GetResource(&backbufferRes);
D3D10_TEXTURE2D_DESC texDesc;
texDesc.ArraySize = 1;
texDesc.BindFlags = 0;
texDesc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
texDesc.Format = backbufferSurfDesc.Format;
texDesc.Height = backbufferSurfDesc.Height;
texDesc.Width = backbufferSurfDesc.Width;
texDesc.MipLevels = 1;
texDesc.MiscFlags = 0;
texDesc.SampleDesc = backbufferSurfDesc.SampleDesc;
texDesc.Usage = D3D10_USAGE_STAGING;
ID3D10Texture2D *texture;
HRESULT hr;
V( _device->CreateTexture2D(&texDesc, 0, &texture) );
_device->CopyResource(texture, backbufferRes);
V( D3DX10SaveTextureToFile(texture, D3DX10_IFF_DDS, filename) );
texture->Release();
This creates a .dds image that can not be opened by any sort of DDS view/editor I know of.
What's wrong with my code?

All the credit goes to sepul of gamedev.net.
Now, the problems:
texDesc.CPUAccessFlags should be 0
texDesc.Format should be DXGI_FORMAT_R8G8B8A8_UNORM
texDesc.SampleDesc.Count should be 1
texDesc.SampleDesc.Quality should be 0
texDesc.Usage should be D3D10_USAGE_DEFAULT
This way D3DX10SaveTextureToFile will save to BMP even to PNG.
The complete code is:
HRESULT hr;
ID3D10Resource *backbufferRes;
_defaultRenderTargetView->GetResource(&backbufferRes);
D3D10_TEXTURE2D_DESC texDesc;
texDesc.ArraySize = 1;
texDesc.BindFlags = 0;
texDesc.CPUAccessFlags = 0;
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
texDesc.Width = 640; // must be same as backbuffer
texDesc.Height = 480; // must be same as backbuffer
texDesc.MipLevels = 1;
texDesc.MiscFlags = 0;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D10_USAGE_DEFAULT;
ID3D10Texture2D *texture;
V( _device->CreateTexture2D(&texDesc, 0, &texture) );
_device->CopyResource(texture, backbufferRes);
V( D3DX10SaveTextureToFile(texture, D3DX10_IFF_PNG, L"test.png") );
texture->Release();
backbufferRes->Release();

Related

Blazor WASM PDF Generation with iTextSharp

I want to generate a PDF Document in Blazor WASM. I found examples with iTexSharp, so I did a small example.
Now I have two problems:
I have trouble with the image path to add an image in the pdf:
`Image img = Image.GetInstance("images/test.png");
How need I set the image reference to my "wwwroot/images" folder?
I get some error when I want to close my document with the command "document.Close()"
The error is:
System.Security.Cryptography.Algorithms is not supported on this
platform.
System.PlatformNotSupportedException: System.Security.Cryptography.Algorithms is not supported on this platform.
at System.Security.Cryptography.MD5.Create()
at iTextSharp.text.pdf.PdfEncryption.CreateDocumentId()
at iTextSharp.text.pdf.PdfWriter.Close()
at iTextSharp.text.pdf.PdfDocument.Close()
at iTextSharp.text.Document.Close()
Here is the whole code:
_document = new Document(PageSize.A4, 10f, 10f, 20f, 30f);
_pdfPTable.WidthPercentage = 50;
_pdfPTable.HorizontalAlignment = Element.ALIGN_LEFT;
_fontStyle = FontFactory.GetFont("Tahoma", 8f, 1);
PdfWriter.GetInstance(_document, _memoryStream);
_document.Open();
float[] sizes = new float[_maxColumn];
for (int i = 0; i < _maxColumn; i++)
{
if (i == 0) sizes[i] = 50;
else sizes[i] = 100;
}
_pdfPTable.SetWidths(sizes);
this.ReportHeader();
this.ReporBody();
_pdfPTable.HeaderRows = 2;
_document.Add(_pdfPTable);
_document.Close();
return _memoryStream.ToArray();
I have the same problem as you. What I found out is that because of WebAssembly sandbox constraint it will not be able to run itextsharp on the client side. That is why you are getting an error at the .close()
Read more at:
https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/5.0/cryptography-apis-not-supported-on-blazor-webassembly
As for the problem with the image, if you have at the server side it will be able to be used. Otherwise you would need to make it an embedded resource and them stream it in.

How to get the element in BufferedImage [ ]?

I created a program that display images on JTable, so I used BufferedImage [] images. I used the following code to store my images in the images. The program has successfully shows the images on JTable.
int indexFile=0;
String[] fileNames = {"img1.jpg", "img2.jpg","img3.jpg"};
BufferedImage[] images = new BufferedImage[fileNames.length];
for(int j = 0; j<images.length; j++)
try {
fileNo =fileNames[indexFile];
path = "/myJava/resources/"+fileNo;
URL url = myClass.class.getResource(path);
images[j] = ImageIO.read(url);
indexFile++;
}
I want to get the value of the element in images, so I used the following code:
for(int i = 0; i<images.length; i++) {
System.out.println(images[i]) // I am expecting output like "img1.jpg"
}
My problem is, it gives me the following output instead of (e.g. img1, img2, img3).
BufferedImage#e691ea46: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace#cd292449 transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 607 height = 509 #numDataElements 3 dataOff[0] = 2
How can I get this output? ---> img1.jpg
Thank you.

three.js Unproject camera within group

I have a camera as child within a Group object and I need to get the origin/direction:
var cameraRig = new THREE.Group();
cameraRig.add( cameraPerspective );
cameraRig.add( cameraOrtho );
scene.add( cameraRig );
function relativeMousePosition () {
var canvasBoundingBox = renderer.domElement.getBoundingClientRect();
var mouse3D = new THREE.Vector3(0, 0, 0.5);
mouse3D.x = ((mouseX - 0) / canvasBoundingBox.width) * 2 - 1;
mouse3D.y = -((mouseY - 0) / canvasBoundingBox.height) * 2 + 1;
return mouse3D;
}
cameraRig.position.set(89,34,91);
cameraRig.lookAt(something.position);
cameraPerspective.position.set(123,345,123);
var dir = relativeMousePosition().unproject(camera).sub(cameraPerspective.position).normalize();
var origin = cameraPerspective.position;
The above code gives a origin + direction with the context of the cameraRig. When I exclude the camera out, having the scene as direct parent, it gives me the world origin/direction which I want. So how to incorporate the cameraRig to get world origin/direction, so I can do picking or whatever?
FIDDLE: https://jsfiddle.net/647qzhab/1/
UPDATE:
As mentioned in the comment by Falk:
var dir = relativeMousePosition().unproject(camera).sub(cameraPerspective.getWorldPosition()).normalize();
var origin = cameraPerspective.getWorldPosition();
The result is better, but not yet fully satisfiing, as the camera rotation seems not applied yet.
I need to update matrixWorld for the cameraRig:
cameraRig.position.set(89,34,91);
cameraRig.lookAt(something.position);
cameraPerspective.position.set(123,345,123);
cameraRig.updateMatrixWorld(true);
cameraPerspective.updateMatrixWorld(true);

Is there a better way to fix my AS2 preloader?

I have a game with a preloader in scene 1, with the following code on the time line.
stop();
loadingBar._xscale = 1;
var loadingCall:Number = setInterval(preloadSite, 50);
function preloadSite():Void {
var siteLoaded:Number = _root.getBytesLoaded();
var siteTotal:Number = _root.getBytesTotal();
var percentage:Number = Math.round(siteLoaded/siteTotal*100);
loadingBar._xscale = percentage;
bytesDisplay.text = percentage + "%";
if (siteLoaded >= siteTotal) {
clearInterval(loadingCall);
gotoAndPlay("StartMenu", 1);
}
}
The code works fine when there are no music files linked to frame 1. If there are music files linked, then everything loads before the preloader shows up.
I found this great webpage about preloaders, which speaks about the linkage issue, and suggests I put all the big files on frame 2, after the preloader, then skip them. I put my large files on frame 2 as suggested and the preloader worked again.
My question is, is there a better way to do this. This solution seems like a hack.
The only better option I can think of, is to NOT store the MP3 file in your Flash file, but rather load it in your preloader with your flash file's content. This is provided that you're storing your MP3 file somewhere else online (like on a server).
stop();
loadingBar._xscale = 1;
var sound:Sound = new Sound();
sound.loadSound("http://www.example.com/sound.mp3", false);
var loadingCall:Number = setInterval(preloadSite, 50);
function preloadSite():Void {
var siteLoaded:Number = _root.getBytesLoaded()+sound.getBytesLoaded();
var siteTotal:Number = _root.getBytesTotal()+sound.getBytesTotal();
var percentage:Number = Math.round(siteLoaded / siteTotal * 100);
loadingBar._xscale = percentage;
bytesDisplay.text = percentage + "%";
if (siteLoaded >= siteTotal) {
clearInterval(loadingCall);
gotoAndPlay("StartMenu", 1);
sound.start();
}
}

Flex 3 - Enable context menu for text object under a transparent PNG

Here is the situation. In my app I have an overlay layer that is composed of a transparent PNG. I have replaced the hitarea for the png with a 1x1 image using the following code:
[Bindable]
[Embed(source = "/assets/1x1image.png")]
private var onexonebitmapClass:Class;
private function loadCompleteHandler(event:Event):void
{
// Create the bitmap
var onexonebitmap:BitmapData = new onexonebitmapClass().bitmapData;
var bitmap:Bitmap;
bitmap = event.target.content as Bitmap;
bitmap.smoothing = true;
var _hitarea:Sprite = createHitArea(onexonebitmap, 1);
var rect:flash.geom.Rectangle = _box.toFlexRectangle(sprite.width, sprite.height);
var drawnBox:Sprite = new FlexSprite();
bitmap.width = rect.width;
bitmap.height = rect.height;
bitmap.x = -loader.width / 2;
bitmap.y = -loader.height / 2;
bitmap.alpha = _alpha;
_hitarea.alpha = 0;
drawnBox.x = rect.x + rect.width / 2;
drawnBox.y = rect.y + rect.height / 2;
// Add the bitmap as a child to the drawnBox
drawnBox.addChild(bitmap);
// Rotate the object.
drawnBox.rotation = _rotation;
// Add the drawnBox to the sprite
sprite.addChild(drawnBox);
// Set the hitarea to drawnBox
drawnBox.hitArea = _hitarea;
}
private function createHitArea(bitmapData:BitmapData, grainSize:uint = 1):Sprite
{
var _hitarea:Sprite = new Sprite();
_hitarea.graphics.beginFill(0x900000, 1.0);
for (var x:uint = 0; x < bitmapData.width; x += grainSize)
{
for (var y:uint = grainSize; y < bitmapData.height; y += grainSize)
{
if (x <= bitmapData.width && y <= bitmapData.height && bitmapData.getPixel(x, y) != 0)
{
_hitarea.graphics.drawRect(x, y, grainSize, grainSize);
}
}
}
_hitarea.graphics.endFill();
return _hitarea;
}
This is based off the work done here: Creating a hitarea for PNG Image with transparent (alpha) regions in Flex
Using the above code I am able to basically ignore the overlay layer for all mouse events (click, double click, move, etc.) However, I am unable to capture the right click (context menu) event for items that are beneath the overlay.
For instance I have a spell check component that checks the spelling on any textitem and like most other spell checkers if the word is incorrect or not in the dictionary underlines the word in red and if you right click on it would give you a list of suggestions in the contextmenu. This is working great when the text box is not under the overlay, but if the text box is under the overlay I get nothing back.
If anyone can give me some pointers on how to capture the right click event on a textItem that is under a transparent png that would be great.