mdietz
asked on
Strange EAccessViolation when loading a Bitmap
I have to handle two bitmaps, one in a visual component and another, smaller one, in memory to be drawn into the first to specific positions. Every time I try to assign a bitmap to the memory-held BitMap the program gets an EAccessViolation. I tried to save and load the data, but here again the EAccessViolation when loading it to the variable.
Is there something I have to do with the Pixmap before loading an image to it? If I understood the help tables correctly, LoadFromFile should do the whole bunch of creating, defining the size, allocating memory and so on.
procedure TAnimation.LoadSign(Sender : TObject);
var SignBrightName:string;
begin
LoadSignDlg.Execute;
Sign.Filename:=extractFile (LoadSignD lg.Filenam e);
SignName.text:=Sign.Filena me;
Sign.VisModel^.Bright:=Str ToInt(Brig htness.Tex t);
SignBrightName:='.\images\ '+Copy(Sig n.Filename ,1,Length( Sign.Filen ame)-4)+'_ '+IntToStr (Sign.VisM odel^.Brig ht)+'.BMP' ;
if FileExists(SignBrightName) then
Sign.VisModel^.Pixmap.Load FromFile(S ignBrightN ame) //<--------crash with EAccessViolation
else
begin
ShownImage.Bildfeld.Pictur e.Bitmap.L oadFromFil e(Sign.Fil ename);
ShownImage.AdjustBright(25 5,Sign.Vis Model^.Bri ght);
ShownImage.Bildfeld.Pictur e.Bitmap.S aveToFile( SignBright Name);
Sign.VisModel^.Pixmap.Load FromFile(S ignBrightN ame);
end;
end;
Sign is of type TSignDef which holds the data for defining the sign in the scene, Sign.VisModel is a pointer to type TSignModel, which holds the data needed to display the sign on the screen. Sign.VisModel is created when showing the form to enter the data, if it's not already existing.
type
TSignModel=record
ScreenPosx:integer;
Screenposy:integer;
ScreenSize:record
width:integer;
height:integer;
end;
Bright:integer;
PixMap:TBitmap;
end;
TSignDef=record
Filename:String;
Position:record
x:real;
y:real;
z1:real;
z2:real;
end;
speed:real;
realheight :real;
VisModel:^TSignModel;
end;
Is there something I have to do with the Pixmap before loading an image to it? If I understood the help tables correctly, LoadFromFile should do the whole bunch of creating, defining the size, allocating memory and so on.
procedure TAnimation.LoadSign(Sender
var SignBrightName:string;
begin
LoadSignDlg.Execute;
Sign.Filename:=extractFile
SignName.text:=Sign.Filena
Sign.VisModel^.Bright:=Str
SignBrightName:='.\images\
if FileExists(SignBrightName)
Sign.VisModel^.Pixmap.Load
else
begin
ShownImage.Bildfeld.Pictur
ShownImage.AdjustBright(25
ShownImage.Bildfeld.Pictur
Sign.VisModel^.Pixmap.Load
end;
end;
Sign is of type TSignDef which holds the data for defining the sign in the scene, Sign.VisModel is a pointer to type TSignModel, which holds the data needed to display the sign on the screen. Sign.VisModel is created when showing the form to enter the data, if it's not already existing.
type
TSignModel=record
ScreenPosx:integer;
Screenposy:integer;
ScreenSize:record
width:integer;
height:integer;
end;
Bright:integer;
PixMap:TBitmap;
end;
TSignDef=record
Filename:String;
Position:record
x:real;
y:real;
z1:real;
z2:real;
end;
speed:real;
realheight :real;
VisModel:^TSignModel;
end;
change this part
if FileExists(SignBrightName) then
Sign.VisModel^.Pixmap.Load FromFile(S ignBrightN ame) //<--------crash with EAccessViolation
into
if FileExists(SignBrightName) then
begin
if not(assigned(Sign.VisModel ^.Pixmap)) then
Sign.VisModel^.Pixmap := TBitmap.Create;
Sign.VisModel^.Pixmap.Load FromFile(S ignBrightN ame);
end;
don't forget to free the bitmap, before you dispose the vismodel
meikl ;-)
if FileExists(SignBrightName)
Sign.VisModel^.Pixmap.Load
into
if FileExists(SignBrightName)
begin
if not(assigned(Sign.VisModel
Sign.VisModel^.Pixmap := TBitmap.Create;
Sign.VisModel^.Pixmap.Load
end;
don't forget to free the bitmap, before you dispose the vismodel
meikl ;-)
hello?
ASKER
Creating an empty Bitmap before assigning or loading doesn't help. Neither by Sign.VisModel^.Pixmap.Crea te nor by Sign.VisModel^.Pixmap:=TBi tmap.Creat e (This was also my first thought, and the first thing I tested). The only difference is that the Violation then gives a different memory address, where the fault occured (simply because the code that should load the image is a few lines later than it was before).
I don't think the problem is a problem of creating the destination Bitmap. I guess that LoadFromFile reads the file, creates a bitmap of correct size, enters the graphical data into that structure and then assigns the new created bitmap to the component that called LoadFromFile, so creating before loading could be fatal if LoadFromFile doesn't free the memory of the 'old' bitmap.
The source of the problem and the way to the solution seems to be in the way how Delphi handles the Bitmaps of visual components. Here I can LoadFromFile as often as the user wants (and in the slide show I load a new image over the old every time the user hits a key) without any Access Violations, but except the embedding into a TImage and the cast-through create when the Form is created I see no differences.
I don't think the problem is a problem of creating the destination Bitmap. I guess that LoadFromFile reads the file, creates a bitmap of correct size, enters the graphical data into that structure and then assigns the new created bitmap to the component that called LoadFromFile, so creating before loading could be fatal if LoadFromFile doesn't free the memory of the 'old' bitmap.
The source of the problem and the way to the solution seems to be in the way how Delphi handles the Bitmaps of visual components. Here I can LoadFromFile as often as the user wants (and in the slide show I load a new image over the old every time the user hits a key) without any Access Violations, but except the embedding into a TImage and the cast-through create when the Form is created I see no differences.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Yes, you're right. I entered the line VisModel^.Pixmap:=TBitmap. Create; directly after the new(VisModel); and now it works.
It's strange that it didn't work when I created it without the assigned(...) check.
Thanks for all
Martin
It's strange that it didn't work when I created it without the assigned(...) check.
Thanks for all
Martin
PixMap:TBitmap;
created?