Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

Sujet : Question sur l'utilisation des TBitmap dans les fonctions... [ Mutimédia / Image & Vidéo ] (cerber943)

lundi 23 octobre 2006 à 13:08:44 | Question sur l'utilisation des TBitmap dans les fonctions...

cerber943

Bonjour,
J'ai créé quelques fonctions qui retournent des TBitmap. Je rencontre actuellement une augmentation de l'espace mémoire alloué à mon programme au fil de l'exécution de ces fonctions. Je suppose donc que je ne dois pas libérer les images correctement.


A chaque fin de procédure mes images intermédiaires sont libérées par
if Assigned(mon_img) then mon_img.Free;

Je me posais la questions si mes images étaient copiées ou transmises par références dans ce genre de situation :

function get_img() : TBitmap;
begin
result:=TBitmap.Create;
result.width:=10;
result.height:=10;
[...] bref on alloue cette image [...]
end;

procedure test_img (img : TBitmap) : Boolean;
begin
// fait quelque chose avec cette image
end;

Et dans ma fonction main :
if test_img(get_img) then ....

Je me demande si je peux écrire

if test_img(get_img) then ....
ou si je dois écrire :
tmp_img:=get_img;
if test_img(tmpImg) then ....
if Assigned(tmp_img) then tmp_img.Free;
De même (mais je pense avoir la réponse), j'ai un doute quand à l'utilisation de boucles pour parcourir les pixels des Canvas des Bitmap : doit-je itérer de 0 à Height-1 (ce que je pense) ou de 0 à Height ?
Je me pose la question car itérer de 0 à Height ne semble pas gérer de message d'erreur à l'exécution, mais un résultat incertain.

J'espère avoir été assez clair et je vous remercie par avance de votre aide



lundi 23 octobre 2006 à 23:54:39 | Re : Question sur l'utilisation des TBitmap dans les fonctions...

f0xi

Membre Club Administrateur CodeS-SourceS
Réponse acceptée !
ok je vais essayer de t'eclairer :

pour créer un bitmap par une methode mieux vaut prendre une procedure ou une fonction a retour booleen :

function CreateBitmap(BMP : TBitmap; const AWidth, AHeight : integer; const APixelFormat : TPixelFormat = pf32bit) : boolean;
begin
   result := false;
   if not Assigned(BMP) then begin
      BMP := TBitmap.Create;
      BMP.Width := AWidth;
      BMP.Height:= AHeight;
      BMP.PixelFormat := APixelFormat;
      result := true;
   end;
end;

>> CreateBitmap(MonBitmap1,10,10); // crée une image 32 bits par defaut
>> CreateBitmap(MonBitmap2,10,10,pf24bit); // force une image 24 bits

function FreeBitmap(BMP : TBitmap) : boolean;
begin
  result := false;
  if Assigned(BMP) then begin
     FreeAndNil(BMP);
     result := true;
  end;
end;

>> FreeBitmap(MonBitmap1); // libere et remet a nil la variable MonBitmap1
>> FreeBitmap(MonBitmap2);
// libere et remet a nil la variable MonBitmap1

