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

Post reply

Other options

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

Topic summary

Posted by Galfar
 - 20 December 2011, 03:54:31
Bug was found and fixed. GTK2 uses different RB order than Win/Qt/Carbon widget sets and it
wasn't checked when converting from LCL bitmap back to Imaging. I'll update repository tomorrow.

Basically, LCL/VCL stuff was added to get ability to simply display Imaging's internal image formats
in GUI apps. If you just want to load/rotate/scale/save there's no need to use LCL stuff.

Btw, ifA32R32G32B32F seems like an overkill (128bits per pixel) that the file formats you use
for saving just convert back to 24/32bit.
Posted by mjoyner@vbservices.net
 - 14 December 2011, 01:22:01
Really not sure where your classes end and the LCL stuff begins. Just know that I read that I needed your classes to load image with automatic detection of image type and also using your functions for basic image rotate and scale operations at the moment.

Here is a copy of the subroutine.

Code (pascal) Select

function processImage(Filename: UTf8String): imgInfo;
  const
  {$J+}
    image: TSingleImage = nil;
    png: TImagingPNG = nil;
    jpg: TImagingJpeg = nil;
  {$J-}
  var
    info: imgInfo;
    tmpFile: UTF8String;
    tmpJPG: UTF8String;
    tmpPNG: UTF8String;
    scaleByH: double;
    scaleByW: double;
    scaleBy: double;
    newWidth: longint;
    newHeight: longint;
    jpgQuality: longint;
  begin
    //info=imgInfo;
    if UI.cbShowDebug.Checked then frmDebug.ShowOnTop;
    if image = nil then begin
      image := TSingleImage.Create;
      png := TImagingPNG.Create;
      jpg := TImagingJpeg.Create;
      end;
    {load image}
    image.Clear;
    frmDebug.memoDebug.Append(Filename);
    image.LoadFromFile(Filename);

    {basic transforms to ensure internal consistancy}
    ConvertImage(image.ImageDataPointer^, ifA32R32G32B32F);

    frmDebug.memoDebug.Append('Size: ' + IntToStr(image.Width) + 'x' +
      IntToStr(image.Height));

    {rotate check?}
    if UI.cbRotate.Checked then if portrait then begin
        if (image.Width > image.Height) then begin
          UI.ProcessMessages;
          RotateImage(image.ImageDataPointer^, 90);
          frmDebug.memoDebug.Append('Rotated Size: ' + IntToStr(image.Width) +
            'x' + IntToStr(image.Height));
          end;
        end else {landscape} if (image.Height > image.Width) then begin
          UI.ProcessMessages;
          RotateImage(image.ImageDataPointer^, -90);
          frmDebug.memoDebug.Append('Rotated Size: ' + IntToStr(image.Width) +
            'x' + IntToStr(image.Height));
          end;

    {rescale check?}
    if UI.cbRescale.Checked then begin
      {rescale down maxpect}
      frmDebug.memoDebug.Append('Maxpect Size: ' + IntToStr(imageMaxpectWidth) +
        'x' + IntToStr(imageMaxpectHeight));
      UI.ProcessMessages;
      scaleByW := imageMaxpectWidth / (image.Width * 1.0);
      scaleByH := imageMaxpectHeight / (image.Height * 1.0);

      if ((scaleByW < 1) or (scaleByH < 1)) then begin
        if scaleByW < scaleByH then scaleBy := scaleByW
        else
          scaleBy := scaleByH;
        newWidth := Round(scaleBy * image.Width);
        newHeight := Round(scaleBy * image.Height);
        ResizeImage(image.ImageDataPointer^, newWidth, newHeight, rfBicubic);
        frmDebug.memoDebug.Append('New Size: ' + IntToStr(image.Width) +
          'x' + IntToStr(image.Height));
        end;

      {rescale up maxpect}
      if (scaleByW > 1) and (scaleByH > 1) then begin
        if scaleByW < scaleByH then scaleBy := scaleByW
        else
          scaleBy := scaleByH;

        newWidth := Round(scaleBy * image.Width);
        newHeight := Round(scaleBy * image.Height);
        ResizeImage(image.ImageDataPointer^, newWidth, newHeight, rfBicubic);
        frmDebug.memoDebug.Append('New Size: ' + IntToStr(image.Width) +
          'x' + IntToStr(image.Height));

        end;
      end;

    {work around Red/Blue swap on Assign issue, all further
    assigns will swap the Red/Blue back to correctness, if the
    bug does not exist (WIN32 for example), it is just extra
    data being moved around with only a minor cpu impact}

    png.AssignFromImage(image);
    png.AssignToImageData(image.ImageDataPointer^);

    {save as temporary png file}
    tmpPNG := mkstemp;
    png.AssignFromImage(image);
    png.CompressLevel := 9;
    png.PreFilter := 6;
    png.SaveToFile(tmpPNG);

    {save as temporary jpg file}
    tmpJPG := mkstemp;
    jpg.AssignFromImage(image);
    jpgQuality:=UI.seJpgQ.Value;


    jpg.Quality := jpgQuality;
    jpg.SaveToFile(tmpJPG);

    if  (FileSize(tmpPNG)>(UI.seJpgSize.Value*1024)) then begin
        while (FileSize(tmpJPG) > UI.seJpgSize.Value*1024)
        and (jpgQuality>=0) do begin
            jpgQuality -= 1;
            jpg.Quality := jpgQuality;
            jpg.SaveToFile(tmpJPG);
        end;
    end;


    {which is smaller?}
    if (FileSize(tmpJPG) < FileSize(tmpPNG)) then tmpFile := tmpJPG
    else
      tmpFile := tmpPNG;
    Result[0] := tmpFile;
    Result[1] := DetermineFileFormat(tmpFile);
    Result[2] := IntToStr(image.Width);
    Result[3] := IntToStr(image.Height);
    Result[4] := '';

  end;           
