How to display picture(jpg) with TDBImage from TBlobField? - delphi

I want to display image from database that was set to blobdata type.
But when i pair with TDBImage show error
anyone can help?

I have been using this code to load any kind of image from Database.
uses
Vcl.Graphics, PNGImage, JPEG;
function GetHeader(const AFile: string; const AByteCount: integer): string;
const
HEADER_STR = '%s_HEADER: array [0 .. %d] of byte = (%s)';
var
_HeaderStream: TMemoryStream;
_FileStream: TMemoryStream;
_Buf: integer;
_Ext: string;
_FullByteStrArr: string;
_ByteStr: string;
i: integer;
begin
Result := '';
if not FileExists(AFile) then
Exit;
_HeaderStream := TMemoryStream.Create;
_FileStream := TMemoryStream.Create;
try
_FileStream.LoadFromFile(AFile);
_FileStream.Position := 0;
_HeaderStream.CopyFrom(_FileStream, 5);
if _HeaderStream.Size > 4 then
begin
_HeaderStream.Position := 0;
_ByteStr := '';
_FullByteStrArr := '';
for i := 0 to AByteCount do
begin
_HeaderStream.Read(_Buf, 1);
_ByteStr := IntToHex(_Buf, 2);
_FullByteStrArr := _FullByteStrArr + ', $' +
Copy(_ByteStr, Length(_ByteStr) - 1, 2);
end;
_FullByteStrArr := Copy(_FullByteStrArr, 3, Length(_FullByteStrArr));
_Ext := UpperCase(ExtractFileExt(AFile));
_Ext := Copy(_Ext, 2, Length(_Ext));
Result := Format(HEADER_STR, [_Ext, AByteCount, _FullByteStrArr]);
end;
finally
FreeAndNil(_FileStream);
FreeAndNil(_HeaderStream);
end;
end;
function GetImageFromBlob(const ABlobField: TBlobField): TGraphic;
CONST
JPG_HEADER: array [0 .. 2] of byte = ($FF, $D8, $FF);
GIF_HEADER: array [0 .. 2] of byte = ($47, $49, $46);
BMP_HEADER: array [0 .. 1] of byte = ($42, $4D);
PNG_HEADER: array [0 .. 3] of byte = ($89, $50, $4E, $47);
TIF_HEADER: array [0 .. 2] of byte = ($49, $49, $2A);
TIF_HEADER2: array [0 .. 2] of byte = (77, 77, 00);
PCX_HEADER: array [0 .. 2] of byte = (10, 5, 1);
var
_HeaderStream: TMemoryStream;
_ImgStream: TMemoryStream;
_GraphicClassName: string;
_GraphicClass: TGraphicClass;
begin
Result := nil;
_HeaderStream := TMemoryStream.Create;
_ImgStream := TMemoryStream.Create;
try
ABlobField.SaveToStream(_ImgStream);
_ImgStream.Position := 0;
_HeaderStream.CopyFrom(_ImgStream, 5);
if _HeaderStream.Size > 4 then
begin
if CompareMem(_HeaderStream.Memory, #JPG_HEADER, SizeOf(JPG_HEADER)) then
_GraphicClassName := 'TJPEGImage'
else if CompareMem(_HeaderStream.Memory, #GIF_HEADER, SizeOf(GIF_HEADER))
then
_GraphicClassName := 'TGIFImage'
else if CompareMem(_HeaderStream.Memory, #PNG_HEADER, SizeOf(PNG_HEADER))
then
_GraphicClassName := 'TPNGImage'
else if CompareMem(_HeaderStream.Memory, #BMP_HEADER, SizeOf(BMP_HEADER))
then
_GraphicClassName := 'TBitmap'
else if CompareMem(_HeaderStream.Memory, #TIF_HEADER, SizeOf(TIF_HEADER))
then
_GraphicClassName := 'TWICImage'
else if CompareMem(_HeaderStream.Memory, #TIF_HEADER2, SizeOf(TIF_HEADER2))
then
_GraphicClassName := 'TWICImage'
else if CompareMem(_HeaderStream.Memory, #PCX_HEADER, SizeOf(PCX_HEADER))
then
_GraphicClassName := 'PCXImage';
RegisterClasses([TIcon, TMetafile, TBitmap, TJPEGImage, TPngImage,
TWICImage]);
_GraphicClass := TGraphicClass(FindClass(_GraphicClassName));
if (_GraphicClass <> nil) then
begin
Result := _GraphicClass.Create; // Create appropriate graphic class
_ImgStream.Position := 0;
Result.LoadFromStream(_ImgStream);
end;
end;
finally
FreeAndNil(_ImgStream);
FreeAndNil(_HeaderStream);
end;
end;
{ --- Usage --- }
procedure TForm1.BitBtn5Click(Sender: TObject);
begin
qImage.Close;
qImage.ParamByName('prm_id').Value := Edit2.Text;
qImage.Open;
Image1.Picture.Assign(GetImageFromBlob(qImageany_kind_image));
Image1.Picture.SaveToFile('C:\Users\Edijs\Desktop\test.' +
GraphicExtension(TGraphicClass
(GetClass(Image1.Picture.Graphic.ClassName))));
end;

In your case you can use just the *.bmp files , to use *.jpeg files
You must use JPEG unit :
Uses
JPEG;

Related

Delphi FFMPEG CUDA hardware accelerated video decoding generating shadows

I'm trying to use cuda hardware accelerated video decoding, loading from a .mp4 file, according to the code bellow, but getting the image with shadows
Specification:
FFMPEG 4.3
Delphi 10.3
NVIDIA GeForce RTX 3050 Laptop GPU 4Gb DDR6
Intel Core i5 11400H 16 Gb RAM
unit UVideoDecoding;
interface
uses
Vcl.Graphics, Winapi.Windows,
System.SysUtils, System.Classes,
libavcodec, libavdevice,
libavfilter, libswresample, libavformat, libavutil,
libswscale;
type
TDecoder = class
protected
fFormatCtx: PAVFormatContext;
fCodec: PAVCodec;
fCodecParams, fLocalCodecParams: PAVCodecParameters;
fCodecCtx: libavcodec.PAVCodecContext;
fPacket: PAVPacket;
fFrameIn, fFrameOut: PAVFrame;
fScaler: PSwsContext;
fVideoStreamIndex: Integer;
fHWPixelFormat: AVPixelFormat;
fOutputWidth: Integer;
fOutputHeight: Integer;
function DecodeVideoPacket: Integer;
public
function Load(pFileName: string): Integer;
end;
implementation
function TDecoder.Load(pFileName: string): Integer;
var
vCount: Integer;
vLocalCodec: PAVCodec;
vFileName: AnsiString;
vType: AVHWDeviceType;
vDecPackResponse: Integer;
begin
vType := av_hwdevice_find_type_by_name('cuda');
{vType = AV_HWDEVICE_TYPE_CUDA}
fFormatCtx := avformat_alloc_context;
vFileName := AnsiString(pFileName);
avformat_open_input(fFormatCtx, PAnsiChar(vFileName), nil, nil);
avformat_find_stream_info(fFormatCtx, nil);
for vCount := 0 to fFormatCtx.nb_streams - 1 do
begin
fLocalCodecParams := fFormatCtx.streams[vCount].codecpar;
case fLocalCodecParams.codec_id of
AVCodecID.AV_CODEC_ID_H264: vLocalCodec := avcodec_find_decoder_by_name('h264_cuvid');
AVCodecID.AV_CODEC_ID_HEVC: vLocalCodec := avcodec_find_decoder_by_name('hevc_cuvid');
AVCodecID.AV_CODEC_ID_MJPEG: vLocalCodec := avcodec_find_decoder_by_name('mjpeg_cuvid');
AVCodecID.AV_CODEC_ID_MPEG4: vLocalCodec := avcodec_find_decoder_by_name('mpeg4_cuvid');
else
vLocalCodec := avcodec_find_decoder(fLocalCodecParams.codec_id);
end;
if fLocalCodecParams.codec_type = AVMEDIA_TYPE_VIDEO then
begin
fVideoStreamIndex := vCount;
fCodec := vLocalCodec;
fCodecParams := fLocalCodecParams;
end;
end;
{fCodec.name = h264_cuvid}
fCodecCtx := avcodec_alloc_context3(fCodec);
var vHWDeviceCtx: PAVBufferRef;
try
if av_hwdevice_ctx_create(vHWDeviceCtx, vType, nil, nil, 0) >= 0 then
fCodecCtx.hw_device_ctx := av_buffer_ref(vHWDeviceCtx);
finally
av_buffer_unref(vHWDeviceCtx);
end;
avcodec_open2(fCodecCtx, fCodec, nil);
{
fCodecCtx.codec_id = AV_CODEC_ID_H264
fCodecCtx.pix_fmt = AV_PIX_FMT_MMAL
}
fFrameIn := av_frame_alloc;
fFrameOut := av_frame_alloc;
fFrameOut.format := Integer(AV_PIX_FMT_BGRA);
fFrameOut.width := 640;
fFrameOut.height := 480;
//On getting sws_context I've tried srcFormat = AV_PIX_FMT_MMAL but the result was nil
fScaler := sws_getContext(fCodecCtx.Width, fCodecCtx.Height, AV_PIX_FMT_NV12{fCodecCtx.pix_fmt},
fOutputWidth, fOutputHeight, AV_PIX_FMT_BGRA, SWS_BILINEAR, nil, nil, nil);
fPacket := av_packet_alloc;
while (av_read_frame(fFormatCtx, fPacket) >= 0) do
begin
if fPacket.stream_index = fVideoStreamIndex then
begin
vDecPackResponse := DecodeVideoPacket;
av_packet_unref(fPacket);
if vDecPackResponse < 0 then
Break;
end
end;
Exit(0);
end;
function TDecoder.DecodeVideoPacket: Integer;
var
vResponse: Integer;
vBmp: Vcl.Graphics.TBitmap;
vScaleResult, vSize: Integer;
vBuffer: PByte;
vSWFrame, vTMPFrame: pAVFrame;
begin
Result := 0;
vResponse := avcodec_send_packet(fCodecCtx, fPacket);
if vResponse < 0 then
Exit(vResponse);
while (vResponse >= 0) do
begin
vResponse := avcodec_receive_frame(fCodecCtx, fFrameIn);
if (vResponse = AVERROR_EAGAIN) or (vResponse = AVERROR_EOF) then
Break
else if vResponse < 0 then
Exit(vResponse);
if vResponse >= 0 then
begin
vSWFrame := av_frame_alloc;
if av_hwframe_transfer_data(vSWFrame, fFrameIn, 0) >= 0 then
vTMPFrame := vSWFrame
else
vTMPFrame := fFrameIn;
vSize := av_image_get_buffer_size(AVPixelFormat(vTMPFrame.format), vTMPFrame.width, vTMPFrame.height, 1);
vBuffer := av_malloc(vSize);
if Assigned(vBuffer) then
av_image_copy_to_buffer(vBuffer, vSize, #vTMPFrame.data, #vTMPFrame.linesize, AVPixelFormat(vTMPFrame.format), vTMPFrame.width, vTMPFrame.height, 1);
MoveMemory(vTMPFrame.data[0], vBuffer, vSize);
vTMPFrame.data[0] := vTMPFrame.data[0] + vTMPFrame.linesize[0] * (fCodecCtx.height - 1);
vTMPFrame.linesize[0] := vTMPFrame.linesize[0] * -1;
vTMPFrame.data[1] := vTMPFrame.data[1] + vTMPFrame.linesize[1] * (fCodecCtx.height div 2 - 1);
vTMPFrame.linesize[1] := vTMPFrame.linesize[1] * -1;
vTMPFrame.data[2] := vTMPFrame.data[2] + vTMPFrame.linesize[2] * (fCodecCtx.height div 2 - 1);
vTMPFrame.linesize[2] := vTMPFrame.linesize[2] * -1;
vScaleResult := sws_scale(fScaler, #vTMPFrame.Data, #vTMPFrame.Linesize, 0,
fCodecCtx.Height, #fFrameOut.data, #fFrameOut.Linesize);
if vScaleResult <= 0 then
begin
Break;
end;
vBmp := Vcl.Graphics.TBitmap.Create;
try
vBmp.Height := fOutputHeight;
vBmp.Width := fOutputWidth;
vBmp.PixelFormat := TPixelFormat.pf32bit;
MoveMemory(PByte(vBmp.ScanLine[vBmp.Height -1]),
fFrameOut.data[0], fOutputHeight * fFrameOut.linesize[0]);
//Renders BMP on main thread
// if Assigned(fOnBitmap) then
// fOnBitmap(vBmp);
finally
av_frame_unref(vSWFrame);
av_frame_free(vTMPFrame);
av_freep(#vBuffer);
FreeAndNil(vBmp);
Result := 1;
end;
end;
end;
end;
end.
I've tried using different pixelformats but none of them properly decoded the video.

MAPISendMail access violation

I have a problem with MapiSendMail function of MAPI32.dll. Everything seems fine, message is completed, then I send it by winapi function, and i get an Access violation error, it happend in MAPISendMail. Here's the fragment of the code:
MAPIModule := LoadLibrary(PWideChar(MAPIDLL));
if MAPIModule = 0 then
Result := -1
else
try
#SM := GetProcAddress(MAPIModule, 'MAPISendMail');
if #SM <> nil then
begin
Result := SM(0, application.Handle, Msg, MAPI_DIALOG {or MAPI_LOGON_UI}, 0);
end
else
Result := 1;
finally
end;
Also I was trying to change GetProcAddres to MAPISendMailW or MAPISendMailHelper, but then #SM was nil.
#Edit1
function TMail._SendMAPIEmail(const aTo, aAtts: array of AnsiString; const body, subject, SenderName, SenderEmail: string; ShowError: Boolean = true): Integer;
var
SM: TFNMapiSendMail;
Msg: MapiMessage;
lpSender: MapiRecipDesc;
Recips: array of MapiRecipDesc;
Att: array of MapiFileDesc;
TempAttNames: array of pAnsiChar;
TempAttNamesAnsi: array of AnsiString;
TempAttPaths: array of pAnsiChar;
TempRecip: array of pAnsiChar;
p1, LenTo, LenAtts: Integer;
MAPIModule: HModule;
sError: String;
i: integer;
begin
try
FillChar(Msg, SizeOf(Msg), 0);
{ get the length of all arrays passed to this function }
LenTo := length(aTo);
if Trim(aAtts[0]) <> '' then
LenAtts := length(aAtts)
else
LenAtts := 0;
{ ... }
SetLength(Recips, LenTo);
SetLength(TempRecip, LenTo);
Setlength(Att, LenAtts);
SetLength(TempAttNames, LenAtts);
SetLength(TempAttPaths, LenAtts);
SetLength(TempAttNamesAnsi, LenAtts);
{ to }
for p1 := 0 to LenTo - 1 do
begin
FillChar(Recips[p1], SizeOf(Recips[p1]), 0);
Recips[p1].ulReserved := 0;
Recips[p1].ulRecipClass := MAPI_TO;
{ Upgrade }
Recips[p1].lpszName := '';
TempRecip[p1] := pAnsichar(aTo[p1]);
Recips[p1].lpszAddress := TempRecip[p1];
end;
{ atts }
for p1 := 0 to LenAtts - 1 do
begin
FillChar(Att[p1], SizeOf(Att[p1]), 0);
FillChar(TempAttPaths[p1], SizeOf(pAnsiChar), 0);
FillChar(TempAttNames[p1], SizeOf(pAnsiChar), 0);
FillChar(TempAttNamesAnsi[01], SizeOf(AnsiChar), 0);
Att[p1].ulReserved := 0;
Att[p1].flFlags := 0;
Att[p1].nPosition := Cardinal($FFFFFFFF);
{ Upgrade }
TempAttPaths[p1] := pAnsichar(aAtts[p1]);
Att[p1].lpszPathName := TempAttPaths[p1];
TempAttNamesAnsi[p1] := AnsiString((ExtractFileName(string(aAtts[p1]))));
TempAttNames[p1] := pAnsiChar(TempAttNamesAnsi[p1]);
Att[p1].lpszFileName := TempAttNames[p1];
end;
{ fill the message }
with Msg do
begin
ulReserved := 0;
if subject <> '' then
{ Upgrade }
lpszSubject := pAnsichar(AnsiString(subject));
if body <> '' then
{ Upgrade }
lpszNoteText := pAnsichar(AnsiString(body));
if SenderEmail <> '' then
begin
lpSender.ulRecipClass := MAPI_ORIG;
if SenderName = '' then
lpSender.lpszName := pAnsichar(AnsiString(SenderEmail))
else
lpSender.lpszName := pAnsichar(AnsiString(SenderName));
lpSender.lpszAddress := pAnsichar(AnsiString(SenderEmail));
lpSender.ulEIDSize := 0;
lpSender.lpEntryID := nil;
lpOriginator := #lpSender;
end
else
Msg.lpOriginator := nil;
Msg.lpszMessageType := nil;
Msg.lpszDateReceived := nil;
Msg.lpszConversationID := nil;
Msg.flFlags := 0;
Msg.nRecipCount := LenTo;
Msg.lpRecips := #Recips[0];
Msg.nFileCount := LenAtts;
Msg.lpFiles := #Att[0];
end;
MAPIModule := LoadLibrary(PWideChar(MAPIDLL));
if MAPIModule = 0 then
Result := -1
else
try
#SM := GetProcAddress(MAPIModule, 'MAPISendMail');
if #SM <> nil then
begin
//Result := MapiSendMail(0, application.Handle, Msg, MAPI_DIALOG, 0);
Result := SM(0, 0, Msg, MAPI_DIALOG {or MAPI_LOGON_UI}, 0);
end
else
Result := 1;
finally
if Assigned(Att) and (Msg.nFileCount > 0) then
begin
for i := 0 to Msg.nFileCount - 1 do
begin
if Assigned(Att[i].lpszPathName) then
Att[i].lpszPathName := nil;
if Assigned(Att[i].lpszFileName) then
Att[i].lpszFileName := nil;
//FreeMem(Att[i].lpszPathName);
//Dispose(Att[i].lpszPathname);
//StrDispose(Att[i].lpszPathName);
//Dispose(Att[i].lpszFileName);
//StrDispose(Att[i].lpszFileName);
end;
Att := nil;
end;
if Assigned(Recips) and (Msg.nRecipCount > 0) then
begin
for i := 0 to Msg.nRecipCount - 1 do
begin
if Assigned(Recips[i].lpszName) then
Recips[i].lpszName := nil;
if Assigned(Recips[i].lpszAddress) then
Recips[i].lpszAddress := nil;
//if Assigned(Recips[i].lpszName) then
//Dispose(Recips[i].lpszName);
//if Assigned(Recips[i].lpszAddress) then
//Dispose(Recips[i].lpszAddress);
end;
Recips := nil;
end;
end;
Under Win32
Under Win32 it should not be a problem. Just first try calling MapiSendMail with very simple MapiMessage and if it will work, add complexity little by little. Your code is just too complex to debug it visually. Did you call MapiSendMail with very simple MapiMessage, just for testing? Please try the following code, it works for sure:
procedure TestSendExA(const APath1, ACaption1, APath2, ACaption2: AnsiString);
var
R: Integer;
MSG: TMapiMessage;
F: Array [0..1] of TMapiFileDesc;
Recipients: array[0..1] of TMapiRecipDesc;
Originator : array[0..0] of TMapiRecipDesc;
begin
if not FileExists(APath1) or not FileExists(APath2) then raise Exception.Create('File not found');
FillChar(Msg, SizeOf(Msg), 0);
Msg.lpszSubject := 'testo';
Msg.lpszNoteText := 'Hi there!';
Msg.lpszDateReceived := '2015/01/25 12:34';
Msg.lpszConversationId := '1234.test#ritlabs.com';
Msg.flFlags := MAPI_RECEIPT_REQUESTED;
FillChar(Recipients, SizeOf(Recipients), 0);
with Recipients[0] do
begin
ulRecipClass := MAPI_TO;
lpszName := 'Maxim Masiutin';
lpszAddress := 'maxim.test#ritlabs.com';
end;
with Recipients[1] do
begin
ulRecipClass := MAPI_CC;
lpszName := 'Vasilii Pupkin';
lpszAddress := 'pupkin.test#ritlabs.com';
end;
FillChar(Originator, SizeOf(Originator), 0);
with Originator[0] do
begin
ulRecipClass := MAPI_TO;
lpszName := 'Maxim Masiutin';
lpszAddress := 'max#ritlabs.com';
end;
Msg.lpOriginator := #Originator;
Msg.nRecipCount := 2;
Msg.lpRecips := #Recipients;
Msg.nFileCount := 2;
Msg.lpFiles := #F;
FillChar(F, SizeOf(F), 0);
F[0].lpszPathName := PAnsiChar(APath1);
F[0].lpszFileName := PAnsiChar(ACaption1);
F[1].lpszPathName := PAnsiChar(APath2);
F[1].lpszFileName := PAnsiChar(ACaption2);
R := MAPISendMail(MapiSession, 0, Msg, 0, 0);
end;
The MapiSession in the above example is a handle to the session returned by MapiLogon.
This sample code requires that you pass two valid file paths to valid files in APath1 and APath2.
Under Win64
It is the record alignment of MapiMessage and other records that it is important when you work with Simple MAPI from Delphi: (1) make sure the records don't have "packed" prefix; and (2) make sure you have {$A8} compiler directive is explicitly specified before first record definition. This will work fine under both Win32 and Win64.

Search for an array of bytes in another process

I wish to search for an array of bytes inside another process. I am using VirtualQueryEx and ReadProcessMemory but i am unsure of the correct what to do this.
Here is how my code looks so far:
procedure TForm1.Button2Click(Sender: TObject);
const
Target: array[0..7] of byte = ($A0, $19, $40, $2B, $F6, $7F, $00, $00);
var
Mbi: TMemoryBasicInformation;
Handle: THandle;
buff: array of byte;
hWin, ProcID, BuffSize: Cardinal;
Addr: DWORD_PTR;
BytesRead: NativeUInt;
i: integer;
begin
hWin := FindWindow(nil, 'Minesweeper');
if hWin > 0 then
GetWindowThreadProcessID(hWin, #ProcId);
if ProcId > 0 then
begin
Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, ProcId);
if Handle <> 0 then
begin
while (VirtualQueryEx(Handle, Ptr(Addr), Mbi, SizeOf(Mbi)) <> 0) do
begin
SetLength(buff, BuffSize);
if ReadProcessMemory(Handle, Mbi.BaseAddress, Buff, Mbi.RegionSize, BytesRead) then
begin
for i := 0 to Length(Buff) do
if CompareMem(#Buff[i], #Target[1], Length(Target)) then
begin
ShowMessage('Found');
end;
end;
if Addr + BuffSize < Addr then
break;
Addr := Addr + BuffSize;
end;
SetLength(buff, 0);
CloseHandle(Handle);
end;
end;
end;
Program freezes.
There are a number of issues with your code.
Rather than spoonfeed the solution I'm going to explain where to get the info.
Every local variable that you use, must be initialized beforehand.
Initialize local variables
The following vars are not initialized:
{mbi - Set to zero using} FillChar(mbi, SizeOf(Mbi), #0);
BuffSize:= 1024*4 + SizeOf(Target);
//Also add a
const
DefaultBufSize = 1024*4;
Do not start reading from 0
Instead initialize Addr to the starting address of the process using GetModuleInfo
Don't forget to initialize the mi: TModuleInfo structure using:
FillChar(mi, SizeOf(mi), #0);
Read a 4k+ buffer
Now keep loading buffers of BuffSize, but only increase Addr with DefaultBuffSize.
Check how many bytes are actually read
Make sure to check the BytesRead parameter and reduce the BuffSize if fewer bytes are read (or you'll get access violations).
Utilize a smart search algorithm
Use the following routine to find the string:
Boyer-Moore-Horspool string search algorithm - Wiki
(Thanks to: Dorin Duminica)
{$PointerMath on}
function FindMem(P1: pointer; Size1: Cardinal; P2: Pointer; Size2: Cardinal): Integer;
var
i,j,k: Integer;
LenPattern: Integer;
LenValue: Integer;
SkipTable: array[byte] of Integer;
Found: Boolean;
B: Byte;
function __SameByte: Boolean;
begin
Result := (PByte(P1)[i] = PByte(P2)[j])
end; // function __SameChar: Boolean;
begin
Found := False;
Result := -1;
LenPattern := size2;
if LenPattern = 0 then begin
Result := 0;
Found := True;
end; // if LenPattern = 0
for B:= low(byte) to high(byte) do SkipTable[B]:= LenPattern;
for k:= 1 to LenPattern - 1 do SkipTable[PByte(P2)[k]]:= LenPattern - k;
k:= LenPattern + 0;
LenValue := size1;
while (not Found) and (k <= LenValue) do begin
i := k;
j := LenPattern;
while (j >= 1) do begin
if __SameByte then begin
j := j -1;
i := i -1;
end else
j := -1;
if j = 0 then begin
Result := i;
Found := True;
end; // if j = 0
k := k + SkipTable[PByte(P1)[k]];
end; // while (j >= 1)
end; // while (not Found) and (k <= Size1)
end;
See here for info on GetModuleInfo
Good luck

how to get two different file with this procedure in deplhi

i want to get value from two file .txt, one file contain different dimension matrix with other
i have try this code:
procedure TfrmJST.ParseDelimited(const S1: TStrings; const Value: String; const Delimiter: String);
var
dx,cx: integer;
ns,ms: String;
txt: string;
delta,teta: integer;
procedure TfrmJST.ParseDelimited(const S1: TStrings; const Value: String; const Delimiter: String);
var
dx,cx: integer;
ns,ms: String;
txt: string;
delta,teta: integer;
begin
Col := 1;
Delta := Length(Delimiter);
Txt := Value+Delimiter;;
begin
while Length(Txt) > 1 do
begin
Dx := Pos(Delimiter, Txt);
Ns := Trim(Copy(Txt, 1, Dx-1));
// S1.Add('#'+Ns+'*'); //only needed for testing
if Ns <> '' then
begin
Matrix[Row,Col] := StrToFloat(Ns); //for first matrix
Inc(Col);
end;
Txt := Copy(Txt, Dx+Delta, MaxInt);
end;
end;
Col := 1;
teta := Length(delimiter);
txt := value+delimiter;
begin
while Length(txt) > 1 do
begin
cx := Pos(delimiter, txt);
ms := Copy(txt, 1, cx-1);
if ms <> '' then
begin
ref[Row,Col] := StrToFloat(ms); ///for 2nd matrix
Inc(Col);
end;
txt := Copy(txt, cx+teta, MaxInt);
end;
end;
end;
and this is initialize of matrix:
private
{ Private declarations }
Row, Col: integer;
Matrix: array[1..140,1..141] of double;
Ref: array[1..2,1..140] of double ;
this is the implementation:
begin
Temp := TStringList.Create;
MemoSL:= TStringList.Create ;
Temp.LoadFromFile('trainer.txt');
Row := 1;
for I := 0 to Temp.Count-1 do
begin
ParseDelimited(MemoSL, Trim(Temp.Strings[I]), ' ');
Inc(Row); //stackoverflow error in this line
end;
Temp.Free;
//parsing second matrix
TempList := TStringList.Create;
Templist.LoadFromFile('refbaru.txt');
row := 1;
for J := 0 to Templist.Count-1 do
begin
T := Templist[J];
ParseDelimited(Memo1.Lines, T, ' ');
Inc(row);
end;
Templist.Free;
i tried that code but give me error,
the error was stackoverflow error in line 'inc(row)' that process first matrix.
and while i gave comment out at the second function that process 2nd matrix, Temp[i] only returns 2 rows of matrix[140x141]. does it mean the code can't process two different file? and why it only return two rows of the matrix?
anyone can help me?
while Length(Txt) > 1 do
begin
Dx := Pos(Delimiter, Txt);
Ns := Trim(Copy(Txt, 1, Dx-1));
// S1.Add('#'+Ns+'*'); //only needed for testing
if Ns <> '' then
begin
Matrix[Row,Col] := StrToFloat(Ns); //for first matrix
Inc(Col);
end;
Txt := Copy(Txt, Dx+Delta, MaxInt);
end;
Looking at this piece of code I see the posibility of an endless loop: what happens if there is no Delimiter found? It will keep running and forever increase your 'col' value. Make sure to have a condition to stop your while loop if no delimeter is found.
It is pointless to look for a specific stack overflow error when many ordinary errors already exist.
If your code is clean programmed and it is still stack overflow, then of course, is time to look deeper into the code.
But first ! As long as you can see obvious errors, you should remove them.
1.) "Row" used in the same procedure on a 140 dimension array and on a only 2 dimension array.
How can that work ?
Matrix: array[1..140,1..141] of double;
Ref: array[1..2,1..140] of double ;
File 'trainer.txt' 140 Lines
File 'refbaru.txt' 2 Lines.
for I := 0 to Temp.Count-1 do // 140 lines
// ParseDelimited() will only run properly if Row < 3
// remember -> Ref: array[1..2,1..140])
// if Row > 2 , with Ref[Row,Col] := , 137 times data is overwritten.
procedure ParseDelimited(MemoSL, Trim(Temp.Strings[I]), ' ');
....
Matrix[Row,Col] := StrToFloat(Ns);
....
Ref[Row,Col] := StrToFloat(ms);
....
end;
Inc(Row);
end;
2.) If you run the second loop with refbaru.txt and the two arrays are present together in the procedure ParseDelimited(), then you overwrite 2 values of array Matrix
recommendation
make sure: Loop through trainer.txt, writes values only to the Matrix array.
make sure: Loop through refbaru.txt, writes values only to the Ref array.
Your code could look something like:
[...]
filetoload: String;
[...]
procedure TfrmJST.ParseDelimited(S1: TStrings; Value: String; const Delimiter: String);
var
f:double;
[...]
Col := 1;
txt := Value+Delimiter;
[...]
if filetoload='trainer.txt' then begin
Delta := Length(Delimiter);
while Length(txt) > 1 do
begin
Dx := Pos(Delimiter, txt);
Ns := Trim(Copy(txt, 1, Dx-1));
if Ns <> '' then
begin
if TryStrToFloat(Ns,f) then Matrix[Row,Col]:=f;
Inc(Col);
if Col > MatrixColMax then break;
txt := Copy(txt, Dx+Delta, MaxInt);
end else txt:='';
end;
end;
if filetoload='refbaru.txt' then begin
teta := Length(delimiter);
while Length(txt) > 1 do
begin
cx := Pos(delimiter, txt);
ms := Copy(txt, 1, cx-1);
if ms <> '' then
begin
if TryStrToFloat(ms,f) then Ref[Row,Col]:=f;
Inc(Col);
if Col > RefColMax then break;
txt := Copy(txt, cx+teta, MaxInt);
end else txt:='';
end;
end;
begin
[...]
filetoload:='trainer.txt';
Temp := TStringList.Create;
Temp.LoadFromFile(filetoload);
if Temp.Count > MatrixRowMax then LinesToLoad:=MatrixRowMax-1 else
LinesToLoad:=Temp.Count-1;
for I := 0 to LinesToLoad do
[...]
ParseDelimited(MemoSL, Trim(Temp.Strings[I]), ' ');
[...]
end;
filetoload:='refbaru.txt';
TempList := TStringList.Create;
TempList.LoadFromFile(filetoload);
if TempList.Count > RefRowMax then LinesToLoad:=RefRowMax-1 else
LinesToLoad:=TempList.Count-1;
for J := 0 to LinesToLoad do
[...]
ParseDelimited(Memo1.Lines, T, ' ');
[...]
end;
end;
You should also compare the linesize of the file with the size of the arrays
RefRowMax: integer;
RefColMax: integer;
MatrixRowMax: integer;
MatrixColMax: integer;
LinesToLoad: integer;
....
RefRowMax:=2;
RefColMax:=140;
MatrixRowMax:=140;
MatrixColMax:=141;
....
procedure ParseDelimited()
if filetoload='trainer.txt' then begin
[...]
Inc(Col)
if Col > MatrixColMax then break;
end;
if filetoload='refbaru.txt' then begin
[...]
Inc(Col)
if Col > RefColMax then break;
end;
You should also look for a valid value of Ns , StrToFloat(Ns) before you write to the arrays in ParseDelimited()
function TryStrToFloat(const S: string; out Value: Double): Boolean;
or
Val();
var
f:double;
....
begin
....
if TryStrToFloat(Ns,f) then Matrix[Row,Col]:=f;
....
The OP overwritting many of used data.
And when he has enough data overwritten, he gets a stack overflow error.

Convert hex string to ansistring in Delphi 2010

I used to use this function to convert hex string to string in Delphi 6 :
const
testSign = '207F8060287F585054505357FFD55861';
function Hex2Dec(const data: string): byte;
var
nH1, nH2: byte;
begin
if data[1] in ['0' .. '9'] then
nH1 := strtoint(data[1])
else
nH1 := 9 + ord(data[1]) - 64;
if data[2] in ['0' .. '9'] then
nH2 := strtoint(data[2])
else
nH2 := 9 + ord(data[2]) - 64;
Result := nH1 * 16 + nH2;
end;
function HexStrToStr(const HexStr: string): string;
var
BufStr: string;
LenHex: Integer;
x, y: Integer;
begin
LenHex := Length(HexStr) div 2;
x := 1;
y := 0;
while y <> LenHex do
begin
Inc(y);
BufStr := BufStr + Chr(Hex2Dec(HexStr[x] + HexStr[x + 1]));
Inc(x, 2);
end;
Result := BufStr;
end;
Now I want to use the function with Delphi 2010.
const
testSign: AnsiString = '207F8060287F585054505357FFD55861';
function Hex2Dec(const data: ansistring): byte;
var
nH1, nH2: byte;
begin
if data[1] in ['0' .. '9'] then
nH1 := strtoint(data[1])
else
nH1 := 9 + ord(data[1]) - 64;
if data[2] in ['0' .. '9'] then
nH2 := strtoint(data[2])
else
nH2 := 9 + ord(data[2]) - 64;
Result := nH1 * 16 + nH2;
end;
function HexStrToStr(const HexStr: ansistring): ansistring;
var
BufStr: ansistring;
LenHex: Integer;
x, y: Integer;
begin
LenHex := Length(HexStr) div 2;
x := 1;
y := 0;
while y <> LenHex do
begin
Inc(y);
BufStr := BufStr + Chr(Hex2Dec(HexStr[x] + HexStr[x + 1]));
Inc(x, 2);
end;
Result := BufStr;
end;
Output from first code in D6 :
' '#$7F'€`('#$7F'XPTPSWÿÕXa'
Output from second code in D2010 :
' '#$7F#$0080'`('#$7F'XPTPSWÿÕXa'
How do I fix the code in D2010 so it can produces same result like D6?
Besides the solutions others provided, you can also make use of the built-in function:
function HexStrToStr(const HexStr: string): string;
var
tmp: AnsiString;
begin
Assert(not Odd(Length(HexStr)), 'HexToStr input length must be an even number');
SetLength(tmp, Length(HexStr) div 2);
HexToBin(PWideChar(HexStr), #tmp[1], Length(tmp));
result := tmp;
end;
This implementation assumes that the hex-encoded string has been an Ansistring in the first place. For flexibility I suggest to use TBytes instead.

Resources