ensuite pour acceder aux pixels d'un bitmap le mieux c'est ScanLine (canvas.pixel est trés long d'accés) :

const
  MAXWidth = 4096;

type
  TPixel24bit = record
    R,G,B : byte;
  end;

  TPixel32bit = record
    R,G,B,A : byte;
  end;
 
  pSLPixel24 = ^TSLPixel24;
  pSLPixel32 = ^TSLPixel32;
  TSLPixel24 = array[0..MAXWidth] of TPixel24bit;
  TSLPixel32 = array[0..MAXWidth] of TPixel32bit;

function GetPixelRGB24(BMP : TBitmap; const X,Y : integer; out Pixel : TPixel24bit) : boolean;
var pPL : pSLPixel24;
begin
  result := false;
  if ((X >= 0) and (X <= BMP.Width-1)) and ((Y >= 0) and (Y <= BMP.Height-1) then begin
     pPL    := BMP.ScanLine[y];
     Pixel  := pPL[X];
     result := true;
  end;
end;

function GetPixelRGB32(BMP : TBitmap; const X,Y : integer; out Pixel : TPixel32bit) : boolean;
var pPL : pSLPixel32;
begin
  result := false;
  if ((X >= 0) and (X <= BMP.Width-1)) and ((Y >= 0) and (Y <= BMP.Height-1) then begin
     pPL    := BMP.ScanLine[y];
     Pixel  := pPL[X];
     result := true;
  end;
end;
function SetPixelRGB24(BMP : TBitmap; const X,Y : integer; const Pixel : TPixel24bit) : boolean;
var pPL : pSLPixel24;
begin
  result := false;
  if ((X >= 0) and (X <= BMP.Width-1)) and ((Y >= 0) and (Y <= BMP.Height-1) then begin
     pPL    := BMP.ScanLine[y];
     pPL[X] := Pixel;
     result := true;
  end;
end;

function SetPixelRGB32(BMP : TBitmap; const X,Y : integer; const Pixel : TPixel32bit) : boolean;
var pPL : pSLPixel32;
begin
  result := false;
  if ((X >= 0) and (X <= BMP.Width-1)) and ((Y >= 0) and (Y <= BMP.Height-1) then begin
     pPL    := BMP.ScanLine[y];
     pPL[X] := Pixel;
     result := true;
  end;
end;

et un exemple de la boucle type pour utiliser ScanLine, pour les algorythmes d'images complexe ou non :

{ athlon 2700+ @ 2Ghz / bitmap 640x480 = 0..7ms }
procedure NegativizeScanline(BMP : TBitmap);
var pPL   : pSLPixel32;
    X,Y   : integer;
begin
  BMP.PixelFormat := pf32bit;
  for Y := 0 to BMP.Height-1 do begin
      pPL := BMP.ScanLine[y];
      for X := 0 to BMP.Width-1 do
          with pPL[X] do begin
            R := 255-R;
            G := 255-G;
            B := 255-B;
          end;
  end;
end;

alors que la methode Canvas.Pixel (meme optimisée) :

{ athlon 2700+ @ 2Ghz / bitmap 640x480 = 1670..1680ms }
procedure NegativizeCanvas(BMP : TBitmap);
var Color : integer;
    RGB   : array[0..2] of byte absolute color;
    N,X,Y : integer;
begin
  BMP.PixelFormat := pf32bit;
  for Y := 0 to BMP.Height-1 do begin
      for X := 0 to BMP.Width-1 do begin
          Color := BMP.Canvas.Pixels[X,Y];
          for N := 0 to 2 do
              RGB[N] := 255-RGB[N];
          BMP.Canvas.Pixels[X,Y] := Color;
      end;
  end;
end;


et ce n'est qu'un simple negatif, imagine sur une rehausse des couleurs, des contrastes ou autres modfication complexe....

ensuite il faut savoir qu'un Canvas n'a pas de réelle limite de coordonées ... on peut trés bien aller a X=10000,Y=-5000 sur un canvas qui ne fait que 320x200 pixel.
contrairement a ScanLine qui est reduit a l'interval 0..Width-1, 0..Height-1 et provoque une erreur si on sort de cette limite.



Croc (click me)

mardi 24 octobre 2006 à 08:48:50 | Re : Question sur l'utilisation des TBitmap dans les fonctions...

cerber943

Merci beaucoup du temps que tu as du passer pour me répondre, c'est très complet et très clair. Bravo !
Je n'ai plus qu'à remodifier mon code pour voir ce que cela m'a apporté et il est vrai que mon code était lent... je m'attend donc à avoir une agréable surprise lorsque j'aurais appliqué tes fonctions :)
Puis-je encore abuser de ton temps et demander pourquoi lorsque tu veux créer des pointeurs, tu les définies comme étant des pointeurs de tableau d'une taille max ?
Est-ce que la taille max a une importance ? Je pensais qu'un pointeur n'avait besoin que de savoir le type de donnée pointée, pas le nombre d'éléments de mémoire qui se trouve dans la zone pointée...
Je me doute qu'il faille faire comme tu l'as mis mais c'était pour mieux comprendre.

Quoi qu'il en soit si tu n'as pas le temps de répondre tu auras déja répondu à ma question donc encore merci pour ton dévouement et ton efficacité !

mardi 24 octobre 2006 à 09:55:07 | Re : Question sur l'utilisation des TBitmap dans les fonctions...

cerber943

Je précise que j'ai un problème lorsque j'utilise
function CreateBitmap(BMP : TBitmap; const AWidth, AHeight : integer; const APixelFormat : TPixelFormat = pf32bit) : boolean;
begin
   result := false;
   if not Assigned(BMP) then begin
      BMP := TBitmap.Create;
      BMP.Width := AWidth;
      BMP.Height:= AHeight;
      BMP.PixelFormat := APixelFormat;
      result := true;
   end;
end;

Il semble que je sois obligé de mettre ma variable à nil avant d'appeler CreateBitmap.
Lorsque je met :
result:=nil;
CreateBitmap(result,4,7);

result vaut toujours nil. Néanmoins si je rajoute var devant BMP dans la déclaration de CreateBitmap comme ceci :

function CreateBitmap(var BMP : TBitmap; const AWidth, AHeight : integer; const APixelFormat : TPixelFormat = pf32bit) : boolean;
le problème semble résolu.
En tout cas merci j'espère ne pas avoir fait d'erreur en mettant ce var devant BMP
A+

mardi 24 octobre 2006 à 13:30:46 | Re : Question sur l'utilisation des TBitmap dans les fonctions...

Guillemouze

c'est ce que j'allai dire, il manque un var devant le BMP de createBitmap et FreeBitmap aussi.

mardi 24 octobre 2006 à 22:30:45 | Re : Question sur l'utilisation des TBitmap dans les fonctions...

f0xi

Membre Club Administrateur CodeS-SourceS
oui il manque le var... mais uniquement pour Create et Free.
pour les autres on peu trés bien travailler sur le Bitmap d'un TImage donc pas de var.

sinon, pour les pointeurs c'est une question inerrante a scanline.
en effet les anciens bitmap etait limité a 2048 pixels de long.
soit :
array[0..2047] of ...

mais maintenant, le format ayant evolué, la taille n'est plus limitée et donc on peu definir une taille min/max a ce buffer.

quand on recupere pPL := BMP.ScanLine[Y], pPL contient tout les pixels de la ligne Y.
ensuite on appel pPL[X] pour travailler sur le pixel X de la ligne Y.

sincerement je crois avoir tenter une fois d'utiliser un tableau dynamique pour scanline, mais il me semble que ça ne fonctionne pas.

j'explique aussi pourquoi j'utilise des structure Record.
comme tu le sais un bitmap peut avoir un format de pixel different :
pf8bit (byte)
pf16bit (word)
pf24bit (...)
pf32bit (integer)

le probleme, c'est que par exemple il n'existe pas de type scalaire 24bit (3x1byte). et donc il nous faut une structure record ou un tableau de 3 bytes :

TPixel24 = record B,G,R : byte end;
TPixel24 = array[0..2] of byte;

pour le pf32bit, un structure record ou un integer est identique, sauf que la structure record offre quelques avantage, comme par exemple d'eviter de faire des SHL et SHR pour travailler sur lun des octet de couleur RGB.


Croc (click me)

vendredi 4 avril 2008 à 17:05:21 | Re : Question sur l'utilisation des TBitmap dans les fonctions...

kiwi200810



salut les gas!!!!!!!
quelle est l'avatage d'utiliser scanline par apport a getpixel
je voudrai savoir que fait le fonction assign

vendredi 4 avril 2008 à 17:25:13 | Re : Question sur l'utilisation des TBitmap dans les fonctions...


Cette discussion est classé dans : img, get, fonctions, height, tbitmap


Répondre à ce message

Sujets en rapport avec ce message

Impression d'un bitmap : Page Blanche [ par Francky23012301 ] Salut à tous,Je travaille actuellement avec le composant TGraphXY de Kénavo. J'ai besoin de pouvoir l'imprimer en noir et blanc, j'utilise donc ce cod Aide pour ce qui ressemble à un bug dans mon programme svp ... [ par cerber943 ] Bonjour,Voici mon problème je cherche à réaliser une fonction qui récupere une image TBitmap la découpe en 16 zones égales et retourne un tableau de 1 chargement DLL dynamique avec fonctions [ par christophedlr ] Bonsoir à tous,Dans mon logiciel, je prévois plusieurs langues possibles par fichiers DLL.J'ai trouvé sur delphipage, un moyen de charger dynamiquemen Connaitre toute les fonctions d'une DLL [ par askil2000 ] Bonjour,Certe, j'ai déja travaillé avec des DLL, mais je connaissais leurs fonctions et donc les appelais de manière dynamique.exemple :type  TMyDll = Création dynamique de TStringList et de TBitmap [ par sisi231 ] Bonjour,je souhaiterais pouvoir créer dynamiquement (i.e. pendant l'exécution de mon programme) des TBitmap et des TstringList autant que je veux.L'en Comment libérer un TBitmap résultant d'une fonction? [ par Caribensila ] Salut à tous, Une question existentielle me tourmente...Je vous donne un petit exemple, ce sera plus simple: <font face="Verd deux fonctions inconnues! [ par arfimounir ] Salut à tous.Je veux quelqu'un qui peut me dire: que veux dire ces deux fonctions en delphi   -   inc( )   -  trunc( )Et Merci. Sur les expressions Qreport [ par leader2000 ] Salut!S'il y a un doué (ou un habitué) dans l'utilisation du QuickReport pourrai-il me donner une liste  expliquée sur quelques fonctions utilisables Création dynamique [ par gabs77 ] bonjour,    je fais une création dynamique d'image comme un album en quelque sorte et, jusque là tout marche nickel, dont voici le script :var  Form1: Problème d'affichage d'une Image1.Canvas.Pen.Mode [ par cincap ] Bonsoir à toutes et à tous,Je dispose de deux fiche, sur la 1ère (formvisu) je charge une photo dans un Timage et j'ai un Tprintersetupdialog, sur la


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :

Comparez les prix Nouvelle version


LG KP501

Entre 9€ et 159€


Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,421 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.