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

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Patman

1
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;

2
ImagingCanvases.pas:

function TransformPremultiplyAlpha(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec;
begin
  Result.A := Pixel.A;
  Result.R := Result.R * Pixel.A;
  Result.G := Result.G * Pixel.A;
  Result.B := Result.B * Pixel.A;
end;

function TransformUnPremultiplyAlpha(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec;
begin
  Result.A := Pixel.A;
  if Pixel.A <> 0.0 then
  begin
    Result.R := Result.R / Pixel.A;
    Result.G := Result.G / Pixel.A;
    Result.B := Result.B / Pixel.A;
  end
  else
  begin
    Result.R := 0;
    Result.G := 0;
    Result.B := 0;
  end;
end;


IMHO the alpha operations on Result.R, Result.G and Result.B should be on Pixel.R, Pixel.G and Pixel.B:

function TransformPremultiplyAlpha(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec;
begin
  Result.A := Pixel.A;
  Result.R := Pixel.R * Pixel.A;
  Result.G := Pixel.G * Pixel.A;
  Result.B := Pixel.B * Pixel.A;
end;

function TransformUnPremultiplyAlpha(const Pixel: TColorFPRec; P1, P2, P3: Single): TColorFPRec;
begin
  Result.A := Pixel.A;
  if Pixel.A <> 0.0 then
  begin
    Result.R := Pixel.R / Pixel.A;
    Result.G := Pixel.G / Pixel.A;
    Result.B := Pixel.B / Pixel.A;
  end
  else
  begin
    Result.R := 0;
    Result.G := 0;
    Result.B := 0;
  end;
end;


SMF spam blocked by CleanTalk