Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Match altered image to its original
#11
Using the tiff files, I got quite a good color match using the elsamuko plugin. I did crop the 'letter boxing' top and bottom though.
The correction curve looks like this:

   

A comparison clip attached.  The tiffs are different from the other pngs. The ghosted tiff is less sharp and does not have those 'edge artifacts'  as in the png's.  I wonder what in your processing adds those. Sharpening maybe ?


Attached Files
.gz   corrected.xcf.gz (Size: 401.83 KB / Downloads: 122)
Reply
#12
(11-01-2021, 11:07 AM)Ofnuts Wrote: This is very odd. There are 32 regularly spaced (step=8) peaks in the output histogram (that are the same on all channels). IS the image quantized in the process? If so, forget it, no way you are going to get a proper image after compensation. That would be a bit like transforming a cow so that it eventually comes out alive from the meat grinder.

Odd, indeed.  I couldn't agree more.

You'll see in a moment that I've gone to some lengths to get this mystery to the next level, hopefully toward conclusion; spent the last few hours to gather a meaningful collection.

I'm delighted that you're hanging in here, Ofnuts.  Your assistance dates directly back to 2-20-21, in aiding my grokking of Color Mapping.  You provide – first, accuracy; then clarity; then simplification – in that order, which is how it should be.  So check this out:

I have not given a full account of the known associations with this ghosting.  I knew where lay the cause, but not the why.  For a considerable time, I dodged it; found workarounds; but always said, "Some day I'm gonna hafta' get this damn thing figured out.  So here goes.  I think this'll offer some insights as to possible quantization, even-ness of steps, and so on.

