Jump to content

shineworld

Members
  • Content Count

    321
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by shineworld

  1. shineworld

    Transferring TBitmap to Python and back

    The way to manage FPU exceptions in DELPHI is not the same on Python so you have to add this in your Delphi unit: initialization MaskFPUExceptions(True); PS: Actually I've moved from PIL to SKIA in image management. Skia offers more features than Pillow. import skia ... . ... # frame_inp is a numpy containing RGB image # convert numpy image from RGB to RGBA (add AlphaBlend layer) skia_frame = cv2.cvtColor(frame_inp, cv2.COLOR_RGB2RGBA) # create a skia image from numpy RGBA array skia_image = skia.Image.fromarray(skia_frame) # sample of image resize with skia image_ratio = 1.0 image_width = skia_image.width() image_height = skia_image.height() camera_image_width = self.CameraImage.Width camera_image_height = self.CameraImage.Height r_w = image_width / camera_image_width r_h = image_height / camera_image_height if r_w > 1.0 or r_h > 1.0: image_ratio = max(r_w, r_h) image_width = int(image_width / image_ratio) image_height = int(image_height / image_ratio) skia_image = skia_image.resize(image_width, image_height, skia.FilterQuality.kLow_FilterQuality) skia_frame = skia_image.toarray() # sample of antialiasing drawings on skia paint = skia.Paint(AntiAlias=True, Color=skia.ColorRED) canvas = skia.Canvas(skia_frame) canvas.drawLine(0, int(image_height / 2), image_width, int(image_height / 2), paint) canvas.drawLine(int(image_width / 2), 0, int(image_width / 2), image_height, paint) # back skia image to numpy array RGB skia_frame = cv2.cvtColor(skia_frame, cv2.COLOR_RGBA2RGB) # draw of numpy array RGB to delphi Image ext.update_image_from_bytes( self.CameraImage, skia_frame.tobytes(), skia_frame.shape[1], skia_frame.shape[0], 3 if len(skia_frame.shape) == 3 else 1 ) self.CameraImage.Repaint()
  2. shineworld

    delphivcl and PyLint

    Hi all, there is a way to inform PyLint about delphivcl types ? I've tried to add it to .pylintrc without results: [MASTER] # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code. extension-pkg-allow-list= # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code. (This is an alternative name to extension-pkg-allow-list # for backward compatibility.) extension-pkg-whitelist=cv2,delphivcl # Return non-zero exit code if any of these messages/categories are detected, # even if score is above --fail-under value. Syntax same as enable. Messages # specified are enabled, while categories only check already-enabled messages. fail-on= ... .. .
  3. shineworld

    Transferring TBitmap to Python and back

    I've left only the upon described code in my extension so you can evaluate the code to check if meets your needs. cnc_vision_video_ext.7z
  4. shineworld

    Transferring TBitmap to Python and back

    Delphi Extension way vs Pillow using time.time_perf: # delphi module extension way t1 = time.perf_counter() ext.update_image_from_bytes( self.CameraImage, frame_inp.tobytes(), frame_inp.shape[1], frame_inp.shape[0], 3 if len(frame_inp.shape) == 3 else 1) self.CameraImage.Repaint() t2 = time.perf_counter() # pillow way t3 = time.perf_counter() rgb_im: PIL_Image.Image = PIL_Image.fromarray(np.uint8(frame_inp[...,[2,1,0]].copy())).convert('RGB') self.CameraImage.Picture.Bitmap.SetSize(rgb_im.width, rgb_im.height) dib = PIL_ImageWin.Dib(rgb_im) dib.expose(self.CameraImage.Picture.Bitmap.Canvas.Handle) self.CameraImage.Repaint() t4 = time.perf_counter() # timings report self.Caption = 'EXT = {:7.3f} ms - PILLOW {:7.3f}'.format(t2 - t1, t4 - t3) Delphi way take half time in this case 🙂
  5. shineworld

    Transferring TBitmap to Python and back

    To fastly send an image in NumPy array to a delphivcl.Image component, without use Pillow and DIB way, you can create a new python extension module with Delphi where you wrap a update_image_from_bytes(image: Image(), data: bytes, width: int, height: int, channels: int) -> bool { generic functions wrappers } function CncVisionUpdateImageFromBytesArray_Wrapper(pself, args: PPyObject): PPyObject; cdecl; var Image: TImage; Width: Integer; Height: Integer; Channels: Integer; Bytes: TByteArray; BytesPyObj: PPyObject; ImagePyObj: PPyObject; function PyBytesAsBytes(Obj: PPyObject): TByteArray; var Size: NativeInt; Buffer: PAnsiChar; begin Result := nil; with GetPythonEngine do begin if not PyBytes_Check(Obj) then Exit; PyBytes_AsStringAndSize(Obj, Buffer, Size); if Size = 0 then Exit; SetLength(Result, Size); CopyMemory(Result, Buffer, Size); end; end; begin with GetPythonEngine do begin try if PyArg_ParseTuple(args, 'OOiii:update_image_from_bytes', @ImagePyObj, @BytesPyObj, @Width, @Height, @Channels) <> 0 then begin if ImagePyObj.ob_type.tp_name <> 'Image' then AbortFast; Image := TPyDelphiImage(TPyObject(PAnsiChar(ImagePyObj) + SizeOf(PyObject))).DelphiObject; if Image = nil then AbortFast; if BytesPyObj.ob_type.tp_name <> 'bytes' then AbortFast; Bytes := PyBytesAsBytes(BytesPyObj); if Bytes = nil then AbortFast; if Length(Bytes) <> (Width * Height * Channels) then AbortFast; if not CncVisionUpdateImageFromBytesArray(Image, Bytes, Width, Height, Channels) then AbortFast; Result := ReturnTrue; end else Result := ReturnFalse; except Result := ReturnFalse; end; end; end; ... . ... procedure TPyExtensionManager.WrapperInitializationEvent(Sender: TObject); begin FWrapper.RegisterFunction ( PAnsiChar('update_image_from_bytes'), CncVisionUpdateImageFromBytesArray_Wrapper, PAnsiChar('update delphivcl Image object from bytes array with width, height & channels') ); end; Then the pascal byte array to Image is: function CncVisionUpdateImageFromBytesArray(Image: TImage; Bytes: osCncVisionTypes.TByteArray; Width, Height, Channels: Integer): Boolean; type TRGBBitmapInfoHeader = record Header: TBitmapInfoHeader; ColorTable: array[0..255] of TRGBQuad; end; PBitmapInfoHeader = ^TBitmapInfoHeader; var I: Integer; Bitmap: TBitmap; IsGray: Boolean; Buffer: TRGBBitmapInfoHeader; BmpInfoHeader: PBitmapInfoHeader; var BmpInfoBuffer: TBitmapInfo absolute Buffer; begin try if Length(Bytes) = 0 then Exit(False); if Length(Bytes) <> (Width * Height * Channels) then Exit(False); if not Channels in [1, 3] then Exit(False); if Image.Picture.Bitmap = nil then Image.Picture.Bitmap := TBitmap.Create; Bitmap := Image.Picture.Bitmap; Bitmap.Width := Width; Bitmap.Height := Height; BmpInfoHeader := PBitmapInfoHeader(@Buffer); BmpInfoHeader^.biSize := SizeOf(TBitmapInfoHeader); BmpInfoHeader^.biWidth := Width; BmpInfoHeader^.biHeight := -Height; BmpInfoHeader^.biPlanes := 1; BmpInfoHeader^.biBitCount := 8 * Channels; BmpInfoHeader^.biCompression := BI_RGB; BmpInfoHeader^.biSizeImage := 0; BmpInfoHeader^.biXPelsPerMeter := 0; BmpInfoHeader^.biYPelsPerMeter := 0; BmpInfoHeader^.biClrUsed := 0; BmpInfoHeader^.biClrImportant := 0; // if Bytes array is for monochrome image (channels = 1) normalizes bitmap color table // https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader // // The BITMAPINFOHEADER structure may be followed by an array of palette entries or color masks. // The rules depend on the value of biCompression. // // - If biCompression equals BI_RGB and the bitmap uses 8 bpp or less, the bitmap has a color table immediately // following the BITMAPINFOHEADER structure. The color table consists of an array of RGBQUAD values. The size // of the array is given by the biClrUsed member. If biClrUsed is zero, the array contains the maximum number // of colors for the given bitdepth; that is, 2^biBitCount colors. if Channels = 1 then begin for I := 0 to 255 do begin Buffer.ColorTable[I].rgbBlue := I; Buffer.ColorTable[I].rgbGreen := I; Buffer.ColorTable[I].rgbRed := I; end; end; LockWindowUpdate(Bitmap.Canvas.Handle); try Result := SetDIBitsToDevice ( Bitmap.Canvas.Handle, // handle to device context 0, // x-coordinate of upper-left corner of 0, // y-coordinate of upper-left corner of Width, // source rectangle width Height, // source rectangle height 0, // x-coordinate of Lower-left corner of 0, // y-coordinate of Lower-left corner of 0, // first scan line in array Height, // number of scan lines Bytes, // address of array with DIB bits BmpInfoBuffer, // address of structure with bitmap info DIB_RGB_COLORS // RGB or palette indexes ) > 0; finally LockWindowUpdate(0) end; except Result := False; end; end; CncVisionUpdateImageFromBytesArray permits RGB or Monochrome Bytes array. In python the code to update image is simple: import cnc_vision_ext as ext # this is only my delphi extension module for python where extra features for delphivcl are placed # for monochrome frames to CameraImage (delphivcl.Image object) frame = get_frame_image_from_somewhere() frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) ext.update_image_from_bytes( self.CameraImage, frame_inp.tobytes(), frame_inp.shape[1], frame_inp.shape[0], 3 if len(frame_inp.shape) == 3 else 1) self.CameraImage.Invalidate() # for color frames to CameraImage (delphivcl.Image object) frame = get_frame_image_from_somewhere() ext.update_image_from_bytes( self.CameraImage, frame_inp.tobytes(), frame_inp.shape[1], frame_inp.shape[0], 3 if len(frame_inp.shape) == 3 else 1) self.CameraImage.Invalidate()
  6. Hi all, I'm using DelphiVCL + PyScripter to develop a Python windows application.I've created and "pyd" extension module in which perform some critical time operations or add support functions missing in DelphiVCL. - In python script I create an Image - now I would like to send a bytes array to cnc_vision_ext module (made with Delphi): import delphivcl import cnc_vision_ext as ext .... my_Image = delphivcl.Image(Form1) ext.update_image_from_bytes(my_image, 1024, 768, 3) Now in the wrapper CncVisionUpdateImageFromBytesArray_Wrapper I need to extract the TImage instance contained in PPyObject of args. I was not able to find the right way.... { generic functions wrappers } function CncVisionUpdateImageFromBytesArray_Wrapper(pself, args: PPyObject): PPyObject; cdecl; var Image: TImage; Width: Integer; Height: Integer; Channels: Integer; Bytes: TByteArray; ImagePyObj: PPyObject; begin with GetPythonEngine do begin if PyArg_ParseTuple(args, 'Oiii:update_image_from_bytes', @ImagePyObj, @Width, @Height, @Channels) <> 0 then begin // ??? HOW TO GET BACK wrapped TImage from Image() object created with my_image = delphivcl.Image(owner) ??? Image := TImage((PythonToDelphi(ImagePyObj) as TPyDelphiObject).DelphiObject); Result := PyUnicodeFromString ( Format('%s %d %d %d', [Image.Name, Width, Height, Channels]) ); end else Result := nil; end; end; { TPyExtensionManager } procedure TPyExtensionManager.WrapperInitializationEvent(Sender: TObject); begin FWrapper.RegisterDelphiWrapper(TPyCncVisionVideoCapturePxc_Wrapper); FWrapper.RegisterFunction ( PAnsiChar('update_image_from_bytes'), CncVisionUpdateImageFromBytesArray_Wrapper, PAnsiChar('update delphivcl Image object from bytes array with width, height & channels') ); FWrapper.RegisterFunction ( PAnsiChar('get_usb_camera_device_list'), CncVisionGetUSBCameraDeviceList_Wrapper, PAnsiChar('get list of available usb camera devices') ); end; Thanks in advance for the suggestions.... Best Regards Silverio
  7. shineworld

    get back a Image() object created from Python

    Seems this works but is hard to say OK, at moment, for me: { A B C +-------------------++------------------------------------------------------+ | PyObject header || TPyObject class | +----------+--------++-----------------+------------+----------+------------+ |ob_refcnt |ob_type ||hidden Class Ptr |PythonType |IsSubType |PythonAlloc | |integer |pointer ||pointer |TPythonType |Boolean |Boolean | |4 bytes |4 bytes ||4 bytes |4 bytes |1 byte |1 byte | +----------+--------++-----------------+------------+----------+------------+ ^ ^ | | ptr returned ptr returned by Adjust by GetSelf - a Python object must start at A. - a Delphi class class must start at B - TPyObject.InstanceSize will return C-B - Sizeof(TPyObject) will return C-B - The total memory allocated for a TPyObject instance will be C-A, even if its InstanceSize is C-B. - When turning a Python object pointer into a Delphi instance pointer, PythonToDelphi will offset the pointer from A to B. - When turning a Delphi instance into a Python object pointer, GetSelf will offset Self from B to A. - Properties ob_refcnt and ob_type will call GetSelf to access their data. } function CncVisionUpdateImageFromBytesArray_Wrapper(pself, args: PPyObject): PPyObject; cdecl; var Image: TImage; Width: Integer; Height: Integer; Channels: Integer; Bytes: TByteArray; ImagePyObj: PPyObject; begin with GetPythonEngine do begin if PyArg_ParseTuple(args, 'Oiii:update_image_from_bytes', @ImagePyObj, @Width, @Height, @Channels) <> 0 then begin Image := TPyDelphiImage(TPyObject(PAnsiChar(ImagePyObj)+Sizeof(PyObject))).DelphiObject; Result := PyUnicodeFromString ( Format('%s %d %d %d', [Image.Name, Width, Height, Channels]) ); end else Result := nil; end; end;
  8. shineworld

    Transferring TBitmap to Python and back

    TVideoCapture is managed as a record, not a class, with class members so do not requires a TVideoCapture.Create It is defined in videoio.inc. Never tried if this structure permits more than one instance. I've checked the demos and copied/pasted the minimal code to try it. My actual implementation is yet on Python + delphivcl + opencv. It's a very big project and I'm yet in the writting phase. When finished I will try to recreate my vision python framework directly in Delphi code + DelphiPythonVCL.
  9. shineworld

    Transferring TBitmap to Python and back

    In the dropbox link, I can't attach files bigger than 4.8Mb here, you can find a very simple Delphi Sydney 10.4.1 project where the OpenCV get frames from a USB camera (VideoCapture device 0) and with the trackbar, you can apply Canny filter thresholds 1 & 2. The required DLLs are in Win64\Debug & Release folders BUT can also be placed one time for always in Windows OS folders. Just my first test with Delphi-OpenCV. ONLY 64 bit applications are supported by Delphi-OpenCV class. https://www.dropbox.com/s/iqzlnfwttj20pnr/cnc_vision_2.7z?dl=0 PS: I don't know if there are other MS dependencies because I've Microsoft Visual Studio installed and some DLL could be already available for MSVC packages. During run-in IDE these are modules loaded: Module Load: cnc_vision_2. No Debug Info. Base Address: $0000000000400000. Process cnc_vision_2.exe (14340) Module Load: ntdll.dll. No Debug Info. Base Address: $00007FFD371B0000. Process cnc_vision_2.exe (14340) Module Load: KERNEL32.dll. No Debug Info. Base Address: $00007FFD36870000. Process cnc_vision_2.exe (14340) Module Load: KERNELBASE.dll. No Debug Info. Base Address: $00007FFD34BA0000. Process cnc_vision_2.exe (14340) Module Load: WINSPOOL.DRV. No Debug Info. Base Address: $00007FFD2AF90000. Process cnc_vision_2.exe (14340) Module Load: SHELL32.dll. No Debug Info. Base Address: $00007FFD36930000. Process cnc_vision_2.exe (14340) Module Load: WINMM.dll. No Debug Info. Base Address: $00007FFD2B2A0000. Process cnc_vision_2.exe (14340) Module Load: msvcp_win.dll. No Debug Info. Base Address: $00007FFD34FC0000. Process cnc_vision_2.exe (14340) Module Load: COMCTL32.dll. No Debug Info. Base Address: $00007FFD26F50000. Process cnc_vision_2.exe (14340) Module Load: msvcrt.dll. No Debug Info. Base Address: $00007FFD35B40000. Process cnc_vision_2.exe (14340) Module Load: ucrtbase.dll. No Debug Info. Base Address: $00007FFD348D0000. Process cnc_vision_2.exe (14340) Module Load: msvcrt.dll. No Debug Info. Base Address: $0000000000D50000. Process cnc_vision_2.exe (14340) Module Unload: msvcrt.dll. Process cnc_vision_2.exe (14340) Module Load: msvcrt.dll. No Debug Info. Base Address: $0000000000DF0000. Process cnc_vision_2.exe (14340) Module Unload: msvcrt.dll. Process cnc_vision_2.exe (14340) Module Load: USER32.dll. No Debug Info. Base Address: $00007FFD35BE0000. Process cnc_vision_2.exe (14340) Module Load: GDI32.dll. No Debug Info. Base Address: $00007FFD370E0000. Process cnc_vision_2.exe (14340) Module Load: win32u.dll. No Debug Info. Base Address: $00007FFD34F20000. Process cnc_vision_2.exe (14340) Module Load: win32u.dll. No Debug Info. Base Address: $00000000001A0000. Process cnc_vision_2.exe (14340) Module Unload: win32u.dll. Process cnc_vision_2.exe (14340) Module Load: OLEAUT32.dll. No Debug Info. Base Address: $00007FFD35390000. Process cnc_vision_2.exe (14340) Module Load: gdi32full.dll. No Debug Info. Base Address: $00007FFD34A00000. Process cnc_vision_2.exe (14340) Module Load: VERSION.dll. No Debug Info. Base Address: $00007FFD2DB50000. Process cnc_vision_2.exe (14340) Module Load: combase.dll. No Debug Info. Base Address: $00007FFD36460000. Process cnc_vision_2.exe (14340) Module Load: RPCRT4.dll. No Debug Info. Base Address: $00007FFD35540000. Process cnc_vision_2.exe (14340) Module Load: ADVAPI32.dll. No Debug Info. Base Address: $00007FFD36140000. Process cnc_vision_2.exe (14340) Module Load: SECHOST.dll. No Debug Info. Base Address: $00007FFD36290000. Process cnc_vision_2.exe (14340) Module Load: ole32.dll. No Debug Info. Base Address: $00007FFD36330000. Process cnc_vision_2.exe (14340) Module Load: NETAPI32.dll. No Debug Info. Base Address: $00007FFD21B00000. Process cnc_vision_2.exe (14340) Module Load: netutils.dll. No Debug Info. Base Address: $00007FFD33E40000. Process cnc_vision_2.exe (14340) Module Load: IMM32.dll. No Debug Info. Base Address: $00007FFD356A0000. Process cnc_vision_2.exe (14340) Module Load: MSCTF.dll. No Debug Info. Base Address: $00007FFD35210000. Process cnc_vision_2.exe (14340) Module Load: UxTheme.dll. No Debug Info. Base Address: $00007FFD32280000. Process cnc_vision_2.exe (14340) Module Load: AppCore.dll. No Debug Info. Base Address: $00007FFD32800000. Process cnc_vision_2.exe (14340) Module Load: bcryptPrimitives.dll. No Debug Info. Base Address: $00007FFD34B10000. Process cnc_vision_2.exe (14340) Module Load: WTSAPI32.dll. No Debug Info. Base Address: $00007FFD2F7C0000. Process cnc_vision_2.exe (14340) Module Load: WINSTA.dll. No Debug Info. Base Address: $00007FFD33640000. Process cnc_vision_2.exe (14340) Module Load: opencv_world455.dll. No Debug Info. Base Address: $00007FFCE7660000. Process cnc_vision_2.exe (14340) Module Load: WS2_32.dll. No Debug Info. Base Address: $00007FFD35D80000. Process cnc_vision_2.exe (14340) Module Load: COMDLG32.dll. No Debug Info. Base Address: $00007FFD35460000. Process cnc_vision_2.exe (14340) Module Load: SHCORE.dll. No Debug Info. Base Address: $00007FFD367C0000. Process cnc_vision_2.exe (14340) Module Load: SHLWAPI.dll. No Debug Info. Base Address: $00007FFD35330000. Process cnc_vision_2.exe (14340) Module Load: VCRUNTIME140.dll. No Debug Info. Base Address: $00007FFD21D40000. Process cnc_vision_2.exe (14340) Module Load: CONCRT140.dll. No Debug Info. Base Address: $00007FFD231C0000. Process cnc_vision_2.exe (14340) Module Load: MSVCP140.dll. No Debug Info. Base Address: $00007FFD14770000. Process cnc_vision_2.exe (14340) Module Load: VCRUNTIME140_1.dll. No Debug Info. Base Address: $0000000000830000. Process cnc_vision_2.exe (14340) Module Unload: VCRUNTIME140_1.dll. Process cnc_vision_2.exe (14340) Module Load: VCRUNTIME140_1.dll. No Debug Info. Base Address: $00007FFD2F5D0000. Process cnc_vision_2.exe (14340) Module Load: opencv_videoio_msmf455_64.dll. No Debug Info. Base Address: $00007FFD22EB0000. Process cnc_vision_2.exe (14340) Module Load: MF.dll. No Debug Info. Base Address: $00007FFD20830000. Process cnc_vision_2.exe (14340) Module Load: MFReadWrite.dll. No Debug Info. Base Address: $00007FFD1F890000. Process cnc_vision_2.exe (14340) Module Load: dxgi.dll. No Debug Info. Base Address: $00007FFD33210000. Process cnc_vision_2.exe (14340) Module Load: MFPlat.DLL. No Debug Info. Base Address: $00007FFD060C0000. Process cnc_vision_2.exe (14340) Module Load: CFGMGR32.dll. No Debug Info. Base Address: $00007FFD351C0000. Process cnc_vision_2.exe (14340) Module Load: d3d11.dll. No Debug Info. Base Address: $00007FFD300B0000. Process cnc_vision_2.exe (14340) Module Load: MFCORE.dll. No Debug Info. Base Address: $00007FFCE71D0000. Process cnc_vision_2.exe (14340) Module Load: CRYPT32.dll. No Debug Info. Base Address: $00007FFD35060000. Process cnc_vision_2.exe (14340) Module Load: bcrypt.dll. No Debug Info. Base Address: $00007FFD349D0000. Process cnc_vision_2.exe (14340) Module Load: POWRPROF.dll. No Debug Info. Base Address: $00007FFD33EA0000. Process cnc_vision_2.exe (14340) Module Load: ksuser.dll. No Debug Info. Base Address: $00007FFD32120000. Process cnc_vision_2.exe (14340) Module Load: CRYPTBASE.dll. No Debug Info. Base Address: $00007FFD342A0000. Process cnc_vision_2.exe (14340) Module Load: RTWorkQ.DLL. No Debug Info. Base Address: $00007FFD1D060000. Process cnc_vision_2.exe (14340) Module Load: UMPDC.dll. No Debug Info. Base Address: $00007FFD33D10000. Process cnc_vision_2.exe (14340) Module Load: CLBCatQ.DLL. No Debug Info. Base Address: $00007FFD36010000. Process cnc_vision_2.exe (14340) Module Load: DEVENUM.DLL. No Debug Info. Base Address: $00007FFD252A0000. Process cnc_vision_2.exe (14340) Module Load: SETUPAPI.dll. No Debug Info. Base Address: $00007FFD356D0000. Process cnc_vision_2.exe (14340) Module Load: NTMARTA.dll. No Debug Info. Base Address: $00007FFD335A0000. Process cnc_vision_2.exe (14340) Module Load: DEVOBJ.dll. No Debug Info. Base Address: $00007FFD34670000. Process cnc_vision_2.exe (14340) Module Load: WINTRUST.dll. No Debug Info. Base Address: $00007FFD34F50000. Process cnc_vision_2.exe (14340) Module Load: MSASN1.dll. No Debug Info. Base Address: $00007FFD344B0000. Process cnc_vision_2.exe (14340) Module Load: msdmo.dll. No Debug Info. Base Address: $00007FFD2C5B0000. Process cnc_vision_2.exe (14340) Module Load: QCap.dll. No Debug Info. Base Address: $00007FFD16770000. Process cnc_vision_2.exe (14340) Module Load: QUARTZ.dll. No Debug Info. Base Address: $00007FFD145A0000. Process cnc_vision_2.exe (14340) Module Load: Windows.Storage.dll. No Debug Info. Base Address: $00007FFD32A00000. Process cnc_vision_2.exe (14340) Module Load: Wldp.dll. No Debug Info. Base Address: $00007FFD34330000. Process cnc_vision_2.exe (14340) Module Load: Source.dll. No Debug Info. Base Address: $00007FFD166B0000. Process cnc_vision_2.exe (14340) Module Load: ATL.DLL. No Debug Info. Base Address: $00007FFD24C60000. Process cnc_vision_2.exe (14340) Module Load: MFSENSORGROUP.dll. No Debug Info. Base Address: $00007FFD15110000. Process cnc_vision_2.exe (14340) Module Load: ksproxy.ax. No Debug Info. Base Address: $00007FFD14550000. Process cnc_vision_2.exe (14340) Module Load: d3d9.dll. No Debug Info. Base Address: $00007FFD2CF10000. Process cnc_vision_2.exe (14340) Module Load: dwmapi.dll. No Debug Info. Base Address: $00007FFD32510000. Process cnc_vision_2.exe (14340) Module Load: policymanager.dll. No Debug Info. Base Address: $00007FFD2F4A0000. Process cnc_vision_2.exe (14340) Module Load: msvcp110_win.dll. No Debug Info. Base Address: $00007FFD33A30000. Process cnc_vision_2.exe (14340) Module Load: vidcap.dll. No Debug Info. Base Address: $00007FFD24C50000. Process cnc_vision_2.exe (14340) Module Load: kswdmcap.dll. No Debug Info. Base Address: $00007FFD23190000. Process cnc_vision_2.exe (14340) Module Load: MFC42.dll. No Debug Info. Base Address: $00007FFCF43E0000. Process cnc_vision_2.exe (14340) Module Load: QEdit.dll. No Debug Info. Base Address: $00007FFD144A0000. Process cnc_vision_2.exe (14340) Module Load: gdiplus.dll. No Debug Info. Base Address: $00007FFD2B040000. Process cnc_vision_2.exe (14340) Module Load: MSVFW32.dll. No Debug Info. Base Address: $00007FFD1F210000. Process cnc_vision_2.exe (14340) Module Load: DDRAW.dll. No Debug Info. Base Address: $00007FFCFC5D0000. Process cnc_vision_2.exe (14340) Module Load: DCIMAN32.dll. No Debug Info. Base Address: $00007FFD238F0000. Process cnc_vision_2.exe (14340) Module Load: nvldumdx.dll. No Debug Info. Base Address: $00007FFD2ADB0000. Process cnc_vision_2.exe (14340) Module Load: imagehlp.dll. No Debug Info. Base Address: $00007FFD35670000. Process cnc_vision_2.exe (14340) Module Load: CRYPTSP.dll. No Debug Info. Base Address: $00007FFD34280000. Process cnc_vision_2.exe (14340) Module Load: RSAENH.dll. No Debug Info. Base Address: $00007FFD339A0000. Process cnc_vision_2.exe (14340) Module Load: NVD3DUMX.dll. No Debug Info. Base Address: $00007FFCC5A50000. Process cnc_vision_2.exe (14340) Module Load: nvspcap64.dll. No Debug Info. Base Address: $00007FFD09D00000. Process cnc_vision_2.exe (14340) Module Load: profapi.dll. No Debug Info. Base Address: $00007FFD34810000. Process cnc_vision_2.exe (14340) Module Load: NvCameraWhitelisting64.dll. No Debug Info. Base Address: $00007FFD14410000. Process cnc_vision_2.exe (14340) Module Unload: NvCameraWhitelisting64.dll. Process cnc_vision_2.exe (14340) Module Load: dxcore.dll. No Debug Info. Base Address: $00007FFD2B680000. Process cnc_vision_2.exe (14340) Module Unload: NVD3DUMX.dll. Process cnc_vision_2.exe (14340) Module Unload: nvldumdx.dll. Process cnc_vision_2.exe (14340) Module Load: nvldumdx.dll. No Debug Info. Base Address: $00007FFD2ADB0000. Process cnc_vision_2.exe (14340) Module Load: NVD3DUMX.dll. No Debug Info. Base Address: $00007FFCC5A50000. Process cnc_vision_2.exe (14340) Module Load: NvCameraWhitelisting64.dll. No Debug Info. Base Address: $00007FFD14410000. Process cnc_vision_2.exe (14340) Module Unload: NvCameraWhitelisting64.dll. Process cnc_vision_2.exe (14340) Module Unload: NVD3DUMX.dll. Process cnc_vision_2.exe (14340) Module Unload: nvldumdx.dll. Process cnc_vision_2.exe (14340) Module Load: nvldumdx.dll. No Debug Info. Base Address: $00007FFD2ADB0000. Process cnc_vision_2.exe (14340) Module Load: NVD3DUMX.dll. No Debug Info. Base Address: $00007FFCC5A50000. Process cnc_vision_2.exe (14340) Module Load: NvCameraWhitelisting64.dll. No Debug Info. Base Address: $00007FFD14410000. Process cnc_vision_2.exe (14340) Module Unload: NvCameraWhitelisting64.dll. Process cnc_vision_2.exe (14340) Module Unload: NVD3DUMX.dll. Process cnc_vision_2.exe (14340) Module Unload: nvldumdx.dll. Process cnc_vision_2.exe (14340) Module Load: WINMMBASE.dll. No Debug Info. Base Address: $00007FFD22CE0000. Process cnc_vision_2.exe (14340) Module Load: MSYUV.dll. No Debug Info. Base Address: $00007FFD238E0000. Process cnc_vision_2.exe (14340) Module Unload: MSYUV.dll. Process cnc_vision_2.exe (14340) Module Load: TextInputFramework.dll. No Debug Info. Base Address: $00007FFD2B430000. Process cnc_vision_2.exe (14340) Module Load: CoreUIComponents.dll. No Debug Info. Base Address: $00007FFD31640000. Process cnc_vision_2.exe (14340) Module Load: CoreMessaging.dll. No Debug Info. Base Address: $00007FFD319A0000. Process cnc_vision_2.exe (14340) Module Load: WinTypes.dll. No Debug Info. Base Address: $0000000007A20000. Process cnc_vision_2.exe (14340) Module Load: WinTypes.dll. No Debug Info. Base Address: $0000000007B80000. Process cnc_vision_2.exe (14340) Module Unload: WinTypes.dll. Process cnc_vision_2.exe (14340) Module Unload: WinTypes.dll. Process cnc_vision_2.exe (14340) Module Load: WinTypes.dll. No Debug Info. Base Address: $00007FFD30ED0000. Process cnc_vision_2.exe (14340) Module Load: OLEACC.dll. No Debug Info. Base Address: $00007FFD2AF20000. Process cnc_vision_2.exe (14340)
  10. shineworld

    Transferring TBitmap to Python and back

    IMO, you have two solutions: a) Use the new, but experimental, Delphi-OpenCV-Class (opencv 4.5.5) for Delphi 10.4 & 11.0 package: https://github.com/Laex/Delphi-OpenCV-Class Laex is doing a very very good job to import opencv 4.5.5 C++ based DLLs to Delphi. I don't know how much of opencv is already ported but I've cloned the project only yesterday and tried a basic Canny function: Works very very fastly, with native Delphi (in the snapshot I've got frames from a USB camera and applied canny filter). During run-in IDE environment there are some delays (also in Release) because uses debug versions of DLLs, but when you close the IDE and start the program from Explorer BOOM is a rocket. I will move, only in the next future, my Python delphivcl application to be a native Delphi set of classes. This ONLY to fully integrate into Forms of native VCL program. b) To back processed image to Delphi just pass the opencv NumPy array content which can be o monodimensional array for gray images or a tridimensional array for images with RGB. Pass also Width and Height info. Then you have only to use a Bitmap, and related canvas HDC Handle with the same width and height and use DIB windows functions to recreate bitmap image from a byte array. This is an extract of yesterday's experiments for upon Image. TMat is the Laex generics implementation of OpenCV mat so array of bytes of image: function MatDraw(DC: HDC; Image: TMat; const Rect: TRect; const Stretch: Boolean = True): Boolean; type pCOLORREF = ^COLORREF; pBITMAPINFOHEADER = ^BITMAPINFOHEADER; var // isrgb: Boolean; IsGray: Boolean; buf: array [1 .. SizeOf(BITMAPINFOHEADER) + SizeOf(RGBQUAD) * 256] of byte; dibhdr: pBITMAPINFOHEADER; _dibhdr: TBitmapInfo ABSOLUTE buf; _rgb: pCOLORREF; i: Integer; iResult: Integer; begin if Image.empty then Exit(False); // isrgb := ('R' = upcase(img^.colorModel[0])) and ('G' = upcase(img^.colorModel[1])) and ('B' = upcase(img^.colorModel[2])); // isgray := 'G' = upcase(img^.colorModel[0]); IsGray := Image.channels = 1; // if (not isgray) and (not isrgb) then // Exit(false); // if (1 = img^.nChannels) and (not isgray) then // Exit(false); dibhdr := pBITMAPINFOHEADER(@buf); _rgb := pCOLORREF(Integer(dibhdr) + SizeOf(BITMAPINFOHEADER)); if (IsGray) then for i := 0 to 255 do _rgb[i] := rgb(i, i, i); dibhdr^.biSize := SizeOf(BITMAPINFOHEADER); dibhdr^.biWidth := Image.cols; // Check origin for display // if img^.Origin = 0 then dibhdr^.biHeight := -Image.rows; // else // dibhdr^.biHeight := img^.Height; dibhdr^.biPlanes := 1; dibhdr^.biBitCount := 8 * Image.channels; dibhdr^.biCompression := BI_RGB; dibhdr^.biSizeImage := 0; // img^.imageSize; dibhdr^.biXPelsPerMeter := 0; dibhdr^.biYPelsPerMeter := 0; dibhdr^.biClrUsed := 0; dibhdr^.biClrImportant := 0; if Stretch then begin SetStretchBltMode(DC, COLORONCOLOR); SetMapMode(DC, MM_TEXT); // Stretch the image to fit the rectangle iResult := StretchDIBits(DC, Rect.Left, Rect.Top, Rect.Width, Rect.Height, 0, 0, Image.cols, Image.rows, Image.Data, _dibhdr, DIB_RGB_COLORS, SRCCOPY); Result := (iResult > 0); // and (iResult <> GDI_ERROR); end else begin // Draw without scaling iResult := SetDIBitsToDevice(DC, Rect.Left, Rect.Top, Image.cols, Image.rows, 0, 0, 0, Image.rows, Image.Data, _dibhdr, DIB_RGB_COLORS); Result := (iResult > 0); // and (iResult <> GDI_ERROR); end; end; Code went from Laex library sources so try to read them.
  11. shineworld

    OnMouseDown/Up events

    Hi, all I'm trying to use Python extension from Embarcadero: https://github.com/Embarcadero/DelphiVCL4Python installed in Python 3.9 (32 bits) with pip install delphivcl I was able to assign an OnClick event (in a Button): # creates jogs buttons btnXM = Button(self) btnXM.Parent = pgOne btnXM.Caption = 'X-' btnXM.Left = 8 btnXM.Top = 10 btnXP = Button(self) btnXP.Parent = pgOne btnXP.Caption = 'X+' btnXP.Left = btnXM.Left + btnXM.Width + 8 btnXP.Top = 10 def ClickEventHandler(Sender): pass btnXP.OnClick = self.jogClickEvent def MouseDownHandler(Sender, State, Button, X, Y): pass btnXP.OnMouseDown = MouseDownHandler but when reaches the btnXP.OnMouseDown Python notice this error: *** Remote Interpreter Reinitialized *** Traceback (most recent call last): File "D:\x\develop\qem\rosetta_cnc_1\python-scripts\pyipctcpjsonvcl-demo.py", line 249, in <module> main() File "D:\x\develop\qem\rosetta_cnc_1\python-scripts\pyipctcpjsonvcl-demo.py", line 241, in main f = MainForm(Application) File "D:\x\develop\qem\rosetta_cnc_1\python-scripts\pyipctcpjsonvcl-demo.py", line 67, in __init__ btnXP.OnMouseDown = MouseDownHandler AttributeError: Error in setting property OnMouseDown Error: No Registered EventHandler for events of type "TMouseEvent Looking at btnXP dir(): print(btnXP.__dir__()) ['__bound__', '__dir__', '__owned__', 'Action', 'AfterConstruction', 'Align', 'AlignDisabled', 'AlignWithMargins', 'Anchors', 'Assign', 'BeforeDestruction', 'BeginDrag', 'BeginInvoke', 'BiDiMode', 'BindMethodsToEvents', 'BoundsRect', 'BringToFront', 'Broadcast', 'Brush', 'Cancel', 'CanFocus', 'Caption', 'CheckNonMainThreadUsage', 'ClassInfo', 'ClassName', 'ClassNameIs', 'ClassParent', 'ClassType', 'CleanupInstance', 'Click', 'ClientHeight', 'ClientOrigin', 'ClientRect', 'ClientToParent', 'ClientToScreen', 'ClientWidth', 'CommandLinkHint', 'ComObject', 'ComponentCount', 'ComponentIndex', 'Components', 'ComponentState', 'ComponentStyle', 'Constraints', 'ContainsControl', 'ControlAtPos', 'ControlCount', 'Controls', 'ControlState', 'ControlStyle', 'Create', 'CreateParented', 'CreateParentedControl', 'CurrentPPI', 'Cursor', 'CustomHint', 'Default', 'DefaultHandler', 'DesignInfo', 'Destroy', 'DestroyComponents', 'Destroying', 'DisableAlign', 'DisabledImageIndex', 'DisabledImageName', 'DisabledImages', 'Dispatch', 'DisposeOf', 'Dock', 'DockClientCount', 'DockDrop', 'DockManager', 'DockOrientation', 'DockSite', 'DoubleBuffered', 'DragCursor', 'DragDrop', 'Dragging', 'DragKind', 'DragMode', 'DrawTextBiDiModeFlags', 'DrawTextBiDiModeFlagsReadingOnly', 'DropDownMenu', 'ElevationRequired', 'EnableAlign', 'Enabled', 'EndDrag', 'EndFunctionInvoke', 'EndInvoke', 'Equals', 'ExecuteAction', 'ExplicitHeight', 'ExplicitLeft', 'ExplicitTop', 'ExplicitWidth', 'FieldAddress', 'FindChildControl', 'FindComponent', 'FlipChildren', 'Floating', 'FloatingDockSiteClass', 'Focused', 'Font', 'Free', 'FreeInstance', 'FreeNotification', 'FreeOnRelease', 'GetChildren', 'GetControlsAlignment', 'GetEnumerator', 'GetHashCode', 'GetInterface', 'GetInterfaceEntry', 'GetInterfaceTable', 'GetNamePath', 'GetParentComponent', 'GetStyleName', 'GetSystemMetrics', 'GetTabControlList', 'GetTabOrderList', 'GetTextBuf', 'GetTextLen', 'Handle', 'HandleAllocated', 'HandleNeeded', 'HasParent', 'Height', 'HelpContext', 'HelpKeyword', 'HelpType', 'Hide', 'Hint', 'HostDockSite', 'HotImageIndex', 'HotImageName', 'ImageAlignment', 'ImageIndex', 'ImageMargins', 'ImageName', 'Images', 'InheritsFrom', 'InitiateAction', 'InitInstance', 'InsertComponent', 'InsertControl', 'InstanceSize', 'Invalidate', 'IsCustomStyleActive', 'IsDrawingLocked', 'IsImplementorOf', 'IsLightStyleColor', 'IsRightToLeft', 'Left', 'LockDrawing', 'LRDockWidth', 'ManualDock', 'ManualFloat', 'Margins', 'MethodAddress', 'MethodName', 'ModalResult', 'MouseInClient', 'MouseWheelHandler', 'Name', 'NewInstance', 'Observers', 'OnClick', 'OnContextPopup', 'OnDragDrop', 'OnDragOver', 'OnDropDownClick', 'OnEndDock', 'OnEndDrag', 'OnEnter', 'OnExit', 'OnGesture', 'OnKeyDown', 'OnKeyPress', 'OnKeyUp', 'OnMouseActivate', 'OnMouseDown', 'OnMouseEnter', 'OnMouseLeave', 'OnMouseMove', 'OnMouseUp', 'OnStartDock', 'OnStartDrag', 'Owner', 'Padding', 'PaintTo', 'Parent', 'ParentBiDiMode', 'ParentCustomHint', 'ParentDoubleBuffered', 'ParentFont', 'ParentShowHint', 'ParentToClient', 'ParentWindow', 'Perform', 'PixelsPerInch', 'PopupMenu', 'PreProcessMessage', 'PressedImageIndex', 'PressedImageName', 'QualifiedClassName', 'Realign', 'RedrawDisabled', 'ReferenceInterface', 'Refresh', 'RemoveComponent', 'RemoveControl', 'RemoveFreeNotification', 'Repaint', 'ReplaceDockedControl', 'SafeCallException', 'ScaleBy', 'ScaleFactor', 'ScaleForPPI', 'ScaleRectSize', 'ScaleValue', 'ScreenToClient', 'ScrollBy', 'SelectedImageIndex', 'SelectedImageName', 'SendToBack', 'SetBounds', 'SetDesignVisible', 'SetFocus', 'SetParentComponent', 'SetProps', 'SetSubComponent', 'SetTextBuf', 'Show', 'ShowHint', 'Showing', 'Style', 'StyleElements', 'StyleName', 'StylusHotImageIndex', 'StylusHotImageName', 'TabOrder', 'TabStop', 'Tag', 'TBDockHeight', 'ToList', 'Top', 'ToString', 'ToTuple', 'Touch', 'UndockHeight', 'UndockWidth', 'UnitName', 'UnitScope', 'UnlockDrawing', 'Update', 'UpdateAction', 'UpdateControlState', 'UseDockManager', 'UseRightToLeftAlignment', 'UseRightToLeftReading', 'UseRightToLeftScrollBar', 'VCLComObject', 'Visible', 'VisibleDockClientCount', 'Width', 'WindowProc', 'WordWrap'] OnMouseDown/Up are exposed.... I'm not able to understand what I've missed... Thank you in advance for suggestions
  12. shineworld

    OnMouseDown/Up events

    I'm not used with github fork/push/request of pull but I've open a pull request: https://github.com/Embarcadero/python4delphi/pull/25 I hope it is the right way to do...
  13. shineworld

    Syndney 10.4.1 missing NumberBox

    Hi all. There is a way to detect if compile phase is in Delphi 10.4.1 or 10.4.2 ? At Embarcadero documentation they notice only VER340 and compiler 34.0 for either: https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Compiler_Versions but VCL from 10.4.1 and 10.4.2 is different and in 10.4.1 NumberBox is not available. This block 10.4.1 users to compile PythonVCL design package or force them, at any pull, to manually remove any reference to NumberBox where present in check: {$IFDEF DELPHI10_4_OR_HIGHER} ... {$ENDIF DELPHI10_4_OR_HIGHER}.
  14. shineworld

    Place image in a TImage

    Initially failed to understand how in Demo29 the use of PIL allowed to place an image in a TImage object. But slowly I succeeded: rgb_im = PIL_Image.fromarray(np.uint8(frame)).convert('RGB') self.imgFrameI.Picture.Bitmap.SetSize(rgb_im.width, rgb_im.height) dib = PIL_ImageWin.Dib(rgb_im) dib.expose(self.imgFrameI.Picture.Bitmap.Canvas.Handle) self.imgFrameI.Repaint() rgb_im = PIL_Image.fromarray(np.uint8(frame_out)).convert('RGB') self.imgFrameO.Picture.Bitmap.SetSize(rgb_im.width, rgb_im.height) dib = PIL_ImageWin.Dib(rgb_im) dib.expose(self.imgFrameO.Picture.Bitmap.Canvas.Handle) self.imgFrameO.Repaint() Now perfectly works and from 30FPS of PySimpleGUI version, I've reached 89 stable FPS with delphivcl version. AMAZING how fast delphi vcl is"
  15. shineworld

    python delphivcl development

    I'm converting a complex Python PySimpleGUI based program to Python using delphivcl module. In my initial test, the gained speed on UI things sees delphivcl as a very winner. But I need to add some missing features in delphivcl controls as well as the possibility to modify an Image (TImage) content sending it as an array of bitmap (NumPy arrays) instead to have to create a file.bmp and then load it with Image.Picture.LoadFromFile. Also, I need to add OnMouseDown/OnMouseUp in buttons. Gitting delphivcl, or delphifmx, I was not able to find the delphi building project, only the final files. Where I can find sources and projects to make delphivcl module and so to add new features?
  16. shineworld

    python delphivcl development

    Thanks for the info. I remember your suggestion to report the request in github in the issue department. I haven't done it yet because first I would like to try to do something myself, both because I started studying P4D sources and making some modules, and to actually understand how many things are necessary to cover my needs and that they are then useful to everyone. . The project I'm converting from PySimpleGUI is a real-time object recognition system that uses OpenCV and other AI technologies with complicated UIs that need to be really fast, hence the choice of switching to DelphiVCL and / or DelphiFMX. Thanks again for the support.
  17. shineworld

    SynEdit preferred version?

    GetIt is a very useful tool, just a click to install, but if you want to be always on the piece and aligned to the latest changes is better to work directly with sources in github.
  18. shineworld

    Place image in a TImage

    I have not yet found a fast way to load TImage contents starting from a NumPy array... this method is enough fast BUT require a file support (at 30FPS SSD will suffer a lot): # gets and shows frame image storing it in a support file bmp_image = cv2.imencode('.bmp', frame)[1].tobytes() stream = BytesIO(bmp_image) with open("f:\output_a.bmp", "wb") as f: f.write(stream.getbuffer()) f.close() self.imgFrameI.Picture.LoadFromFile("f:\output_a.bmp") this method access to TImage canvas but is VERY SLOW: self.imgFrameI.Picture.Bitmap.SetSize(640, 480) canvas = self.imgFrameI.Picture.Bitmap.Canvas rgb_im = PIL_Image.fromarray(frame) for x in range(640): for y in range(480): b, g, r = rgb_im.getpixel((x, y)) rgb = b * 65536 + g * 256 + r canvas.SetPixel(x, y, rgb) There is some other way to set Picture of a Image() object from a image array ?
  19. shineworld

    Place image in a TImage

    I was not able to update image content directly from data in memory, but only passing from a support file: def __on_timer_update(self, sender): # gets frame frame = cvc.video_capture_get_frame() bmp_image = cv2.imencode('.bmp', frame)[1].tobytes() # shows frame image storing it in a support file stream = BytesIO(bmp_image) with open("output.bmp", "wb") as f: f.write(stream.getbuffer()) f.close() self.imgFrame.Picture.LoadFromFile("output.bmp") This works but I would like to avoid working with files because 60 FPS are dangerous for SSD devices. There is some other way to assign the image, in this case a BMP to be simple, directly to an Image() object using python + DelphiVCL library module ?
  20. Hi all. I'm trying to create a Python Extension Module with Delphi Sydney. I'm adding an IPC Engine Client to access to one or more IPC Engine Server (either based on Windows Messages). It works and is very a good tool. I've only a question about the resulting python class that does not have a list of properties/methods, not in all cases. Looking at xxx.__dir__ I can get the list of available methods: But if I use the code completion of PyScripter only base TPyDelphiPersistent are available: Strangely if I create a pre-made istance TPyIPCEngineClient object and I add it to the module as SetVar('myIPC', xxxx, xxx) all TPyIPCEngineClient are showed. What I'm mistaking ? Thank you in advance for replies. pycncipc1.zip
  21. shineworld

    List of most popular UI components for VCL

    My preferred: Image32 SynEdit GLScene
  22. shineworld

    Delphi 11, migrate or wait

    The hard thing with a new environment, eg: Sydney vs Alexandria, is to move all 3rd parties libraries (often to re-buy), but overall learn workaround on always present IDE issues. The time to discover a problem with an IDE and tool-chain and learn the right workarounds to continue to work is a long activity. Back from new created file project to old, in case of very critical issues are a very waste of time.
  23. shineworld

    OnMouseDown/Up events

    @pyscripter I will do it surely! I'm trying initially to use the tools as they are. In the second phase, I will try to put my hands on it!
  24. Hi all. I'm new to JSON frameworks and I'm getting lost in a spoonful of water. In the Sydney help I've found this code: JSONValue := TJSONObject.ParseJSONValue('{"colors":[{"name":"red", "hex":"#f00"}]}'); Memo1.Lines.Add('READER:'); if JSONValue is TJSONArray then //... else if JSONVAlue is TJSONObject then Memo1.Lines.Add('colors'); Memo1.Lines.Add('name: '+ JSONValue.GetValue<string>('colors[0].name')); Memo1.Lines.Add('hex: '+ JSONValue.GetValue<string>('colors[0].hex')); Now this works fine but I need to read a client request so formatted: var Text: string; Command: string; JsonValue: TJSONValue; JsonValueArg: TJSONValue; begin // parse json JSONValue := TJSONObject.ParseJSONValue('{"cmd":"program.add.text", "txt":"for I := 0 to 100 do"}'); if not (JSONValue is TJSONObject) then Exit; // gets command type (in Command I've found the "cmd" value "program.add.text". ALL RIGHT!!!) if JSONValue.TryGetValue('cmd', Command) then Exit; // gets command argument txt (does not found the "txt" value and program EXITS!!!) if JSONValue.TryGetValue('txt', Text) then Exit; //... I can't change the JSON request string to contain an array as well as in the Embarcardero sample because reach from a customer program and I've checked with only JSON validator and seem to be fine. What was I've mistaken? Thank you in advance for your replies.
  25. shineworld

    Simple JSON parsing

    I'm not aware of that, I'm an occasional user of Indy classes. So on TIdTTCPServerContex.Execute is better do not manage exceptions on WriteLn because are correctly managed in TidTCPServer.Execute caller? To be honest I've got some issues during close application when I do TIdTCPServer.Active := False and TIdTCPServer.Free; with connected clients... Could be because I catch the exceptions on Execute().... and the caller doesn't manage the right closing states. I've changed to: procedure TIPCTCPServerContext.Execute; type TRequestType = ( rqtpCmd, rqtpGet, rqtpSet ); var ArgS: string; ArgI: Integer; Command: string; Request: string; Response: string; JsonValue: TJSONValue; RequestType: TRequestType; begin // sets default response Response := RES_NULL; // extracts request from tcp stack Request := Trim(Connection.IOHandler.ReadLn); try // gets request type JSONValue := TJSONObject.ParseJSONValue(Request); try if not (JSONValue is TJSONObject) then Exit; while True do begin if JSONValue.TryGetValue(REQ_CMD, Command) then begin RequestType := rqtpCmd; Break; end; if JSONValue.TryGetValue(REQ_GET, Command) then begin RequestType := rqtpGet; Break; end; if JSONValue.TryGetValue(REQ_SET, Command) then begin RequestType := rqtpSet; Break; end; Exit; end; // evaluates request type case RequestType of rqtpCmd: begin if Command = 'cnc.homing' then begin if not JSONValue.TryGetValue<Integer>('["axes.mask"]', ArgI) then Exit; Response := DoCmdCNCHoming(ArgI); end else if Command = 'cnc.mdi.command' then begin if not JSONValue.TryGetValue('command', ArgS) then Exit; Response := DoCmdCNCMDICommand(ArgS); end else if Command = 'cnc.pause' then Response := DoCmdCNCPause else if Command = 'cnc.resume.after.pause' then Response := DoCmdCNCResumeAfterPause else if Command = 'cnc.resume.after.stop' then begin if JSONValue.TryGetValue<Integer>('line', ArgI) then Response := DoCmdCNCResumeAfterStop(ArgI) else Response := DoCmdCNCResumeAfterStop(0); end else if Command = 'cnc.start' then begin if JSONValue.TryGetValue<Integer>('line', ArgI) then Response := DoCmdCNCStart(ArgI) else Response := DoCmdCNCStart(0); end else if Command = 'cnc.stop' then Response := DoCmdCNCStop else if Command = 'program.analysis' then begin if JSONValue.TryGetValue('mode', ArgS) then Response := DoCmdProgramAnalysis(ArgS) else Response := DoCmdProgramAnalysis(''); end else if Command = 'program.analysis.abort' then Response := DoCmdProgramAnalysisAbort else if Command = 'program.gcode.add.text' then begin if not JSONValue.TryGetValue('text', ArgS) then Exit; Response := DoCmdProgramGCodeAddText(ArgS); end else if Command = 'program.gcode.clear' then Response := DoCmdProgramGCodeClear else if Command = 'program.gcode.set.text' then begin if not JSONValue.TryGetValue('text', ArgS) then Exit; Response := DoCmdProgramGCodeSetText(ArgS); end else if Command = 'program.load' then begin if not JSONValue.TryGetValue('name', ArgS) then Exit; Response := DoCmdProgramLoad(ArgS); end else if Command = 'program.new' then Response := DoCmdProgramNew else if Command = 'program.save' then begin if JSONValue.TryGetValue('name', ArgS) then Response := DoCmdProgramSave(ArgS) else Response := DoCmdProgramSave('') end else Exit; end; rqtpGet: begin if Command = 'axes.info' then Response := DoGetAxesInfo else if Command = 'cnc.info' then Response := DoGetCNCInfo else if Command = 'compile.info' then Response := DoGetCompileInfo else if Command = 'system.info' then Response := DoGetSystemInfo else Exit; end; rqtpSet: begin //## end; end; finally JSONValue.Free; end; finally Connection.IOHandler.WriteLn(Response); end; end; Should be more right now...
×