Tntman 14 Posted May 14, 2020 (edited) Hi, I am making VCL app but I am mixing FMX units in it. Reason why I am mixing FMX units is that i wanted to detect if webCamera exist, I am using this tutorial ( official embarcadero sample ) to detect it and display useful information ( resolution and fps options ) that camera have: http://docwiki.embarcadero.com/CodeExamples/Rio/en/FMX.CameraComponent_Sample This example works fine even in VCL app, but there are some errors and warnings that i am getting when compiling application.. Again, I have to say that it compile with success and it works im just wondering is there any way to fix this issues and warning and should i do ( approach this ) differently ? I know that it is bad to mix VCL and FMX , but unit "FMX.MEDIA" is such a nice unit that gives me a lot of nice features and i cant see similar unit in VCL... I have to mention that I am actually not mixing VISUAL components on form, I am just using only VCL components with FMX.Media unit and methods from it.. Here is error pic: It basically says that it is keeping FMX resources and discarding VCL one Also I have to say that when i comment FMX.Media unit and other places where I am using its code i stop receiving warnings during compiling.. It is obvious that those warnings are because i used FMX.Media unit.. Edited May 14, 2020 by Tntman Share this post Link to post
David Heffernan 2353 Posted May 14, 2020 Wouldn't it just be easier to detect the webcam without trying to mix FMX into the system? Share this post Link to post
Tntman 14 Posted May 14, 2020 4 hours ago, David Heffernan said: Wouldn't it just be easier to detect the webcam without trying to mix FMX into the system? IT is too difficult for me to figure out and understand code samples that i found on the internet for accessing webcamera on windows ( VCL ) .. I am making some sort of twitch bot/streaming application where i plan to exchange data bettwen users and twitch API + Twitch IRC . In my app i want to have feature for user ( streamer ) to have a nice preview what options he have on his camera ( resolution,fps etc ), also I want to add some features like taking a screenshot of his game that he is playing or whole screen, I have 3 options, to make FMX or VCL app. If i want to make FMX app it will be tricky to take screenshot of particular window or whole screen with fmx due to fmx.bitmap nature.. I basically cannot assing bitmap.canvas.handle when i want to take a screenshot. Quote DCDesk := GetWindowDC(GetDesktopWindow); BitBlt(bmpVCL.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, DCDesk, 0, 0, SRCCOPY); this piece of code is impossible if using bmp from FMX.Graphics. So i have to take screenshot with VCL.Graphics.. SO that means that i am using VCL units in my FMX project ( Mixing again .... ) Other option is to make VCL app that will do screenshot as it usually do with VCL.Graphics bitmap. And to use FMX.Media for accessing webcam properties .. ( Mixing again ... ) Third option is to Make VCL app and LEARN how to access camera options in VCL <- Hardest part ( not mixing fmx and vcl ) .... I guess that third option is best way to go and I think that i should try to re-learn and figure out how code that I found online works.. Share this post Link to post
David Heffernan 2353 Posted May 14, 2020 I don't think that mixing VCL and FMX will work. So I'd just rule that out. Share this post Link to post
Cristian Peța 107 Posted May 14, 2020 Accessing camera has nothing to do with VCL or FMX. It should be feasible to copy what FMX.Media.TCameraComponent is basically doing (trimming all the FMX part) and make you own simple component for VCL. At least that's what I would do. Share this post Link to post
Tntman 14 Posted May 14, 2020 1 hour ago, Cristian Peța said: Accessing camera has nothing to do with VCL or FMX. It should be feasible to copy what FMX.Media.TCameraComponent is basically doing (trimming all the FMX part) and make you own simple component for VCL. At least that's what I would do. I was thinking the same, but isn't a delphi compiler doing that behind the scenes ? ( trimming unused code ) ? Share this post Link to post
Cristian Peța 107 Posted May 14, 2020 (edited) TCameraComponent is using FMX.Graphics.TCanvas and you should replace with Vcl.Graphics.TCanvas and so on. Look what TCameraComponent is doing and do the same using Vcl units. Some things are not the same but with some work I think it should be doable. Edited May 14, 2020 by Cristian Peța Share this post Link to post
Tntman 14 Posted May 14, 2020 (edited) I reorganized my code, im now explicitly assigning values from different units. For example bitmapVCL : vcl.graphic.bitmap... Bitmapfmx : fmx.graphic.bitmap and so on... And it is working perfectly fine.. I think i will not have errors in my program if i am not adding visual components like memo from vcl and memo from fmx But i will consider learning/remaking units.. Edited May 14, 2020 by Tntman Share this post Link to post
Remy Lebeau 1436 Posted May 14, 2020 1 hour ago, Tntman said: IT is too difficult for me to figure out and understand code samples that i found on the internet for accessing webcamera on windows ( VCL ) .. There are numerous examples and tutorials online for how to work with webcams using the Win32 API. 1 hour ago, Tntman said: In my app i want to have feature for user ( streamer ) to have a nice preview what options he have on his camera ( resolution,fps etc ) That information is accessible via webcam APIs. You don't need VCL or FMX for that. 1 hour ago, Tntman said: this piece of code is impossible if using bmp from FMX.Graphics. So i have to take screenshot with VCL.Graphics.. SO that means that i am using VCL units in my FMX project ( Mixing again .... ) Or, you could simply take the screenshot using an in-memory GDI bitmap, and then copy the raw pixel data from that bitmap into an FMX TBitmap as needed. Look at CreateCompatibleDC(), CreateCompatibleBitmap(), GetObject(), and TBitmap.Canvas.MapBitmap()/UnmapBitmap(). 1 Share this post Link to post
Tntman 14 Posted May 14, 2020 1 hour ago, Remy Lebeau said: That information is accessible via webcam APIs. You don't need VCL or FMX for that. I know but win api is too difficult for me, but i need to learn it eventually .. 1 hour ago, Remy Lebeau said: Or, you could simply take the screenshot using an in-memory GDI bitmap, and then copy the raw pixel data from that bitmap into an FMX TBitmap as needed. Look at CreateCompatibleDC(), CreateCompatibleBitmap(), GetObject(), and TBitmap.Canvas.MapBitmap()/UnmapBitmap(). I did not even know that this exist, it is really interesting i will definitely take a look into it, thanks BTW, do you know why we have such a difference in size when SS is saved? Here is the code : procedure unasit3(); var DCDesk: hdc; bmpVCL, test: VCL.Graphics.TBitmap; bmpFMX: FMX.Graphics.TBitmap; // bmpVCL -> MS -> MS -> bmpFMX MS: TMemoryStream; begin bmpVCL := VCL.Graphics.TBitmap.Create; bmpVCL.PixelFormat := pf4bit; bmpFMX := FMX.Graphics.TBitmap.Create; MS := TMemoryStream.Create; bmpVCL.Height := Screen.Height; bmpVCL.Width := Screen.Width; DCDesk := GetWindowDC(GetDesktopWindow); BitBlt(bmpVCL.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, DCDesk, 0, 0, SRCCOPY); bmpVCL.SaveToStream(MS); MS.Position := 0; bmpFMX.LoadFromStream(MS); bmpFMX.SaveToFile('unit3FMXBITMAP.png'); bmpVCL.SaveToFile('unit3VCLBITMAP.png'); bmpVCL.Free; bmpFMX.Free; MS.Free; end; VCL Bitmap have 1.31 MB FMX Bitmap have 79 KB Thats size on disk .. When I open images they look 100% the same , i cant see the difference in quality even if i zoom in .. is there any explanation for that strange behavior ? Share this post Link to post
David Heffernan 2353 Posted May 14, 2020 6 minutes ago, Tntman said: is there any explanation for that strange behavior ? The FMX bitmap that you save is a compressed bitmap. The VCL bitmap is a Windows bitmap, uncompressed. 1 Share this post Link to post
Remy Lebeau 1436 Posted May 15, 2020 (edited) 5 hours ago, Tntman said: BTW, do you know why we have such a difference in size when SS is saved? VCL's TBitmap supports only the BMP format (and actual BMPs, not JPEG/PNG-encoded BMPs that recent Windows versions support). Saving a VCL TBitmap to a file with a ".png" extension DOES NOT create a PNG image, it creates a BMP image. PNG is compressed, whereas BMP is (usually) not (though VCL's TBitmap can load a compressed BMP - I think - but it does not produce compressed BMPs). FMX's TBitmap supports many formats, including BMP and PNG. Saving an FMX TBitmap to a file with a ".png" extension creates a real PNG image. Try saving your FMX TBitmap to a file with a ".bmp" extension and you will see a result closer to what VCL's TBitmap creates. Quote When I open images they look 100% the same BMP and PNG are both lossless formats. The pixel data in both formats may represent the same color arrangements to a viewer, but the way the data is stored in memory and in a file are very different. Edited May 15, 2020 by Remy Lebeau Share this post Link to post
Cristian Peța 107 Posted May 16, 2020 (edited) On 5/15/2020 at 12:04 AM, Tntman said: I know but win api is too difficult for me Then probably what I proposed (to adapt the component from FMX to VCL) is also too difficult for you. On 5/15/2020 at 12:04 AM, Tntman said: BTW, do you know why we have such a difference in size when SS is saved? uses Vcl.Imaging.pngimage; procedure SaveBitmapToPNG(ABitmap: TBitmap; const AFileName: String; ACompresionLevel: Integer = 7); var img: TPngImage; strm: TFileStream; begin img := nil; strm := TFileStream.Create(AFileName, fmCreate); try img := TPngImage.Create; img.CompressionLevel := ACompresionLevel; img.Assign(ABitmap); img.SaveToStream(strm); finally strm.Free; img.Free; end; end; Here TBitmap is a Vcl.Graphics.TBitmap Edited May 16, 2020 by Cristian Peța Share this post Link to post
Remy Lebeau 1436 Posted May 16, 2020 (edited) All VCL TGraphic-derived classes have a SaveToFile() method, you don't need to save to a TFileStream manually: uses Vcl.Imaging.PngImage; procedure SaveBitmapToPNG(ABitmap: TBitmap; const AFileName: String; ACompresionLevel: Integer = 7); var img: TPngImage; begin img := TPngImage.Create; try img.CompressionLevel := ACompresionLevel; img.Assign(ABitmap); img.SaveToFile(AFileName); finally img.Free; end; end; Edited May 16, 2020 by Remy Lebeau Share this post Link to post
Cristian Peța 107 Posted May 17, 2020 You are right, I didn't noticed. I made this procedure in a hurry from my code and there I need to save to a stream. Share this post Link to post
Tntman 14 Posted August 12, 2020 Guys, I am sorry. I had problems IRL, i abandoned all of my projects, I did not had time to play with them , but I will be back soon I guess and resume coding Share this post Link to post