• Welcome to Vampyre Imaging Library Forum. Please login or sign up.
 

Range error when adding images to TMultiImage

Started by Patman, 3 July 2019, 15:03:13

Previous topic - Next topic

Patman

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) Select
var
  LImage: TMultiImage;
  LImageCanvas: TImagingCanvas;
  LImageMipMaps: TDynImageDataArray;
begin
          ...
          LImage.Format := ifDXT5;
          Imaging.GenerateMipMaps(LImage.ImageDataPointer^, 10, LImageMipMaps);
          LImage.AddImages(LImageMipMaps);
          FreeImagesInArray(LImageMipMaps);
          LImage.SaveMultiToFile(ToDir + ToMaterial + '.dds');
          ...
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) Select
function TMultiImage.PrepareInsert(Index, Count: Integer): Boolean;
var
  I: Integer;
begin
  // Inserting to empty image will add image at index 0
  if GetImageCount = 0 then
    Index := 0;

  if (Index >= 0) and (Index <= GetImageCount) and (Count > 0) then
  begin
    SetLength(FDataArray, GetImageCount + Count);
    if Index < GetImageCount - 1 then
    begin
      // Move imges to new position
      System.Move(FDataArray[Index], FDataArray[Index + Count],
        (GetImageCount - Count - Index) * SizeOf(TImageData));
      // Null old images, not free them!
      for I := Index to Index + Count - 1 do
        InitImage(FDataArray[I]);
    end;
    Result := True;
  end
  else
    Result := False;
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) Select
function TMultiImage.PrepareInsert(Index, Count: Integer): Boolean;
var
  I, LImageCount: Integer;
begin
  // Inserting to empty image will add image at index 0
  LImageCount := GetImageCount;
  if LImageCount = 0 then
    Index := 0;

  if (Index >= 0) and (Index <= LImageCount) and (Count > 0) then
  begin
    SetLength(FDataArray, LImageCount + Count);
    if Index <= LImageCount - 1 then
    begin
      // Move images to new position
      System.Move(FDataArray[Index], FDataArray[Index + Count], (GetImageCount - Count - Index) * SizeOf(TImageData));
      // Null old images; do not free them!
      for I := Index to Index + Count - 1 do
        InitImage(FDataArray[I]);
    end;
    Result := True;
  end
  else
    Result := False;
end;



Secondly, this appears to be a bug:

Code (pascal) Select
procedure TMultiImage.InsertImages(Index: Integer;
  const Images: TDynImageDataArray);
begin
  DoInsertImages(Index, FDataArray);
end;


Which should be:

Code (pascal) Select
procedure TMultiImage.InsertImages(Index: Integer;
  const Images: TDynImageDataArray);
begin
  DoInsertImages(Index, Images);
end;


Galfar

Thanks for the fixes, I'll add them to the repository.
TSingleImage and especially TMultiImage are not used and tested that much unfortunately.

Quick Reply

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Name:
Email:

Shortcuts: ALT+S save/post or ALT+P preview

SMF spam blocked by CleanTalk