Sunday, July 5, 2020

#1 2020-05-05 07:51:27 am

Joy
Member
From:: South Tirol
Registered: 2008-07-04
Posts: 642
Website

Sips VS mdls

I'm puzzled.
Usually my preferred method to extract measurements of pictures (width and hight) was to invoke sips.

For some time now, I didn't see, but only sporadic, that the width and hight values weren't in the right sequence,  hight was measured as width, width measured as hight. Maybe because sips was reading data from the picture's original orientation shot with the camera ?

I don't know, as most of the pictures in Finder have the right hight and width, interrogating sips.
Only some picture files in sips have exchanged measures.
Now, I tried another approach and used mdls instead.
Result : sips was wrong and mdls right.
Finally, I'd like to know if the fault is mine or if mdls is the better way to extract info? Thanks for any suggestion

Applescript:

tell application "Finder" to set sel to item 1 of (get the selection) as text

#set {H, W} to {word 2 of item 1, word 2 of item 2} of paragraphs of (do shell script "sips -g pixelHeight -g pixelWidth '" & POSIX path of sel & "' | tail -2")

set {H, W} to {word -1 of item 1, word -1 of item 2} of paragraphs of (do shell script "mdls -name kMDItemPixelHeight -name kMDItemPixelWidth " & POSIX path of sel)
log {H, W}

Some output I get :

Applescript:

tell current application
   do shell script "sips -g pixelHeight -g pixelWidth '/Users/home/Pictures/IMG_6999.jpg' | tail -2"
       --> " pixelHeight: 3456\r pixelWidth: 5184"
   (*3456, 5184*)
   do shell script "mdls -name kMDItemPixelHeight -name kMDItemPixelWidth /Users/home/Pictures/IMG_6999.jpg"
       --> "kMDItemPixelHeight = 5184\rkMDItemPixelWidth = 3456"
   (*5184, 3456*)
end tell

Last edited by Joy (2020-05-05 08:02:45 am)

Offline

 

#2 2020-05-05 09:56:15 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4534

Re: Sips VS mdls

Just look at that.
I selected two versions of the same picture


Applescript:

tell application "Finder" to set {img1, img2} to items 1 thru 2 of (get the selection as alias list)

set infos1 to (do shell script "mdls -name kMDItemPixelHeight -name kMDItemPixelWidth -name kMDItemOrientation " & quoted form of POSIX path of img1)
set infos2 to (do shell script "mdls -name kMDItemPixelHeight -name kMDItemPixelWidth -name kMDItemOrientation " & quoted form of POSIX path of img2)

the log history was :

Applescript:

tell application "Finder"
   get selection
       --> {alias "SSD 1000:Users:**********:Desktop:images:DSC_0257 - rotated.jpg", alias "SSD 1000:Users:**********:Desktop:images:DSC_0257.JPG"}
end tell
tell current application
   do shell script "mdls -name kMDItemPixelHeight -name kMDItemPixelWidth -name kMDItemOrientation '/Users/**********/Desktop/images/DSC_0257 - rotated.jpg'"
       --> "kMDItemOrientation = 0
kMDItemPixelHeight = 1746
kMDItemPixelWidth = 3104"
   do shell script "
mdls -name kMDItemPixelHeight -name kMDItemPixelWidth -name kMDItemOrientation '/Users/**********/Desktop/images/DSC_0257.JPG'"
       --> "
kMDItemOrientation = 1
kMDItemPixelHeight = 3104
kMDItemPixelWidth = 1746"
end tell

Which is what would be returned by sips.

On my side I would use none of them but:

Applescript:

use AppleScript version "2.5" -- 10.11 or later
use framework "Foundation"
use scripting additions

