I load some images into an object list , and then try to recall them. But its not showing the image?
procedure TForm1.LoadImages(const Dir: string);
var
i: Integer;
CurFileName: string;
JpgIn: TJPEGImage;
BmpOut: TBitmap;
begin
//sets index for object list
CurIdx := -1;
i := 0;
while True do
begin
//gets current folder
CurFileName := Format('%s%d.jpg',
[IncludeTrailingPathDelimiter(Dir), i]);
if not FileExists(CurFileName) then
Break;
//creates jpgin
JpgIn := TJPEGImage.Create;
try
//loads jpgin
JpgIn.LoadFromFile(CurFileName);
//creates TBitmap and sets width to same as jpgs
BmpOut := TBitmap.Create;
bmpout.Width := jpgin.Width;
bmpout.Height := jpgin.Height;
try
BmpOut.Assign(JpgIn);
//if i assign it here it works, showing last image of course
//zimage1.Bitmap.Width := bmpout.Width;
//zimage1.Bitmap.Height := bmpout.Height;
//ZImage1.Bitmap.Assign(bmpout);
//adds 1 to index for object list. thus starting at 0
curIdx := curIdx+1;
//add bitmap to objectlist
CurIdx:= mylist.Add(TBitmap(bmpout));
finally
//free bitmap and jpg
BmpOut.Free;
end;
finally
JpgIn.Free;
end;
Inc(i);
end;
//makes sure cout is above 0
if mylist.Count > 0 then
begin
//create bitmap
BmpOut := TBitmap.Create;
try
//sets width and heigh of bitmap before getting image
bmpout.Height := TBitmap(mylist[curidx]).Height;
bmpout.Width := TBitmap(mylist[curidx]).Width;
bmpout.Assign(TBitmap(mylist[CurIdx]));
//sets zimage width height before getting image.
zimage1.Bitmap.Width := bmpout.Width;
zimage1.Bitmap.Height := bmpout.Height;
ZImage1.Bitmap.Assign(bmpout);
finally
BmpOut.Free;
end;
end;
page:= '0';
end;
if you notice i had this part in there to see if loading the iamge into the zimage1 was an issue.
//zimage1.Bitmap.Width := bmpout.Width;
//zimage1.Bitmap.Height := bmpout.Height;
//ZImage1.Bitmap.Assign(bmpout);
when i did that, it loaded bmpout into the zimage1 which leads me to think its something with the object list that iam doing wrong?
You have this code:
CurIdx:= mylist.Add(TBitmap(bmpout));
finally
//free bitmap and jpg
BmpOut.Free;
end;
You add an item to the list, and then you immediately free that very same item. TList
and its descendants like TObjectList
do not make a "deep copy" of the objects they hold.
When you later read the contents of the list, what you're getting are stale references. They no longer refer to the objects they originally referred to, and they probably don't refer to any object at all. The memory at those locations might still contain data structured to look like those former objects, but there's no guarantee of that. There's no guarantee your program won't crash, either. A crash is typical, but the next most common behavior is for your program to exhibit subtle errors, such as continuing to run but not displaying the expected data.
If you want a list of objects, then don't free them; get rid of the finally
block I quoted above. To be exception-safe, you'll want to carefully transfer ownership from the current code block to the list, like this:
BmpOut := TBitmap.Create;
try
BmpOut.Assign(JpgIn);
CurIdx := mylist.Add(bmpout);
except
BmpOut.Free;
raise;
end;
If an exception occurs during the Assign
or Add
calls, then the local procedure should free the bitmap. Otherwise, the list acquires ownership of the object, and freeing the list will implicitly free all its objects (assuming the list's OwnsObjects
property is True
).
Once you've loaded all the bitmaps and stored them in the list, there's no real need to create another bitmap just to have something to assign to your image control. You can just use the one you've stored in the list:
if mylist.Count > 0 then
begin
ZImage1.Bitmap.Assign(mylist[mylist.Count - 1]);
end;
From that code, you can see that you don't even need to keep track of CurIdx
. Its value will always be the index of the last added object, and that index will always be one less than the total number of objects in the list.
You also don't have to set a bitmap's height and width prior to assigning it a value from another graphic object. It will automatically acquire the dimensions of the source object.