Posted by Galfar
 - 13 December 2011, 18:55:38
Look's like it is GTK2 interface or LCL RawImage related issue when converting
from LCL bitmap back to Imaging's image.
Just installed x64 Linux and started debugging...

Btw: Are you using classes from ImagingComponents unit just for saving?
Posted by mjoyner@vbservices.net
 - 12 December 2011, 04:27:02
I found out it is happening during an ASSIGN op:

Code (pascal) Select


    tmpJPG := mkstemp;
    image.SaveToFile('/tmp/test.jpg');
    image.SaveToFile('/tmp/test.png');
    jpg.AssignFromImageData(image.ImageDataPointer^);
    jpg.Quality := Comics2ePubUI.seJpgQ.Value;
    jpg.SaveToFile(tmpJPG);                         



I have tried:

jpg.Assign(image)
jpg.AssignFromImageData(image.ImageDataPointer^)
jpg.AssignFromImage(image)


....


OK, I think I found wherein it lies.

It is specifically the Assign and AssignFromImage*

Code (pascal) Select


const
  {$J+}
    image: TSingleImage = nil;
    imageSwap: TSingleImage = nil;
    png: TImagingPNG = nil;
    jpg: TImagingJpeg = nil;
  {$J-}
  var
    info: imgInfo;
    tmpFile: UTF8String;
    tmpJPG: UTF8String;
    tmpPNG: UTF8String;
    scaleByH: double;
    scaleByW: double;
    scaleBy: double;
    newWidth: longint;
    newHeight: longint;
  begin
      image := TSingleImage.Create;
      png := TImagingPNG.Create;
      jpg := TImagingJpeg.Create;     

{work around Red/Blue swap on Assign issue, all further
    assigns will swap the Red/Blue back to correctness, if the
    bug does not exist (WIN32 for example), it is just extra
    data being moved around with only a minor cpu impact}

    png.AssignFromImage(image);
    png.AssignToImageData(image.ImageDataPointer^);       


The AssignTo does not seem to be impacted.
Posted by mjoyner@vbservices.net
 - 12 December 2011, 01:41:07
Quote from: mjoyner@vbservices.net on 12 December 2011, 01:37:15
Quote from: Galfar on 12 December 2011, 00:15:53
Hello,

Did this work before you downloaded "working"?

Could you try ifA8R8G8B8 instead of ifA32R32G32B32F in the conversion?





Perhaps a CPU32 vs CPU64 thing?


changing format = no change in channel swap

Posted by mjoyner@vbservices.net
 - 12 December 2011, 01:37:15
Quote from: Galfar on 12 December 2011, 00:15:53
Hello,

Did this work before you downloaded "working"?

Could you try ifA8R8G8B8 instead of ifA32R32G32B32F in the conversion?

What file formats have you loaded from/saved to?


a) It wouldn't compile which is why I am using "working".
b) Will give said format a try in a bit and report back.
c) loading from gif, png, jpg, saving to png, jpg
d) just loaded 32-bit lazarus on my windows vm, it doesn't swap colors (what a painful experience..)

Have also discovered that "FileOpen" FHANDLE can hold "-1" on linux/x64 but shows up instead as 4294967295 when assigned -1 on W32 ???

Perhaps a CPU32 vs CPU64 thing?


Posted by Galfar
 - 12 December 2011, 00:15:53
Hello,

Did this work before you downloaded "working"?

Could you try ifA8R8G8B8 instead of ifA32R32G32B32F in the conversion?

What file formats have you loaded from/saved to?
Posted by mjoyner@vbservices.net
 - 11 December 2011, 19:36:41
Hello,

Thanks for this library!

Downloaded the latest "working" and all the images I load and save have the red and blue channels swapped.

If I put this:

Code (pascal) Select


image.LoadFromFile(Filename);

    {basic transforms to ensure internal consistancy}
    ConvertImage(image.ImageDataPointer^, ifA32R32G32B32F);

    {work around Blue/Red channel swap bug}
    image.SwapChannels(ChannelRed, ChannelBlue);



It seems to help.

I am Ubuntu, X64, Lazarus 0.9.30.2-0, FPC Version: 2.4.4, GTK2
SMF spam blocked by CleanTalk