Solved

Strange EAccessViolation when loading a Bitmap

Posted on 2001-08-21
6
415 Views
Last Modified: 2013-12-03
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(LoadSignDlg.Filename);
  SignName.text:=Sign.Filename;
  Sign.VisModel^.Bright:=StrToInt(Brightness.Text);
  SignBrightName:='.\images\'+Copy(Sign.Filename,1,Length(Sign.Filename)-4)+'_'+IntToStr(Sign.VisModel^.Bright)+'.BMP';
  if FileExists(SignBrightName) then
    Sign.VisModel^.Pixmap.LoadFromFile(SignBrightName)  //<--------crash with EAccessViolation
  else
  begin
    ShownImage.Bildfeld.Picture.Bitmap.LoadFromFile(Sign.Filename);
    ShownImage.AdjustBright(255,Sign.VisModel^.Bright);
    ShownImage.Bildfeld.Picture.Bitmap.SaveToFile(SignBrightName);
    Sign.VisModel^.Pixmap.LoadFromFile(SignBrightName);
  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;
0
Comment
Question by:mdietz
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
6 Comments
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6409243
and where is your
  PixMap:TBitmap;
created?
 
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6409249
change this part

if FileExists(SignBrightName) then
   Sign.VisModel^.Pixmap.LoadFromFile(SignBrightName)  //<--------crash with EAccessViolation
 
into

if FileExists(SignBrightName) then
begin
  if not(assigned(Sign.VisModel^.Pixmap)) then
    Sign.VisModel^.Pixmap := TBitmap.Create;
  Sign.VisModel^.Pixmap.LoadFromFile(SignBrightName);
end;
 
don't forget to free the bitmap, before you dispose the vismodel

meikl ;-)
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6412305
hello?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 2

Author Comment

by:mdietz
ID: 6412539
Creating an empty Bitmap before assigning or loading doesn't help. Neither by Sign.VisModel^.Pixmap.Create nor by Sign.VisModel^.Pixmap:=TBitmap.Create (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.
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 100 total points
ID: 6412899
nono,

i guess anyway the problem is exact there,
that there is no properly created tbitmap

LoadFromFile is a streaming-method
it does nothing else as stream the data to the buffer of the properly created component(TBitMap in this case)

nothing else is done, no temporary creating and sizing

i guess more, that your records and subrecords are not initialized properly during its allocations, which may cause garbage in the record fields, even the assigned function may not detect this, because it checks only for nil.

one tip:

be sure that TSignDef.VisModel-Pointer-Record
is properly allacoted and initialized with defualt-values
(NIL for your PixMap-Entry)

after this checks/changes my comment above should work

just to say that a procedure like

var
  B : TBitmap;
  I : Integer;
begin
  B := TBitMap.Create;
  try
    For I := 1 to 10 do
      B.LoadFromFile('Test'+intToStr(I)+'.bmp';
  finally
    B.Free;
  end;
end;

does not cause any exception
(except the files are not available)
nor a memory leak

meikl ;-)
0
 
LVL 2

Author Comment

by:mdietz
ID: 6413009
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
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
error 1.1 400 Bad request idhttp delphi 18 208
Drag & Drop... Data from one grid to another 2 47
Get weeknumber and year from date 4 31
Broadcast a message using ICS 2 28
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question