The culprit is Flash Player -associated imagery in PDFs.  So, you have all your regular arsenal of Adobe Acrobat.  I'll have to followup with you on some of my fairly robust productions.  But here's what I've long known – Any placement of Buttons, atop Flash content, brings about this ghosting, affecting the 'internal' Button imagery.  A few points:
  1. It occurs only in the regions where Button overlaps Flash.
  2. It is not evident; everything looks dandy in Buttonville, until the Flash content is 'activated' [which can occur from user interaction, or JavaScript engagement], which immediately initiates the ghost process.
  3. Following activation [in these instances the Flash material consists of video segments], the effect remains, even when the video stops.
  4. The effect is constant, 'even', and unvarying [thank God for that, anyway]
  5. When the content is 'disabled', the overlying button stuff returns to where it was [though, in practice, disabling never really has any reason to occur, so let's just call it 'perpetual' {until document close/reopen, of course; things always open in intended fashion}].
  6. It appears to matter not, the characteristics of the underlying Flash – that is to say, it appears to be in no way dependent on luminosity, contrast, color values, etc. of that video.
  7. Especially remarkably - it matters not a bit whether video is dynamic, or static – moving or still.  So it's not like there's a relation to processing load.
  8. In all my specimens sent this way, video is at a standstill.
  9. Intermediate Buttons, sandwiched atop the video, and beneath the uppermost Button/icon layer, appear to have no effect; i.e. it doesn't help to sandwich in a black button.
  10. Everywhere else in Acrobatville, a layer is a layer is layer.  Not here.  Flash imparts a spooky magnetic, remote, field over them buttons.
Cool, huh?

– – –

Quite a set of specimens have I sent up to the folder, "Flasher the Friendly Ghost".  It's likely more than you need to see, but I believe illustrates the phenomenon accurately.  The file names, especially if gobbled alphabetically, are essentially self-explanatory.

As for what to do about it, I'm not certain that it's beyond hope.  Even a close approximation would be beneficial.  I don't anticipate the need to 'splice'/merge/combine original with ghosted images, as a split-down-the-middle singularity [though that liberty would be grand to have in store].  More typical is that somewhere on the page, or an earlier page, or an upcoming page, there may be conceptual comparison.  I don't wish to impart cognitive discomfort.  To that end, though, sometimes close is good enough.

Ultimately, I can't get around there being a 'flick-of-the-switch' change, at the moment of content activation.  A processed, prepared-for-ghosting image, sitting in place atop Flash, is gonna change at that moment.  I have to live with that.  But I can mitigate, by causing activation when the user is not looking.  The objective is that the activated/prepared-for-ghosting image will then at least closely resemble its unprepared/not-sitting-atop-Flash counterpart, which may reside nearby.

– – –

What do call a cow with no legs?


A: Ground beef.

(11-01-2021, 11:51 AM)rich2005 Wrote: Using the tiff files, I got quite a good color match using the elsamuko plugin. I did crop the 'letter boxing' top and bottom though.
The correction curve looks like this:



A comparison clip attached.  The tiffs are different from the other pngs. The ghosted tiff is less sharp and does not have those 'edge artifacts'  as in the png's.  I wonder what in your processing adds those. Sharpening maybe ?

Cool, Rich.  Thanks.  I'ma check it out.

I will obtain the plugin.

Letterbox, schmetterbox.  Of course.  They have no place here.  That's an artifact of accurately generating the sample specimens, uniform in the region of interest.

Now, tiff, png.  My eventual use demands png, to gain transparency in Adobe Acrobat.  So that's the ultimate production format.  But I do all the Gimp processing from tiffs, when possible.  Unless there's a reason I oughtn't in this instance.  And also I assumed tiffs the way to go in swapping specimens.

You probably gathered that my original original is a jpeg [1500 x 1004].  It's up in the Upload Repository.  Tiff made directly from that.

– – –

Alright – I just looked.  Neat.  They're gonna love you in Amsterdam.

Here's the big-picture question.  As to "what in your processing adds those", That's the whole quandary.  It is not my processing.  It's Adobe's.

Check my latest post here.  I'm really looking beyond an individual instance, and trying to engineer a generalized fix, if there turns out to be a predictable offset/remedy.
Reply
#13
To quote Wikipedia:

The Flash Player was deprecated in 2017 and officially discontinued at the end of 2020 for all users outside China, as well as non-enterprise users, with many web browsers and operating systems scheduled to remove the Flash Player software around the same time.
Reply
#14
(11-03-2021, 12:29 AM)Ofnuts Wrote: To quote Wikipedia:

The Flash Player was deprecated in 2017 and officially discontinued at the end of 2020 for all users outside China, as well as non-enterprise users, with many web browsers and operating systems scheduled to remove the Flash Player software around the same time.

Jeesh, Ofnuts – This is unexpected.  If I might speak frankly, I find it considerably off-topic, as I am addressing a forum on Image Manipulation, not Business Manipulation.  Wikipedia would more correctly state that Adobe has transferred ongoing full support for Flash Player to Harman International [where I have made contacts], as done routinely with other Adobe products, and it remains readily available to 20% of the world's population.

Yes, I have been working since 2017 to find comparable alternatives.  There are none, known to me.  My interest has naught to do with Web presentation, as my prospective enterprise client, the University of Amsterdam Medical Center, requires positioning of visual elements with the precision of 3.6 microns, routinely available in the ISO 32000 standard [aka PDF].  For now, our prototyping continues uninterrupted, until Adobe releases equivalent support for, and logical coordination with, native media players.  This production is solely for a standalone environment.  None of our numerous operating systems have had Flash Player removed [my specimens are from OS X 10.7.5 - macOS 10.15.7], nor does any entity have the authority, nor the capacity, to so do.

Back to the nature of this Forum.  I feel as if I presented a dilemma attempting to match two images taken at my granddaughter's wedding.  One was taken with a Leica M3, and the other, precisely synchronized via photography strobe-light, a Polaroid SX-70.  And the answer comes back – "We can't help you.  Both of those camera models were deprecated."

Harman International's reply has been, "Flash Player is working as specified.  We'd suggest you try a Photoshop Forum to match the images as required."  Regarding the behavior of Acrobat [you'll see below that it distinctly extends beyond Flash Player], Adobe's reply is the same.  I would prefer an open-source solution, as would Amsterdam.

– – –

Let me re-phrase my topic in the context of a non-deprecated business product utilized worldwide by medical researchers, scientists, engineers, law courts, and tax authorities.  You might cheer up to find that I'm not wallowing in naïveté.  And I believe you are wham-slam, right on the cusp of fixing what's going on here.  To wit, your observations questioning "32 regularly spaced (step=8) peaks in the output histogram (that are the same on all channels). IS the image quantized in the process?"  

Consider this the topic:

I have some images which become altered by a process unknown to me, over which I have no control.  It stems from 3D Models in ISO 32000 documents, as rendered by Adobe Acrobat.  When I place a Button Icon atop the model, the icon image is altered, but only in the region overlapping the model.

See the Upload Repository for the folder Adobe Acrobat 3D Models the Friendly Ghost, where you will find files pertaining to those here attached, including .xcf.


Attached Files Thumbnail(s)
           
Reply
#15
Quote:Back to the nature of this Forum.  I feel as if I presented a dilemma attempting to match two images taken at my granddaughter's wedding.  One was taken with a Leica M3, and the other, precisely synchronized via photography strobe-light, a Polaroid SX-70.  And the answer comes back – "We can't help you.  Both of those camera models were deprecated."

No, the analogy is more like you are trying to match up two pictures to create a slide when no one makes slide projectors anymore and even replacement bulbs all come from an abandoned warehouse in Pripyat.

Now, back to the problem t hand. The peaks that appear in the histogram can have only one explanation: several input colors are mapped to the same output color in a much larger scale than what you get when doing some usual color editing. And since there are no gaps in the histogram this also mean that this happens only for some of the pixels and others are unscathed. So figuring out which is which to find an appropriate transform to pre-compensate is going to be an uphill battle. On the other hand, since
Quote:Harman International's reply has been, "Flash Player is working as specified"

then there are specs, and what do they say?
Reply
#16
(11-03-2021, 09:28 PM)Ofnuts Wrote:
Quote:Back to the nature of this Forum.  I feel as if I presented a dilemma attempting to match two images taken at my granddaughter's wedding.  One was taken with a Leica M3, and the other, precisely synchronized via photography strobe-light, a Polaroid SX-70.  And the answer comes back – "We can't help you.  Both of those camera models were deprecated."

No, the analogy is more like you are trying to match up two pictures to create a slide when no one makes slide projectors anymore and even replacement bulbs all come from an abandoned warehouse in Pripyat.

Now, back to the problem t hand. The peaks that appear in the histogram can have only one explanation: several input colors are mapped to the same output color in a much larger scale than what you get when doing some usual color editing. And since there are no gaps in the histogram this also mean that this happens only for some of the pixels and others are unscathed. So figuring out which is which to find an appropriate transform to pre-compensate is going to be an uphill battle. On the other hand, since
Quote:Harman International's reply has been, "Flash Player is working as specified"

then there are specs, and what do they say?


They say, "We specs are the very definition of proprietary/trade-secret mechanisms."  So even though ISO 32000 is an 'open standard' [i.e it's specs are available, free of royalty payment {in contrast with the bulk of ISO standards, for which one must pay to replicate/practice/distribute said standard}], it also accommodates proprietary customization, for add-ons, extensions, plugins, and such.  Adobe Acrobat aptly demonstrates this with Flash Player.

To quote Wikipedia:

the completeness of its public specifications are debated, and no complete implementation of Flash is publicly available in source code form with a license that permits reuse. 

That's what Harman is referring to when they say, "as specified".  You can appreciate that Adobe finds benefit in not disclosing the specs, since they rely on them for current, ongoing competitive product development.  Following the Great Flash Security Scare of 2016, Adobe suffered losses from people fleeing Adobe Flash Professional.  It's a credit to their marketing prowess that they regained those lost customers flocking back, simply by changing the name to Adobe Animate, with essentially no change to the underlying Flash Professional code.

I hope that my reliance on Flash is not out of ignorance, should you or others have suggestions for comparable alternatives.  I'll forgo a detailed account of requirements in this thread.  In general, Web presentation is ruled out due to unsophistication of imagery [e.g. spatial imprecision, low resolution, limited use of transparency, clumsy scaling], device dependence, limited audience reach, connection vulnerabilities, and security weaknesses, but, above all, temporal coordination [intrinsic flaw of all networks], precisely predictable layout and formatting, and re-use, revision, markup, editing, and redistribution, from an initial recipient to subsequently another.  And, critically –– at no, or low, cost.

You are spot-on in identifying the need for "an appropriate transform to pre-compensate".  But let's set aside, for now, a generalized engineering remedy, for all cases.  I would welcome your guidance, particularly as to a conceptual strategy, on how to approach, how to think about, how to go about, where to observe, which buttons to push – you are eminently adept in all those regards – in undertaking a "best shot approximation" for one image pair.

– – –

Back to the wedding photographs.  My granddaughter got married on the stage at the Concertgebouw in Amsterdam (so you've seen the starting pair).  Should I be adjusting RGB Color Curves, only?  Or better off evaluating HCL, HLS?  Brightness and Contrast seem straightforward.

Pointers to Forum threads, tutorials, or related whatnot, would equally be most welcome.

With appreciation,
BR
Reply
#17
Then I have nothing better to suggest than what I have already said.
Reply
#18
Quote:Back to the wedding photographs. My granddaughter got married on the stage at the Concertgebouw in Amsterdam (so you've seen the starting pair). Should I be adjusting RGB Color Curves, only? Or better off evaluating HCL, HLS? Brightness and Contrast seem straightforward.

Have a look at using 'Luminosity Masks' https://patdavid.net/2013/11/getting-aro...ity-masks/ that describes the process in detail, however there are plugins that make them for you.

The other PDF / shockwave stuff, just my opinion but I cannot see the relevance to Gimp. Maybe this https://creativepro.com/how-to-get-anima...ing-title/
Reply
#19
I was looking for answers to another question (Luminosity Match), and ended up bumping into Rob A's Histogram_Match.scm script.

I just did a few tests with this script (it's been a few minutes since I downloaded it) and I don't really know how to use it correctly yet, but the results seemed acceptable to me for the Hall Original and Hall Ghost images.

What do you think? A viable option?

http://www.silent9.com/blog/archives/162...Match.html
                               .....
Samj PortableGimp 2.10.28 - Win-10 /64.
Reply
#20
Scheme 
I noticed that the link above is broken, so for anyone interested I leave the script code below.


Code:
; histogram_match.scm
; by Rob Antonishen
; http://ffaat.pointclark.net

; Version 1.9 (20091227)
;
; Changes
; 1.1 - added options to copy from image or equalize.
;     - added option to resize images for histogram sampling (speed improvement)
; 1.2 - changed calculation methods (Thanks to isomage at http://axiscity.hexamon.net/users/isomage/ )
;     - added preprocessing of saturation and contrast
; 1.3 - changed to always use lp filtering on histograms (thanks saulgoode at gimptalk!)
;     - removed equalize option
; 1.4 - Provides Additional modes of matching, HSV, LAB, and equalize now an option
; 1.5 - Automated the decision to use scaled iamges for sampling.
; 1.6 - Created an option to sample full size images because of problems with some loss when resampling.
; 1.7 - Changed match algorithm to use the weighted averaged best match.
;       This may give suboptimal results for RGB :(
; 1.8 - Updated to use new menu register syntax.
; 1.9 - Avoids overblown highlights and over-burned shadows - best it should get...

; Description
;
; tries to map the histogram from one image to the current image.
;

; License:
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; The GNU Public License is available at
; http://www.gnu.org/copyleft/gpl.html


;make all array elements sum to 1
(define (array-normalize array)
 (let ((total 0)(i 0))
   (while (< i (vector-length array))
     (set! total (+ total (vector-ref array i)))
     (set! i (+ i 1)))
   (set! i 0)
   (while (< i (vector-length array))
     (vector-set! array i (/ (vector-ref array i) total))
     (set! i (+ i 1)))))

;change array to be an imcremental array
(define (array-incremental array)
 (if (> (vector-length array) 1)
   (let ((i 1))
     (while (< i (vector-length array))
       (vector-set! array i (+ (vector-ref array i) (vector-ref array (- i 1))))
       (set! i (+ i 1))))))

;returns a low pass filtered histogram with gaps interpolated as an array
(define (get-hist-lpf drawable chan)
 (let* (
     (i 0)
     (hist (make-vector 256))
     (filt (make-vector 256))
     (last-v 0)
     (last-x 0)
     (max-v 0)
     (alpha 0.3) ; filter smoothing
     (span 1)
     (delta-v 0)
     )
   (set! i 0)
   (while (< i 256)
     (set! last-v (car (last (gimp-histogram drawable chan i i))))
     (vector-set! hist i last-v)
     (set! max-v (max max-v last-v))
     (set! i (+ i 1))
     )
   (set! hist (list->vector (map (lambda (x) (* (/ x max-v) 255)) (vector->list hist))))
   ; filter left-to-right
   (vector-set! filt 0 (vector-ref hist 0))
   (set! i 1)
   (while (< i 256)
     (set! last-v (vector-ref filt (- i 1)))
     (vector-set! filt i (+ last-v (* alpha (- (vector-ref hist i) last-v))))
     (set! i (+ i 1))
     )

   ; adjust by filtering right-to-left and taking minimum value
   (set! i 255)
   (vector-set! filt i (min (vector-ref filt i) (vector-ref hist i)))
   (while (> i 0)
     (set! last-v (vector-ref filt i))
     (set! i (- i 1))
     (vector-set! filt i (min
         (vector-ref filt i)
         (+ last-v (* alpha (- (vector-ref hist i) last-v)))
         )
       )
     )
   
   ; interpolate histogram whereever filtered histogram is less than original
   (set! last-v (vector-ref hist 0))
   (set! last-x 1)
   (set! i 1)
   (while (< i 256)
     (while (and (< i 256)
                 (< (vector-ref hist i) (vector-ref filt i))
                 )
       (set! i (+ i 1))
       )
     (set! span (- i last-x -1))
     (set! delta-v (- (vector-ref hist i) last-v))
     (while (and (< i 256)
                 (< last-x i)
                 )
       (vector-set! hist last-x (+ last-v (* (- span (- i last-x)) (/ delta-v span))))
       (set! last-x (+ last-x 1))
       )
     (set! last-v (vector-ref hist i))
     (set! i (+ i 1))
     (set! last-x i)
     )
   hist
   )
 )

;returns the raw histogram  with values 0-1 as an array
(define (get-hist drawable chan)
 (let* (
     (i 0)
     (hist (make-vector 256))
     )
   (set! i 0)
   (while (< i 256)
     (vector-set! hist i (car (last (gimp-histogram drawable chan i i))))
     (set! i (+ i 1))
     )
   hist
   )
 )

;returns a flat histogram
(define (get-hist-flat)
 (let* (
     (i 0)
     (hist (make-vector 256))
     )
   (set! i 0)
   (while (< i 256)
     (vector-set! hist i 1)
     (set! i (+ i 1))
     )
   hist
   )
 )

;performs the histogram match on a single greyscale channel (layer)
;separate from and to to use scaled, apply is the target layer, smooth is TRUE otr FALSE
;to interpolate the spaces
(define (hist-xfer drawFrom drawTo drawApply smooth equalize)
 (let*
   ((varNumBytes 256)
   (varSrcCurve     (cons-array varNumBytes 'double))
   (varSrcCurveN     (cons-array varNumBytes 'double))
   (varTgtCurve     (cons-array varNumBytes 'double))
   (varAdjCurve     (cons-array varNumBytes 'byte))
   )

 ;get curves
 (gimp-progress-pulse)
 (if (eq? equalize TRUE)
   (set! varSrcCurve (get-hist-flat))
   (set! varSrcCurve (if (eq? smooth TRUE) (get-hist-lpf drawFrom HISTOGRAM-VALUE) (get-hist drawFrom HISTOGRAM-VALUE))))

 (gimp-progress-pulse)
 (set! varTgtCurve (if (eq? smooth TRUE) (get-hist-lpf drawTo HISTOGRAM-VALUE) (get-hist drawTo HISTOGRAM-VALUE)))

 ;normalize, convert to incremental
 (gimp-progress-pulse)
 (array-normalize varSrcCurve)
 (set! varSrcCurveN varSrcCurve)  ;copy

 (gimp-progress-pulse)
 (array-incremental varSrcCurve)
 (gimp-progress-pulse)
 (array-normalize varTgtCurve)
 (gimp-progress-pulse)
 (array-incremental varTgtCurve)

 (gimp-progress-pulse)
 (gimp-progress-set-text "Matching...")
 
 ;find the match on the source histogram using a weighted average.
 (let ((counter1 0) (counter2 0) (checkval 0) (sumval 0) (sumtot 0))
   (while (< counter1 varNumBytes)
     (set! sumval 0)
     (set! sumtot 0)
     (set! checkval (vector-ref varTgtCurve counter1))
     (while (and (< counter2 varNumBytes) (<= (vector-ref varSrcCurve counter2) checkval)); second was just lt before...
       (set! sumval (+ sumval (vector-ref varSrcCurveN counter2)))
       (set! sumtot (+ sumtot (* (+ 1 counter2) (vector-ref varSrcCurveN counter2))))
       (set! counter2 (+ counter2 1))
     )    

     (if (= sumtot 0)
       (aset varAdjCurve counter1 (if (= counter1 0) 0 (vector-ref varAdjCurve (- counter1 1))))
       (aset varAdjCurve counter1 (max 0 (min 255 (- (round (/ sumtot sumval)) 1))))
     )
       
     (gimp-progress-pulse)
     (set! counter1 (+ counter1 1))
   )
   ; backfill the low values.
   (set! counter1 0)
   (while (and (= (vector-ref varAdjCurve counter1) 0) (< counter1 varNumBytes))
     (set! counter1 (+ counter1 1))
   )
   (while (> counter1 0)
     (set! counter1 (- counter1 1))
     (aset varAdjCurve counter1 (vector-ref varAdjCurve (+ counter1 1)))
   )
 )
 
 ;apply the curve
 (gimp-curves-explicit drawApply HISTOGRAM-VALUE varNumBytes varAdjCurve)))


;debug function
(define (ma array)
 (let ((i 0) (msg ""))
   (while (< i (vector-length array))
     (set! msg (string-append msg (number->string (vector-ref array i)) " "))
     (set! i (+ i 1)))
   (gimp-message msg)))

(define (script-fu-histogram-match img inLayer inSource inEqualize inMode inSmooth inSaturation inLightness inFull)
 (let*
   ((imgSrc 0)
   (imgTgt 0)
   (imgSrcDecomp 0)
   (imgTgtDecomp 0)
   (imgInlayerDecomp 0)
   (layerSrc 0)
   (layerTgt 0)
   (buffname "histmatch")
   (sqrt-aspect 0))

   ;  it begins here
   (gimp-context-push)
   (gimp-image-undo-group-start img)
   (gimp-progress-pulse)
   ;work on duplicates
   (set! buffname (car (gimp-edit-named-copy inLayer buffname)))
   (set! imgTgt (car (gimp-edit-named-paste-as-new buffname)))
   (set! layerTgt (vector-ref (cadr (gimp-image-get-layers imgTgt)) 0))  
   (set! buffname (car (gimp-edit-named-copy inSource buffname)))
   (set! imgSrc (car (gimp-edit-named-paste-as-new buffname)))
   (set! layerSrc (vector-ref (cadr (gimp-image-get-layers imgSrc)) 0))  

   ;disable undo on all temp images
   (gimp-image-undo-disable imgTgt)
   (gimp-image-undo-disable imgSrc)

   ;check and rescale to optimal minimum size
   (when (equal? inFull FALSE)
     (when (> (* (car (gimp-image-width imgTgt)) (car (gimp-image-height imgTgt))) 65536)
       (set! sqrt-aspect (sqrt (/ (car (gimp-image-width imgTgt)) (car (gimp-image-height imgTgt)))))
       (gimp-image-scale-full imgTgt (* 256 sqrt-aspect) (/ 256 sqrt-aspect) INTERPOLATION-CUBIC))
     (when (> (* (car (gimp-image-width imgSrc)) (car (gimp-image-height imgSrc))) 65536)
       (set! sqrt-aspect (sqrt (/ (car (gimp-image-width imgSrc)) (car (gimp-image-height imgSrc)))))
       (gimp-image-scale-full imgSrc (* 256 sqrt-aspect) (/ 256 sqrt-aspect) INTERPOLATION-CUBIC)))

   (gimp-progress-pulse)

   ; preprocesing
   (if (not (and (= inSaturation 0) (= inLightness 0)))
     (gimp-hue-saturation layerSrc ALL-HUES 0 inLightness inSaturation))

   (gimp-progress-pulse)
   ;The main part
   (cond
     ((= inMode 0) ;value
       (hist-xfer layerSrc layerTgt inLayer inSmooth inEqualize))
     
     ((= inMode 1) ; ;RGB
       (set! imgSrcDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgSrc layerSrc "RGB" TRUE)))
       (set! imgTgtDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgTgt layerTgt "RGB" TRUE)))
       (set! imgInlayerDecomp (car (plug-in-decompose RUN-NONINTERACTIVE img inLayer "RGB" TRUE)))
       (gimp-image-undo-disable imgSrcDecomp)
       (gimp-image-undo-disable imgTgtDecomp)
       (gimp-image-undo-disable imgInlayerDecomp)
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 1) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 2) inSmooth inEqualize)      
       (plug-in-recompose RUN-NONINTERACTIVE imgInlayerDecomp (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0))
       (gimp-image-delete imgSrcDecomp)
       (gimp-image-delete imgTgtDecomp)
       (gimp-image-delete imgInlayerDecomp))

     ((= inMode 2) ; HSV
       (set! imgSrcDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgSrc layerSrc "HSV" TRUE)))
       (set! imgTgtDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgTgt layerTgt "HSV" TRUE)))
       (set! imgInlayerDecomp (car (plug-in-decompose RUN-NONINTERACTIVE img inLayer "HSV" TRUE)))
       (gimp-image-undo-disable imgSrcDecomp)
       (gimp-image-undo-disable imgTgtDecomp)
       (gimp-image-undo-disable imgInlayerDecomp)
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 1) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 2) inSmooth inEqualize)      
       (plug-in-recompose RUN-NONINTERACTIVE imgInlayerDecomp (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0))
       (gimp-image-delete imgSrcDecomp)
       (gimp-image-delete imgTgtDecomp)
       (gimp-image-delete imgInlayerDecomp))

     ((= inMode 3) ; HS
       (set! imgSrcDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgSrc layerSrc "HSV" TRUE)))
       (set! imgTgtDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgTgt layerTgt "HSV" TRUE)))
       (set! imgInlayerDecomp (car (plug-in-decompose RUN-NONINTERACTIVE img inLayer "HSV" TRUE)))
       (gimp-image-undo-disable imgSrcDecomp)
       (gimp-image-undo-disable imgTgtDecomp)
       (gimp-image-undo-disable imgInlayerDecomp)
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 1) inSmooth inEqualize)      
       (plug-in-recompose RUN-NONINTERACTIVE imgInlayerDecomp (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0))
       (gimp-image-delete imgSrcDecomp)
       (gimp-image-delete imgTgtDecomp)
       (gimp-image-delete imgInlayerDecomp))

     ((= inMode 4) ; LAB
       (set! imgSrcDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgSrc layerSrc "LAB" TRUE)))
       (set! imgTgtDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgTgt layerTgt "LAB" TRUE)))
       (set! imgInlayerDecomp (car (plug-in-decompose RUN-NONINTERACTIVE img inLayer "LAB" TRUE)))
       (gimp-image-undo-disable imgSrcDecomp)
       (gimp-image-undo-disable imgTgtDecomp)
       (gimp-image-undo-disable imgInlayerDecomp)
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 1) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 2) inSmooth inEqualize)      
       (plug-in-recompose RUN-NONINTERACTIVE imgInlayerDecomp (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0))
       (gimp-image-delete imgSrcDecomp)
       (gimp-image-delete imgTgtDecomp)
       (gimp-image-delete imgInlayerDecomp))

     ((= inMode 5) ; A & B
       (set! imgSrcDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgSrc layerSrc "LAB" TRUE)))
       (set! imgTgtDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgTgt layerTgt "LAB" TRUE)))
       (set! imgInlayerDecomp (car (plug-in-decompose RUN-NONINTERACTIVE img inLayer "LAB" TRUE)))
       (gimp-image-undo-disable imgSrcDecomp)
       (gimp-image-undo-disable imgTgtDecomp)
       (gimp-image-undo-disable imgInlayerDecomp)
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 1) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 2) inSmooth inEqualize)      
       (plug-in-recompose RUN-NONINTERACTIVE imgInlayerDecomp (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0))
       (gimp-image-delete imgSrcDecomp)
       (gimp-image-delete imgTgtDecomp)
       (gimp-image-delete imgInlayerDecomp))

     ((= inMode 6) ; YCbCr_ITU_R470
       (set! imgSrcDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgSrc layerSrc "YCbCr_ITU_R470" TRUE)))
       (set! imgTgtDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgTgt layerTgt "YCbCr_ITU_R470" TRUE)))
       (set! imgInlayerDecomp (car (plug-in-decompose RUN-NONINTERACTIVE img inLayer "YCbCr_ITU_R470" TRUE)))
       (gimp-image-undo-disable imgSrcDecomp)
       (gimp-image-undo-disable imgTgtDecomp)
       (gimp-image-undo-disable imgInlayerDecomp)
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 0)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 1) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 2) inSmooth inEqualize)      
       (plug-in-recompose RUN-NONINTERACTIVE imgInlayerDecomp (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0))
       (gimp-image-delete imgSrcDecomp)
       (gimp-image-delete imgTgtDecomp)
       (gimp-image-delete imgInlayerDecomp))

     ((= inMode 7) ; YCbCr_ITU_R470 Keep Y
       (set! imgSrcDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgSrc layerSrc "YCbCr_ITU_R470" TRUE)))
       (set! imgTgtDecomp (car (plug-in-decompose RUN-NONINTERACTIVE imgTgt layerTgt "YCbCr_ITU_R470" TRUE)))
       (set! imgInlayerDecomp (car (plug-in-decompose RUN-NONINTERACTIVE img inLayer "YCbCr_ITU_R470" TRUE)))
       (gimp-image-undo-disable imgSrcDecomp)
       (gimp-image-undo-disable imgTgtDecomp)
       (gimp-image-undo-disable imgInlayerDecomp)
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 1)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 1) inSmooth inEqualize)      
       (hist-xfer (vector-ref (cadr (gimp-image-get-layers imgSrcDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgTgtDecomp)) 2)
                  (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 2) inSmooth inEqualize)      
       (plug-in-recompose RUN-NONINTERACTIVE imgInlayerDecomp (vector-ref (cadr (gimp-image-get-layers imgInlayerDecomp)) 0))
       (gimp-image-delete imgSrcDecomp)
       (gimp-image-delete imgTgtDecomp)
       (gimp-image-delete imgInlayerDecomp))
    )

 ;cleanup duplicate images
 (gimp-image-delete imgSrc)
 (gimp-image-delete imgTgt)

 ;done
 (gimp-progress-end)
 (gimp-image-undo-group-end img)
 (gimp-displays-flush)
 (gimp-context-pop)))

