Problem rotating image file

I’m trying to use the following to rotate an image in the folderItem f.

Each time I run the routine the duration gets longer (0.1sec, 1sec, 15sec …) and on the 4th run it crashes with a nil object exception at the point indicated below.

Another thing I notice is that the file size doubles on each rotation…which might explain some timing.

Can anyone shine a light on where it is going wrong?

[code]Dim t1 As Double = MillisecondsMBS
//grab the date
Dim d As date = f.CreationDate

//from mbs ciFilterAffineTransformMBS class documentation
Dim image As New CIImageMBS(f)

Dim n As New NSAffineTransformMBS
n.rotateByDegrees(If (Keyboard.AsyncOptionKey, 90, -90))

Dim transformFilter As New CIFilterAffineTransformMBS
transformFilter.inputImage = image
transformFilter.inputTransform = n

Dim resultImage As CIImageMBS = transformFilter.outputImage
Dim outputImage As NSImageMBS = resultImage.RenderNSImage(False)

//display the rotated
pic = outputImage.CopyPictureWithMask

Dim name As String = f.NameWithoutExtensionMBS
Dim extn As String = f.NameExtensionMBS
Dim parent As FolderItem = f.parent

mfo = New MacFileOperationMBS
Dim options As Integer = MacFileOperationMBS.kFSFileOperationDefaultOptions
Dim interval As Double = 1

//rename the old file = “oldfile” + “.” + extn

//check the target file is clear
Dim f1 As FolderItem = parent.child(name + “.” + extn)

If f1.exists Then
mfo.MoveObjectToTrash(f1, options, interval)
End If


Dim b As BinaryStream = BinaryStream.create(f1, True)

If b = Nil Or outputImage = Nil Then
//can be GIF, JPEG, TIFF, PNG
b.write outputImage.JPEGRepresentation //crashes here on 4th run with Nil Object Exception
End If


//delete the old file
mfo.MoveObjectToTrash(f, options, interval)

//repoint f at the new file
f = new folderItem( f1.NativePath, folderitem.PathTypeNative)

Catch err As IOException

Dim i As Integer = MsgBox( Str(err.ErrorNumber) + “:” + err.Message, 0)

End Try

lb1.addRow(Str( MillisecondsMBS-t1) )


Is the image Square or Rectangular?

Can be either, but the examples I’ve used are all rectangular.

Check the dimensions after you rotate. I’d bet that they’re square with white space afterwards.

Just out of curiosity, how big are the images you are rotating? Width & height-wise.

They are Jpegs, say 7M.

Just checked - they rotate but outputImage.width and .height show they are still rectangular - but the dimensions double each time - so an example goes from: 3456:5184 to 10368:6912.

Do you have a HiDPI screen? I’m working on something similar (CIFilterLanczosScaleTransformMBS) and had to adjust for the scale factor.

Interesting Beatrix. I just turned off hi-dpi and that fixes the ballooning effect.

So how do I change the scaling for a hiDpi screen? ie is there a way of doing it in one movement in Affine transformations - as the process does seem quite slow.

I’m currently investigating myself. Could this be a bug? I really only need a fixed image size and don’t want to adjust for HiDPI. Especially since my class is deep in the class hierarchy and the result is for the database and not meant for viewing in the class.

This seems to work - simply adding the additional transformation into the Affine Transform - seems to do it in one move.

Thanks for the help.

[code]Dim n As New NSAffineTransformMBS
n.rotateByDegrees(If (Keyboard.AsyncOptionKey, 90, -90))

Dim transformFilter As New CIFilterAffineTransformMBS
transformFilter.inputImage = image
transformFilter.inputTransform = n

Dim resultImage As CIImageMBS = transformFilter.outputImage[/code]

However, since ScaleFactor is window dependent - it actually changes as you move the app’s window to different screens, better to use:

n.scale(if(app.supportsHiDPI, 0.5, 1) )

@Christian Schmitz : what do you say? Should the CIFilters be dependent on the scale factor? I still this that this is pretty weird.

It’s because (at least in James’ example) you’re creating a NSImage, which is designed for use in controls, so you’d want it to support HIDPI on a HIDPI screen.

Instead create a CGImage, or draw the CIImage into a Xojo graphics object.

My code is similar. I had wondered about the convoluted code:

dim img as CIImageMBS = filter.outputImage dim nimg as NSImageMBS = img.RenderNSImage(false) dim resultPic as Picture = nimg.CopyPictureWithAlpha

When I use

dim img as CIImageMBS = filter.outputImage dim resultPic as Picture = = img.RenderPicture

instead then I get what I want.

Thanks, Sam!

Ah, thanks Sam, that’s about 60% faster too.

The convoluted code came from Christian’s example code for CIFilterAffineTransformMBS - it did look hard work.

[quote=415165:@Beatrix Willius]instead then I get what I want.
Thanks, Sam![/quote]

Glad I could help.