Author Topic: Range error when adding images to TMultiImage  (Read 25 times)

Offline Patman

  • Imaging User
  • *
  • Posts: 2
    • View Profile
Range error when adding images to TMultiImage
« on: 3 July 2019, 15:03:13 »
Windows 7 x64
Delphi RAD Studio 10.2
Vampyre Imaging latest snapshot
-----

Error occurs when adding mipmaps to MultiImage before exporting to DDS. Like this:

Code: Pascal
  1. var
  2.   LImage: TMultiImage;
  3.   LImageCanvas: TImagingCanvas;
  4.   LImageMipMaps: TDynImageDataArray;
  5. begin
  6.           ...
  7.           LImage.Format := ifDXT5;
  8.           Imaging.GenerateMipMaps(LImage.ImageDataPointer^, 10, LImageMipMaps);
  9.           LImage.AddImages(LImageMipMaps);
  10.           FreeImagesInArray(LImageMipMaps);
  11.           LImage.SaveMultiToFile(ToDir + ToMaterial + '.dds');
  12.           ...
  13. end;

LImage has only 1 image when AddImages is called to add 10 mipmaps.
Getting range error from System.Move operation in ImagingClasses::PrepareInsert:

Code: Pascal
  1. function TMultiImage.PrepareInsert(Index, Count: Integer): Boolean;
  2. var
  3.   I: Integer;
  4. begin
  5.   // Inserting to empty image will add image at index 0
  6.   if GetImageCount = 0 then
  7.     Index := 0;
  8.  
  9.   if (Index >= 0) and (Index <= GetImageCount) and (Count > 0) then
  10.   begin
  11.     SetLength(FDataArray, GetImageCount + Count);
  12.     if Index < GetImageCount - 1 then
  13.     begin
  14.       // Move imges to new position
  15.       System.Move(FDataArray[Index], FDataArray[Index + Count],
  16.         (GetImageCount - Count - Index) * SizeOf(TImageData));
  17.       // Null old images, not free them!
  18.       for I := Index to Index + Count - 1 do
  19.         InitImage(FDataArray[I]);
  20.     end;
  21.     Result := True;
  22.   end
  23.   else
  24.     Result := False;
  25. end;

The System.Move and InitImage loop are for handling insertions via InsertImage(s) procedures, but it is also executed for all AddImage(s) procedures, which always add to the end of the array.
I changed it to the following (not tested for all InsertImage(s) and AddImage(s) operations):

Code: Pascal
  1. function TMultiImage.PrepareInsert(Index, Count: Integer): Boolean;
  2. var
  3.   I, LImageCount: Integer;
  4. begin
  5.   // Inserting to empty image will add image at index 0
  6.   LImageCount := GetImageCount;
  7.   if LImageCount = 0 then
  8.     Index := 0;
  9.  
  10.   if (Index >= 0) and (Index <= LImageCount) and (Count > 0) then
  11.   begin
  12.     SetLength(FDataArray, LImageCount + Count);
  13.     if Index <= LImageCount - 1 then
  14.     begin
  15.       // Move images to new position
  16.       System.Move(FDataArray[Index], FDataArray[Index + Count], (GetImageCount - Count - Index) * SizeOf(TImageData));
  17.       // Null old images; do not free them!
  18.       for I := Index to Index + Count - 1 do
  19.         InitImage(FDataArray[I]);
  20.     end;
  21.     Result := True;
  22.   end
  23.   else
  24.     Result := False;
  25. end;


Secondly, this appears to be a bug:

Code: Pascal
  1. procedure TMultiImage.InsertImages(Index: Integer;
  2.   const Images: TDynImageDataArray);
  3. begin
  4.   DoInsertImages(Index, FDataArray);
  5. end;

Which should be:

Code: Pascal
  1. procedure TMultiImage.InsertImages(Index: Integer;
  2.   const Images: TDynImageDataArray);
  3. begin
  4.   DoInsertImages(Index, Images);
  5. end;

Offline Galfar

  • Administrator
  • Imaging User
  • *****
  • Posts: 372
    • View Profile
    • Galfar's Homepage
Re: Range error when adding images to TMultiImage
« Reply #1 on: 3 July 2019, 16:31:30 »
Thanks for the fixes, I'll add them to the repository.
TSingleImage and especially TMultiImage are not used and tested that much unfortunately.