(script-fu-register "script-fu-histogram-match"
                   _"_Match Histogram..."
                   _"Match the histogram of another image"
                   "Rob Antonishen"
                   "Rob Antonishen"
                   "April 2009"
                   "RGB*"
                   SF-IMAGE      "image"      0
                   SF-DRAWABLE   "drawable"   0
                   SF-DRAWABLE   "Use Histogram From (Source)"   0
                   SF-TOGGLE     "Equalize Instead of Matching" FALSE                    
                   SF-OPTION     "Channels to Use" (list "Value" "RGB"
                                                             "HSV" "HSV - Preserve Value"
                                                             "LAB" "LAB - Preserve Luma"
                                                             "YCbCr" "YCbCr - Preserve Luma")
                   SF-TOGGLE     "Smooth Histograms" TRUE
                   SF-ADJUSTMENT "Source Saturation Adjust"  (list 0 -100 100 1 10 0 SF-SLIDER)
                   SF-ADJUSTMENT "Source Lightness Adjust"    (list 0 -100 100 1 10 0 SF-SLIDER)
                   SF-TOGGLE     "Sample Full Size (Warning! Slow on Large Images)" FALSE
)

(script-fu-menu-register "script-fu-histogram-match"
                        "<Image>/Colors/Map")
                               .....
Samj PortableGimp 2.10.28 - Win-10 /64.
Reply


Forum Jump: