Want to highlight a helpful answer? Upvote!

Did someone help you, or did an answer or User Tip resolve your issue? Upvote by selecting the upvote arrow. Your feedback helps others! Learn more about when to upvote >

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Sort image files by average luminance and by average hue?

Hi. I would like to be able to sort images by average luminance and by average hue. Is there anything in OS X that will let me determine the average luminance or average hue of an image, and save that datum to the image?


Ultimately, I would like to use this within Aperture (my sole area of expertise {all my ASC points are from the Aperture forum}). After I posted the question there, a regular suggested I post in this forum to find out what is possible: specifically, are there any AppleScript hooks that might allow this? (Sadly, I don't script, but it helps me know what can be done.)


I know of one program which does this: CF/X's Photo Mosaic, which uses the averages to match an image to a tile in the "master image". I don't know of any way to attach the Photo-Mosaic-generated averages to the files themselves. I asked CF/X about this today.


Thanks.

Posted on Jul 10, 2014 3:27 PM

Reply
Question marked as Best reply

Posted on Jul 10, 2014 3:42 PM

I'm not aware of anything in Aperture that provides this information. It's nothing I've ever seen either in the script hooks or within Aperture itself.


It would be something that would need to be computed by looking at the values in the image itself. Searching turns up a number of hits describing how to do it, such as Mean luminance Values of an Image - MathWorks but knowing the math and actually performing the operation on an image are two different things.


Perhaps with some further searching something might turn up

4 replies
Question marked as Best reply

Jul 10, 2014 3:42 PM in response to Kirby Krieger

I'm not aware of anything in Aperture that provides this information. It's nothing I've ever seen either in the script hooks or within Aperture itself.


It would be something that would need to be computed by looking at the values in the image itself. Searching turns up a number of hits describing how to do it, such as Mean luminance Values of an Image - MathWorks but knowing the math and actually performing the operation on an image are two different things.


Perhaps with some further searching something might turn up

Jul 11, 2014 2:06 AM in response to Kirby Krieger

I'm working on a scripting tool that provides as part of its functionality access to Apple's CoreImage routines.


CoreImage has a area average filter that calculates the average value for each colour component (RGB space) of an image.


I can write a script that will get the average image colour value for your images. But I perceive a couple of problems.


How do you convert the RGB result to Luminance and Hue values? I don't know the math. Secondly there may be issues with color matching though I believe this is solvable.


If your interested let me know.


Kevin

Jul 11, 2014 3:19 AM in response to Kirby Krieger

Just had a quick look, there seems to be some fairly standard algorithms for converting from rgb to hsl, though I couldn't see anything that told me what rgb color profile those algorithms were using. I am assuming an equivalent of a core graphics generic linear rgb color space.


Though my scripting tool can be used from AppleScript I've written a library of methods using ruby to drive it. Ruby comes with OS X.


Kevin

Jul 12, 2014 2:23 AM in response to Kirby Krieger

Hello


You may try the AppleScript script listed below. It is a simple wrapper of rubycocoa script which uses CIFilter to calculate average brightness and hue of each image (jpg|jpeg|png) in specified directory tree. It is a skeleton just to generate a TSV output of [brightness, hue, file] records sorted by brightness and then hue on desktop. I don't know how to embed these info into image metabata.


Script is briefly tested under 10.6.8.


Hope this may help somehow,

H


PS. If copied code has extra spaces in front of every line, which appears to be the case with some browsers including Firefox, please remove them before running the script.



-- SCRIPT
set d to (choose folder with prompt "Choose start folder")
set args to d's POSIX path's quoted form

do shell script "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby -w <<'EOF' - " & args & " > ~/desktop/test_out.txt
#
#     get average brightness and hue of image files (jpg|jpeg|png)
#
#     * output record = B=brightness [TAB] H=hue [TAB] file [LF]
#     * sorted by brightness and then hue
#
require 'osx/cocoa'
include OSX

EXTS = %w[ jpg jpeg png ]    # target extensions

module OSX
    class << CIContext
        def contextWithSize(w, h)
            br = NSBitmapImageRep.alloc.objc_send(
                :initWithBitmapDataPlanes, nil,
                :pixelsWide, w,
                :pixelsHigh, h,
                :bitsPerSample, 8,
                :samplesPerPixel, 4,
                :hasAlpha, true,
                :isPlanar, false,
                :colorSpaceName, NSCalibratedRGBColorSpace,
                :bytesPerRow, 0,
                :bitsPerPixel, 0)
            c = NSGraphicsContext.graphicsContextWithBitmapImageRep(br)
            CIContext.objc_send(:contextWithCGContext, c.graphicsPort , :options, {})
        end
    end
    class CIFilter
        def setParameters(dict)
            self.setValuesForKeysWithDictionary(dict)
        end
        def output
            self.valueForKey('outputImage')
        end
    end
    class << CIVector
        def vectorWithRect(r)
            self.vectorWithX_Y_Z_W(r.origin.x, r.origin.y, r.size.width, r.size.height)
        end
    end
end

# process ARGV and retrieve image files with given extensions under specfied directory
raise ArgumentError, %Q[Usage: #{File.basename($0)} directory] unless ARGV.length == 1
dir, = ARGV.map { |a| a == '/' ? a : a.chomp('/')}
ff = %x[find -E \"#{dir}\" -type f -iregex '.*/.*\\.(#{EXTS.join('|')})$' -print0].split(/\\0/)

# get CIContext and CIFilter
cic = CIContext.contextWithSize(5000, 5000)  # let it be large enough
cif = CIFilter.filterWithName('CIAreaAverage')
cif.setDefaults

# retrieve average brightness and hue of images
hh = {}
ff.each do |f|
    u = NSURL.fileURLWithPath(f)
    ci = CIImage.imageWithContentsOfURL(u)
    civ = CIVector.vectorWithRect(ci.extent)
   
    cif.setParameters({'inputImage' => ci, 'inputExtent' => civ})
    ciout = cif.output

    cgout = cic.objc_send(:createCGImage, ciout, :fromRect, ciout.extent)
    colr = NSBitmapImageRep.alloc.initWithCGImage(cgout).colorAtX_y(0, 0)
    hh[f] = { :b => colr.brightnessComponent, :h => colr.hueComponent}
end

# sort criteria
brightness          = lambda { |k| hh[k][:b] }
hue                 = lambda { |k| hh[k][:h] }
brightness_and_hue  = lambda { |k| b, h = hh[k].values_at(:b, :h); b * 1e6 + h }

# print sorted records
hh.keys.sort_by(&brightness_and_hue).each do |k|
    b, h = hh[k].values_at(:b, :h)
    puts %Q[B=%f\\tH=%f\\t%s] %  [b, h, k]
end
EOF"
-- END OF SCRIPT

Sort image files by average luminance and by average hue?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.