on grabThreeInfos:aFile
   set theNSURL to current application's NSURL's fileURLWithPath:(POSIX path of aFile)
   set nsMetaItem to current application's NSMetadataItem's alloc()'s initWithURL:theNSURL
   # Build a list of every available metadatas
   set theMetadata to nsMetaItem's valuesForAttributes:(nsMetaItem's attributes())
   # Duplicate the dictionary in a mutable one from which we may remove items.
   set theKey to "kMDItemPixelCount"
   return {(nsMetaItem's valueForAttribute:"kMDItemOrientation") as string, (nsMetaItem's valueForAttribute:"kMDItemPixelHeight") as string, (nsMetaItem's valueForAttribute:"kMDItemPixelWidth") as string}
end grabThreeInfos:

tell application "Finder" to set {img1, img2} to items 1 thru 2 of (get the selection as alias list)
set infos1 to my grabThreeInfos:img1
log result (*0, 1746, 3104*)
set infos2 to my grabThreeInfos:img2
log result (*1, 3104, 1746*)

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 5 mai 2020 17:56:07

Last edited by Yvan Koenig (2020-05-05 09:59:16 am)

Offline

 

#3 2020-05-05 10:30:02 am

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 532

Re: Sips VS mdls

Joy wrote:

Finally, I'd like to know if the fault is mine or if mdls is the better way to extract info? Thanks for any suggestion



Joy. I don't have an answer to your question but thought I would add some data FWIW.

I found a digital photo which I had taken in portrait mode and which showed different width/height results with Sips and Mdls. The pertinent Exif data obtained with exiftool was:

Exif Image Width 3072
Exif Image Height 2304
Orientation: Rotate 90 CW

Preview, Sips, and Image Events showed the image width as 3072 but Mdls showed the image width as 2304. I also tried Yvan's second script and it returned the following for the test image. It appears that 3072 is the reported height.

(*1, 3072, 2304*)

I don't know if MDLS is a better data source, but it certainly doesn't appear you are doing anything wrong.

Last edited by peavine (2020-05-05 11:00:13 am)


2018 Mac mini - macOS Catalina

Offline

 

#4 2020-05-05 11:50:16 am

Joy
Member
From:: South Tirol
Registered: 2008-07-04
Posts: 642
Website

Re: Sips VS mdls

@Yvan
Great examples, I shall give a try to your Objc code.
And yeah, I omitted kMDItemOrientation because the Metadata was always set on 1 ( rotated), be it for files with or without the right measurements, very odd...

@peavine
Yep, so I'm not an isolated case wink
The Finder must read picture's measurements from the Metadata, because height and width are always correct. Which isn't the case if I'm using sips

Offline

 

#5 2020-05-05 11:53:10 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4534

Re: Sips VS mdls

I made complementary tests with mdls.

It makes no difference between a picture rotated 90° left or 90° right
It makes no difference too between an original picture and the same rotated 180°

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 5 mai 2020 19:52:54

Last edited by Yvan Koenig (2020-05-05 12:37:31 pm)

Offline

 

#6 2020-05-05 12:07:05 pm

KniazidisR
Member
Registered: 2019-03-03
Posts: 1259

Re: Sips VS mdls

Yvan Koenig wrote:

I made complementary tests with mdls.
It makes no difference between a picture rotated 90° left or 90° right


This could not be tested. It is enough to realize that a rectangle rotated 90 degrees clockwise or counterclockwise should have the same height x width. You didn’t check the image rotated 360 degrees. I am sure that in your extensive log-record you will find the original rectangle. Also, it would be nice to test from 720 degrees, etc.

It would be better to test the image by deleting the exif data, rotating it 90 degrees (enough in one direction).

Last edited by KniazidisR (2020-05-05 12:15:54 pm)


Model: MacBook Pro
OS X: Catalina 10.15.4
Web Browser: Safari 13.1
Ram: 4 GB

Offline

 

#7 2020-05-05 12:43:05 pm

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4534

Re: Sips VS mdls

I just wanted to see if the tool was making the difference between rotation 90° left and 90° right which makes a serious difference about what we see, same interrogation between  a rotation 0° and a rotation 180° which makes a real difference too.
Is it really useful to add that I know that rotation 0° and rotation 360° give the same result ?

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 5 mai 2020 20:42:59

Offline

 

#8 2020-05-05 04:06:22 pm

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 532

Re: Sips VS mdls

This script uses exiftool and returns a list containing image width and height based on the value of the orientation exif tag.

Applescript:

set landscapeOrientation to {"Horizontal (normal)", "Rotate 180"}
set portraitOrientation to {"Rotate 90 CW", "Rotate 270 CW"}

tell application "Finder" to set theFile to selection as alias
set theFile to quoted form of POSIX path of theFile

do shell script "/usr/local/bin/exiftool -s3 -ImageWidth -ImageHeight -orientation " & theFile
set imageData to paragraphs of result

if item 3 of imageData is in landscapeOrientation then
   set {imageWidth, ImageHeight} to {item 1, item 2} of imageData
else if item 3 of imageData is in portraitOrientation then
   set {imageWidth, ImageHeight} to {item 2, item 1} of imageData
end if

BTW, I was curious if there are any standards as to the Exif orientation tags and found that there are:

1 = Horizontal (normal)
2 = Mirror horizontal
3 = Rotate 180
4 = Mirror vertical
5 = Mirror horizontal and rotate 270 CW
6 = Rotate 90 CW
7 = Mirror horizontal and rotate 90 CW
8 = Rotate 270 CW



https://exiftool.org/TagNames/EXIF.html

Last edited by peavine (2020-05-07 08:59:47 am)


2018 Mac mini - macOS Catalina

Offline

 

#9 2020-05-05 06:50:53 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6395

Re: Sips VS mdls

Width and height mean different things in different contexts.

Orientation is a purely metadata concept, designed so photos can automatically be rotated when opened. It makes sense that Spotlight metadata reflects the orientation in its values, given its use for things like Finder info -- user-facing values. It's possible the EXIF result reflects its use in the days before orientation metadata, and is avoiding potential ambiguity.

In the case of sips, the values are used for clipping, scaling, etc, and they therefore need to reflect the pixel values in the actual image data of the file, ignoring any metadata. When sips opens a file, it doesn't consult the metadata for orientation (or anything else).

So which tool you use should depend on what you're using the values for.

Here's an alternative that returns values similar to sips.

Applescript:

use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set theFile to posix path of (choose file)
set imageRep to current application's NSBitmapImageRep's imageRepWithContentsOfFile:theFile
set theWidth to imageRep's pixelsWide()
set theHeight to imageRep's pixelsHigh()


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#10 2020-05-05 06:58:58 pm

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 532

Re: Sips VS mdls

Shane Stanley wrote:

Orientation is a purely metadata concept, designed so photos can automatically be rotated when opened. It makes sense that Spotlight metadata reflects the orientation in its values, given its use for things like Finder info -- user-facing values. It's possible the EXIF result reflects its use in the days before orientation metadata, and is avoiding potential ambiguity.



Shane.Do you know where MDLS obtains the portrait/landscape data from? How does macOS know if I held my phone in landscape or portrait mode when I took a photo. Thanks.

Last edited by peavine (2020-05-05 07:27:04 pm)


2018 Mac mini - macOS Catalina

Offline

 

#11 2020-05-05 07:01:08 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6395

Re: Sips VS mdls

peavine wrote:

How does macOS know if I held my phone in landscape or portrait mode when I took a photo.



The phone adds orientation metadata to the image. It's in the exif data, and it may well be in some Apple-specific metadata. The actual arrangement of pixels in terms of across-by-down is always landscape, though.

Last edited by Shane Stanley (2020-05-05 07:02:17 pm)


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#12 2020-05-05 07:14:14 pm

peavine
Member
From:: Prescott, Arizona
Registered: 2018-09-04
Posts: 532

Re: Sips VS mdls

Shane Stanley wrote:

The phone adds orientation metadata to the image. It's in the exif data, and it may well be in some Apple-specific metadata. The actual arrangement of pixels in terms of across-by-down is always landscape, though.



Thanks Shane. What you say makes sense, because I couldn't find a single digital photo in which the exif pixel height was greater than the pixel width.

I looked at every exif tag for my Pixel phone and the only orientation-related tag was named "orientation". So, in this sense, the issue appears fairly simple.


2018 Mac mini - macOS Catalina

Offline

 

#13 2020-05-06 03:47:00 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4534

Re: Sips VS mdls

peavine wrote:


BTW, I was curious if there are any standards as to the Exif orientation tags and found that there are:

1 = Horizontal (normal)
2 = Mirror horizontal
3 = Rotate 180
4 = Mirror vertical
5 = Mirror horizontal and rotate 270 CW
6 = Rotate 90 CW
7 = Mirror horizontal and rotate 90 CW
8 = Rotate 270 CW



https://exiftool.org/TagNames/EXIF.html



Thanks for that peavine, I was trying to see if the rotation returned in metadatas was giving such detailed information.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mercredi 6 mai 2020 11:46:54

Offline

 

#14 2020-05-06 10:36:57 am

Fredrik71
Member
Registered: 2019-10-23
Posts: 279

Re: Sips VS mdls

Shane Stanley wrote:

Here's an alternative that returns values similar to sips.



After I did this...

nm /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit | grep -i imageRepWith



This one will also work, but I do not know the difference from yours Shane.

Applescript:

use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property |⌘| : a reference to current application

set theFile to POSIX path of (choose file)

set imageRep to |⌘|'s NSImageRep's imageRepWithContentsOfFile:theFile

set theWidthFile to imageRep's pixelsWide()
set theHeightFile to imageRep's pixelsHigh()
set result to {theWidthFile, theHeightFile}


I  have skied the highest mountain without logic, and still its the imagination that take me anywhere. Its the desire of something that matters for any knowledge I have or could learn.

Offline

 

#15 2020-05-06 01:54:21 pm

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4534

Re: Sips VS mdls

There are two differences between your code and Shane's one

(1) you define a property :

Applescript:

property |⌘| : a reference to current application

alloying you to use below a concise syntax:

Applescript:

set imageRep to |⌘|'s NSImageRep's imageRepWithContentsOfFile:theFile

although Shane use the standard spelling

Applescript:

set imageRep to current application's NSBitmapImageRep's imageRepWithContentsOfFile:theFile

In fact you don't call the same Class: NSImageRep versus  NSBitmapImageRep but I'm not sure that I really understand the difference between them (if it really exists).

The use of the property may be interesting when a script make numerous use of current application.
When there is a single occurence, it requires more typing than the standard spelling.
More, when there are numerous occurences, the short syntax may be easier to read.

It's mostly interesting in a variation:

Applescript:

property |NSURL| : a reference to current application's NSURL
property NSArray : a reference to current application's NSArray

alloying the concise syntax:

Applescript:

|NSURL|'s fileURLWithPath:(POSIX path of theFileOrPathInput)
set anArray to (NSArray's arrayWithObject:aList

which is more readable than the verbose:

Applescript:

current application's NSURL's fileURLWithPath:(POSIX path of theFileOrPathInput)
set anArray to (current application's NSArray's arrayWithObject:aList

mostly when such ones appears quite often
but clearly it's mostly matter of taste, except when for some unknown reason, instructions perfectly correct refuse to compile as I met some days ago.
The problem disappeared after copying the entire script an pasting into a new blank one.
Seems simple days after but frustrating as long as the copy/paste scheme doesn't come to mind.

(2) You added an extraneous instruction gathering the two grabbed values in a single object :

Applescript:

set result to {theWidthFile, theHeightFile}

All in all both versions are technically identical.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mercredi 6 mai 2020 21:37:14

Last edited by Yvan Koenig (2020-05-06 02:01:19 pm)

Offline

 

#16 2020-05-06 03:18:45 pm

Fredrik71
Member
Registered: 2019-10-23
Posts: 279

Re: Sips VS mdls

Yvan, the difference I was applying to was Shane's NSBitmapImageRep vs and mine use NSImageRep

nm command give me:

_OBJC_METACLASS_$_NSBitmapImageRep
also this  +[NSBitmapImageRep imageRepWithData:]

The nm command also give me _OBJC_METACLASS_$_NSImageRep
and +[NSImageRep imageRepWithContentsOfFile:]

Reading this page.
https://www.cocoawithlove.com/2010/01/w … ive-c.html

The meta-class is the class for a Class object. Every Class has its own unique meta-class (since every Class can have its own unique list of methods). This means that all Class objects are not themselves all of the same class.

The meta-class will always ensure that the Class object has all the instance and class methods of the base class in the hierarchy, plus all of the class methods in-between. For classes descended from NSObject, this means that all the NSObject instance and protocol methods are defined for all Class (and meta-class) objects.

All meta-classes themselves use the base class' meta-class (NSObject meta-class for NSObject hierarchy classes) as their class, including the base level meta-class which is the only self-defining class in the runtime.

Last edited by Fredrik71 (2020-05-06 03:34:45 pm)


I  have skied the highest mountain without logic, and still its the imagination that take me anywhere. Its the desire of something that matters for any knowledge I have or could learn.

Offline

 

#17 2020-05-06 05:33:29 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6395

Re: Sips VS mdls

NSBitmapImageRep is a subclass of NSImageRep, so it inherits all the methods of its superclass.

The basic difference between our scripts is that if you choose a file that doesn't contain a bitmap image — say a PDF — my script will throw an error saying it can't make an NSBitmapImageRep from it, whereas Fredrik's will succeed on that line but fail when he tries to get the number of pixels, because he has an NSPDFImageRep, which has no pixelsWide and pixelHigh methods.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#18 2020-05-07 04:37:18 am

Fredrik71
Member
Registered: 2019-10-23
Posts: 279

Re: Sips VS mdls

Thanks Shane for your (easy to understand) explanation.

I find other code from you on this forum so I made other example.

Here you use NSImage

Applescript:

use AppleScript version "2.5"
use framework "Foundation"
use framework "AppKit"
use scripting additions

set theFile to POSIX path of (choose file)

set theImage to current application's NSImage's alloc()'s initWithContentsOfFile:theFile

-- Size of the image
set theSize to theImage's |size|()
log theSize --> width:856.0, height:1280.0

set theObject to theImage's representations()'s firstObject()
log (theObject's className() as text) --> NSBitmapImageRep

set theWidth to theObject's pixelsWide()
set theHeight to theObject's pixelsHigh()
log ({theWidth, theHeight})


I  have skied the highest mountain without logic, and still its the imagination that take me anywhere. Its the desire of something that matters for any knowledge I have or could learn.

Offline

 

#19 2020-05-07 07:22:06 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6395

Re: Sips VS mdls

The size of an NSImage is in points, not pixels. If you only need the pixels, there's no need to go via anNSImage.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#20 2020-05-07 08:06:55 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4534

Re: Sips VS mdls

Fredrik71 wrote:

Yvan, the difference I was applying to was Shane's NSBitmapImageRep vs and mine use NSImageRep


Isn't it what I wrote as:

In fact you don't call the same Class: NSImageRep versus  NSBitmapImageRep but I'm not sure that I really understand the difference between them (if it really exists).



Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) jeudi 7 mai 2020 16:06:50

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)