cs_TouTSpeed
Messages postés72Date d'inscriptionjeudi 5 janvier 2006StatutMembreDernière intervention30 août 2007
-
3 nov. 2006 à 22:20
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 2022
-
7 nov. 2006 à 04:00
bonsoir à tous.
Je suis en train de retranscrire un programme écrit en language c et en delphi !! ( en fait je lance un programme que j'ai écrit en C afin de traiter une opération que je ne savais faire en delphi à l'époque ! )
le programme en question capture une image toutes les x secondes , l'enregistre au format jpg puis la lit, et en fonction des infos recueillit je détermine la position d'un objet d'une couleur définit auparavant !
le programme fonctionnait parfaitement avec le petit prog en C ! avec capture toutes les demi seconde ce qui me convenait or en delphi je ne peux descendre en dessous de 1 seconde car l'affichage sacade et ensuite il y a probleme de temps de lecture/écriture !
y a t il un moyen d'enregistrer l'image dan sla ram a un eadresse précise et de lire cette image a la meme adresse évidemment !!
en espérant avoir été assez clair
je vous en remercie d'avance !
( le programme d edépart permmettait a une webcam de suivre l'objet en question !
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 5 nov. 2006 à 18:21
Cirec qui utiliser Canvas.Pixel .... #sig# ... tu me decois la, nostalgie de debutant ou ?
voila un exemple concret :
sur la fiche :
une TListbox,
un boutton,
un opendialog.
Type
// pixel
TPixel24bit = array[0..2] of byte;
// ligne de l'image (pixel*width)
pScanLine = ^TScanLine;
// width max de l'image 16384 pixels
TScanLine = array[0..16383] of TPixel24Bit;
// convertion TPixel24bit vers integer ([RR][GG][BB] > 00BBGGRR)
function Pixel24ToInt(const P24 : TPixel24bit): Integer;
asm
mov eax, dword ptr [ebp+$08];
rol eax, $08;
xor al, al;
ror eax, $08;
end;
// Analyse de l'image et affichage des infos dans un TStrings
procedure GetBitmapInfo(const BMPFileName : string; Strings : TStrings);
var X,Y : Integer;
BMP : TBitmap;
pData : pScanline;
TFS : TFileStream;
BMPHeader : TBITMAPFILEHEADER;
BMPInfo : TBITMAPINFO;
begin
// si le fichier n'existe pas
if not FileExists(BMPFileName) then
// on sort
exit;
// on efface la liste
Strings.Clear;
// et on la prepare pour des modifications
Strings.BeginUpdate;
// on crée un stream fichier, pour economiser la memoire
TFS := TFileStream.Create(BMPFileName, fmOpenRead);
try
// on lit les infos
TFS.ReadBuffer(BMPHeader,SizeOf(TBITMAPFILEHEADER));
TFS.ReadBuffer(BMPInfo,SizeOf(TBITMAPINFO));
// on recupere le nom de l'image
Strings.Add(ExtractFileName(BMPFileName));
// on recupere d'autres infos
with BMPInfo.bmiHeader do begin
Strings.Add(format('Width x Height : %dx%d',[biWidth, biHeight]));
Strings.Add( 'Pixel format : '+IntToStr(biBitCount)+' bits');
Strings.Add( 'Image Size : '+IntToStr((biWidth*biHeight*biBitCount) div 8));
Strings.Add('');
end;
finally
// on libere le stream
TFS.Free;
// on mets a jours l'affichage de la liste
Strings.EndUpdate;
end;
// on reprepare la liste pour les modif
Strings.BeginUpdate;
// on crée un objet bitmap
BMP := TBitmap.Create;
try
// on charge l'image
BMP.LoadFromFile(BMPFileName);
// on regle son format a 24bits
BMP.PixelFormat := pf24bit;
// on prepare une entete de tableau (utiliser la police "Courier New")
Strings.Add('R | G | B | Color | X | Y');
Strings.Add('----+-----+-----+-----------+------+------');
// enfin on scan l'image
for y := 0 to BMP.height-1 do begin
// on recupere tout les pixels de la ligne Y
pData := BMP.ScanLine[y];
// on scan la ligne
for x := 0 to BMP.Width-1 do
// on affiche les données du pixel
// a chaque fin de boucle on rafraichis la liste
Strings.EndUpdate;
Strings.BeginUpdate;
end;
finally
// enfin on libere le bitmap
BMP.Free;
// puis on mets fin aux modifications de la liste
Strings.EndUpdate;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// si on ouvre une image
if OpenDialog1.Execute then
// on recuper analyse l'image et on affiche les données dans listbox1
GetBitmapInfo(OpenDialog1.FileName, ListBox1.Items);
end;
cs_TouTSpeed
Messages postés72Date d'inscriptionjeudi 5 janvier 2006StatutMembreDernière intervention30 août 2007 6 nov. 2006 à 01:47
Encore merci à tous ça marche du tonnerre je posterai ma source d'ici quelque temps quand elle sera épurée , puis commenter , ( source de base ) et bien sur avec les fonctions de reconnaissance ( plus tard en mise à jour ) !
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 6 nov. 2006 à 14:14
Voilà ...
Pour faire plaisir à F0xi
voici une autre méthode avec pseudo ScanLine qui, je le rappel, contrairement a celle de F0xi ne charge qu'une seul fois le fichier.
En effet, je charge le fichier dans un TMemoryStream, je lis le Header et les Infos et du même fichier j'extrais
les données de l'image que je reconstitue directement dans un TBitmap et pour finir j'affiche le résultat et quelques données
Le code peut encore être optimisé mais je préfère le laisser tel quel dans un souci de compréhension.
Je ne commente que ce qui a changé ...
Type TRGBRec = record
R,G,B : Byte;
end;
procedure TForm1.Button2Click(Sender: TObject);
Var MS : TMemoryStream;
FileHeader : TBITMAPFILEHEADER;
Info : TBITMAPINFO;
NB : Byte;
DataSize : Cardinal;
aData : Array Of TRGBRec;
X,Y : Integer;
BMP : TBitmap;
begin NB : = 3;
MS := TMemoryStream.Create;
With MS do Try LoadFromFile('fcsambug.BMP');
ReadBuffer(FileHeader, SizeOf(TBITMAPFILEHEADER));
ReadBuffer(Info, SizeOf(TBITMAPINFO));
If Info.bmiHeader.biBitCount = 32 Then NB := 4;
DataSize := (Info.bmiHeader.biWidth * Info.bmiHeader.biHeight) * NB;
MS.Position := FileHeader.bfOffBits;
If Info.bmiHeader.biBitCount = 24 Then
Begin
BMP : = TBitmap.Create;
Try BMP.PixelFormat := pf24Bit;
BMP.Width := Info.bmiHeader.biWidth;
BMP.Height := Info.bmiHeader.biHeight;
// on fixe la taille de notre pseudo ScanLine
SetLength(aData, BMP.Width);
// Verticalement les données sont inversées
// elles commencent par le bas de l'image
For Y : = BMP.Height - 1 DownTo 0 Do Begin // Lecture par Bloc comme avec ScanLine MS.readBuffer(Pointer(aData)^, BMP.Width * 3);
For X := 0 to BMP.Width - 1 Do // Replace les données dans le bon ordre (BGR au lieu de RGB)
BMP.Canvas.Pixels[X, Y] : = RGB(aData[X].B,
aData[X].G, aData[X].R);
End;
Finally Self.Canvas.Draw(0,0,BMP);
BMP.Free;
End;
End; Finally Free;
End;
With Info.bmiHeader, Memo1.Lines do Begin Clear;
Add(Format('HeaderImageSize : %d', [FileHeader.bfSize]));
Add(Format('Width : %d, Height : %d', [biWidth, biHeight]));
Add(Format('BitCount : %d', [biBitCount]));
Add(Format('ImageSize : %d', [biSizeImage]));
Add(Format('DataSize : %d', [DataSize]));
End;
End;
@F0xi : Si tu arrives à "réinjecter" les données avec
Bitmap.ScanLine je serais vivement intéressé ...
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 6 nov. 2006 à 15:21
Petite modification pour plus de rapidité ( ça va faire plaisir à F0xi)
On ajoute ceci :
// Sur le principe de la solution 3 [78..94ms 8MPixels] de F0xi:
// la plus rapide des modifiables (pour moi) ... la version 4 est certe plus rapide
// mais je ne sais pas comment inverser les Bytes R et B
function PixelRGBToInt(const PRGB : TRGBRec) : integer;
begin result := (PRGB.R shl 16) + (PRGB.G shl 8) + PRGB.B;
end;
et à la place de : BMP.Canvas.Pixels[X, Y] : = RGB(aData[X].B, aData[X].G, aData[X].R);
f0xi
Messages postés4205Date d'inscriptionsamedi 16 octobre 2004StatutModérateurDernière intervention12 mars 202235 6 nov. 2006 à 22:02
aller pouf, j'adore les defis !
Type
// pixel 24 bits
TPixel24 = record
R,G,B : byte;
end;
// pour ScanLine en pixelformat pf24bit
pPixelLine = ^TPixelLine;
TPixelLine = array[0..16383] of TPixel24;
// pour copier du stream vers TBitmap
pBytes = ^TBytes;
TBytes = array of byte;
// procedure qui permet d'analyser l'image
procedure AnalyseBitmap(const FileName : string; Strings : TStrings);
Var
MS : TMemoryStream;
BMP : TBitmap;
FileHeader : TBITMAPFILEHEADER;
Info : TBITMAPINFO;
pB : pBytes;
pPL : pPixelLine;
Pixel : TPixel24;
X,Y,
LineLen,
BytesCount : integer;
begin
MS := TMemoryStream.Create;
try
// on charge le stream
MS.LoadFromFile(FileName);
// on recupere les infos
MS.ReadBuffer(FileHeader, SizeOf(TBITMAPFILEHEADER));
MS.ReadBuffer(Info, SizeOf(TBITMAPINFO));
// on vas a l'offset des données
MS.Position := FileHeader.bfOffBits;
BMP := TBitmap.Create;
try
// on selectionne le format des pixels
// tout les formats bmp sont supportés
with Info.bmiHeader do begin
case biBitCount of
1 : BMP.PixelFormat := pf1Bit;
4 : BMP.PixelFormat := pf4Bit;
8 : BMP.PixelFormat := pf8Bit;
15 : BMP.PixelFormat := pf15Bit;
16 : BMP.PixelFormat := pf16Bit;
24 : BMP.PixelFormat := pf24Bit;
32 : BMP.PixelFormat := pf32Bit;
end;
BMP.Width := biWidth;
BMP.Height := biHeight;
// on calcul la longeur d'une ligne (shr 3 = div 8)
LineLen := (BMP.Width * biBitCount) shr 3;
end;
// on injecte rapidement les données dans le bitmap
// il faut lire a l'envers car les données sont stockées
// de bas en haut dans le fichier bitmap
for Y := BMP.Height-1 downto 0 do begin
// on recupere la ligne Y dans un pBytes
pB := BMP.ScanLine[y];
// on lit la ligne en une seule fois
MS.readBuffer(pB^, LineLen);
end;
// on prepare la liste
Strings.Clear;
Strings.BeginUpdate;
// on mets par defaut en 24bits pour faciliter la lecture
BMP.PixelFormat := pf24bit;
for Y := 0 to BMP.Height-1 do begin
// on recupere cette fois la ligne dans un pPixelLine
pPL := BMP.ScanLine[Y];
for X := 0 to BMP.Width-1 do begin
// on ajoute la ligne dans la liste
Strings.Add(format( 'R=%3.d G=%3.d B=%3.d',
[ pPL[x].R, pPL[x].G, pPL[x].B ]));
end;
end;
// on affiche d'autres infos
With Info.bmiHeader do Begin
// Taille du fichier, de l'entête et de données
Strings.Add(Format( 'File size : %d bytes (Head=%d bytes, Data=%d bytes)',[FileHeader.bfSize, FileHeader.bfSize-(LineLen * biHeight), LineLen * biHeight]));
// Resolutions complete Width x Height x Bits
Strings.Add(Format( 'Resolution : %d x %d x %d', [biWidth, biHeight, biBitCount]));
End;
// on notifie la liste que les modifications sont finies
Strings.EndUpdate;
// ici c'est juste pour verifier que le BMP a été lus correctement
// form1.PaintBox1.Canvas.Draw(0,0,BMP);
// on libere tout
finally
BMP.Free;
end;
finally
MS.Free;
end;
End;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Trés simplement
AnalyseBitmap('E:\TropPleinDeTrucsEnBordel\ProgDelphi\test16bits.bmp', ListBox1.Items);
end;