Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 10th July 2008, 00:27   #1  |  Link
mikeytown2
Resize Abuser
 
mikeytown2's Avatar
 
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
Clone of Gimp's Color Balance?

Does AviSynth have anything like this?


Screenshot from Gimp 2.4.6
mikeytown2 is offline   Reply With Quote
Old 10th July 2008, 00:53   #2  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,405
How about some combination of RGBAdjust with AvsP's sliders?
Gavino is offline   Reply With Quote
Old 10th July 2008, 01:33   #3  |  Link
mikeytown2
Resize Abuser
 
mikeytown2's Avatar
 
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
By it's self RGBAdjust can't do it.

At a minimum it would need 9 adjustments: shadows, midtones and highlights; all use 3 sliders. ChannelMixer is not the answer, gimp has this as well under colors -> components -> channel mixer. Color Balance is quite useful, I think thats why its at the top of the menu in gimp.

In order to replicate this you would split up the clip into shadows midtones and highlights; then you need to have an adjuster that goes from cyan to red, magenta to green, and yellow to blue; which happens to be the inverse of each, so it looks like it's playing with the hue for each channel in the shadows, midtones and highlights range.
mikeytown2 is offline   Reply With Quote
Old 10th July 2008, 03:45   #4  |  Link
Mug Funky
interlace this!
 
Mug Funky's Avatar
 
Join Date: Jun 2003
Location: i'm in ur transfers, addin noise
Posts: 4,555
i'd love to see something similar to a "3 point colour corrector".

as in, 3 colour wheels (lift, gamma, gain) with colour directions that correspond to a vectorscope (ie red up top, slightly to the left, green down the bottom left, blue on the right and down a bit). you could accomplish in a single click-drag what would otherwise take 3 click-drags and several adjustments.

this'd be one for avs GUI

of course, then we'd need to split it up into shots and grade each one separately...

[edit]

the top half of this pic is what i had in mind:

http://images.digitalmedianet.com/20...cp_ccsmall.jpg

of course, masktools' RGB_lut can do this quite well - you just need to get it into avsp sliders in a clever way.
__________________
sucking the life out of your videos since 2004

Last edited by Mug Funky; 10th July 2008 at 03:48.
Mug Funky is offline   Reply With Quote
Old 10th July 2008, 04:25   #5  |  Link
rfmmars
Registered User
 
Join Date: Feb 2004
Posts: 743
Quote:
Originally Posted by mikeytown2 View Post
By it's self RGBAdjust can't do it.

At a minimum it would need 9 adjustments: shadows, midtones and highlights; all use 3 sliders. ChannelMixer is not the answer, gimp has this as well under colors -> components -> channel mixer. Color Balance is quite useful, I think thats why its at the top of the menu in gimp.

In order to replicate this you would split up the clip into shadows midtones and highlights; then you need to have an adjuster that goes from cyan to red, magenta to green, and yellow to blue; which happens to be the inverse of each, so it looks like it's playing with the hue for each channel in the shadows, midtones and highlights range.
RGB-eq 2.1 has up to 17 slider per funtion not three, plus spreadsheet funtions for lum and color mix, indeed it will do it.

Richard
rfmmars is offline   Reply With Quote
Old 10th July 2008, 07:51   #6  |  Link
mikeytown2
Resize Abuser
 
mikeytown2's Avatar
 
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
Code:
Function BadColorBalance(clip c, float "R", float "G", float "B")
{
	R = Default(R,0.0)
	G = Default(G,0.0)
	B = Default(B,0.0)
	
	red = BlankClip(c,color=$FF0000)
	green = BlankClip(c,color=$00FF00)
	blue = BlankClip(c,color=$0000FF)
	Black = BlankClip(c,color=$000000)
	
	R1 = Overlay(Black,red,mask=c.ShowRed()).ConvertToYUY2().Tweak(hue=R)
	G1 = Overlay(Black,green,mask=c.ShowGreen()).ConvertToYUY2().Tweak(hue=G)
	B1 = Overlay(Black,blue,mask=c.ShowBlue()).ConvertToYUY2().Tweak(hue=B)

	Overlay(c,R1,opacity=0.6)
	Overlay(last,G1,opacity=0.35)
	Overlay(last,B1,opacity=0.3)
	Overlay(last,c,mode="luma").ConvertToYUY2().Tweak(0,2).ConvertToRGB()

}

BadColorBalance([<"Cyan-Red", -180.0, 180.0, 0.0>],[<"Magenta-Green", -180.0, 180.0, 0.0>],[<"Yellow-Blue", -180.0, 180.0, 0.0>])
Here's a 3 slider for avsp, look at the name; this is more of a yes it's possible then usable function.

I'll be looking into RGB_lut. EDIT did u mean mt_lut ?

Is there a link for RGB-eq?

Last edited by mikeytown2; 10th July 2008 at 08:47.
mikeytown2 is offline   Reply With Quote
Old 10th July 2008, 08:16   #7  |  Link
tin3tin
Registered User
 
tin3tin's Avatar
 
Join Date: Mar 2005
Posts: 365

Gradation for Vdub.

It can also work in YUV colorspace(and many others).
__________________
DVD slideshow GUI(Freeware).
tin3tin is offline   Reply With Quote
Old 10th July 2008, 21:52   #8  |  Link
mikeytown2
Resize Abuser
 
mikeytown2's Avatar
 
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
Take 2

Code:
BadColorBalance([<"LOW Cyan-Red", -45.0, 45.0, 0.0>],[<"LOW Magenta-Green", -45.0, 45.0, 0.0>],[<"LOW Yellow-Blue", -45.0, 45.0, 0.0>], \
[<"MID Cyan-Red", -45.0, 45.0, 0.0>],[<"MID Magenta-Green", -45.0, 45.0, 0.0>],[<"MID Yellow-Blue", -45.0, 45.0, 0.0>], \
[<"HI Cyan-Red", -45.0, 45.0, 0.0>],[<"HI Magenta-Green", -45.0, 45.0, 0.0>],[<"HI Yellow-Blue", -45.0, 45.0, 0.0>])

Function BadColorBalance(clip c, float "RL", float "GL", float "BL", float "RM", float "GM", float "BM", float "RH", float "GH", float "BH")
{
	RL = Default(RL,0.0)
	GL = Default(GL,0.0)
	BL = Default(BL,0.0)
	
	RM = Default(RM,0.0)
	GM = Default(GM,0.0)
	BM = Default(BM,0.0)
	
	RH = Default(RH,0.0)
	GH = Default(GH,0.0)
	BH = Default(BH,0.0)
	
	c=c.ConvertToRGB32()
	
	red = BlankClip(c,color=$FF0000)
	green = BlankClip(c,color=$00FF00)
	blue = BlankClip(c,color=$0000FF)
	Black = BlankClip(c,color=$000000)
	White = BlankClip(c,color=$FFFFFF)
	
	Low = 85
	Mid = 170
	
	RLow = Overlay(Black,red.ConvertToYUY2().Tweak(hue=RL),mask=c.ShowRed().Levels(0,1,Low,0,Low)).ResetMask()
	GLow = Overlay(Black,green.ConvertToYUY2().Tweak(hue=GL),mask=c.ShowGreen().Levels(0,1,Low,0,Low)).ResetMask()
	BLow = Overlay(Black,blue.ConvertToYUY2().Tweak(hue=BL),mask=c.ShowBlue().Levels(0,1,Low,0,Low)).ResetMask()

	RMed = Overlay(Black,red,mask=c.ShowRed().Levels(Low,1,Mid,Low,Mid)).ResetMask().ColorKeyMask($550000,1)
	RMed = Layer(White,RMed).ConvertToYUY2().Tweak(hue=RM).ConvertToRGB32().ColorKeyMask($CCCCCC,100)
	GMed = Overlay(Black,green,mask=c.ShowGreen().Levels(Low,1,Mid,Low,Mid)).ResetMask().ColorKeyMask($005600,1)
	GMed = Layer(White,GMed).ConvertToYUY2().Tweak(hue=GM).ConvertToRGB32().ColorKeyMask($CCCCCC,100)
	BMed = Overlay(Black,blue,mask=c.ShowBlue().Levels(Low,1,Mid,Low,Mid)).ResetMask().ColorKeyMask($000054,1)
	BMed = Layer(White,BMed).ConvertToYUY2().Tweak(hue=BM).ConvertToRGB32().ColorKeyMask($CCCCCC,100)

	RHi = Overlay(Black,red,mask=c.ShowRed().Levels(Mid,1,255,Mid,255)).ResetMask().ColorKeyMask($A80000,1)
	RHi = Layer(black,RHi).ConvertToYUY2().Tweak(hue=RH).ConvertToRGB32().ColorKeyMask($333333,100)
	GHi = Overlay(Black,green,mask=c.ShowGreen().Levels(Mid,1,255,Mid,255)).ResetMask().ColorKeyMask($00AB00,1)
	GHi = Layer(black,GHi).ConvertToYUY2().Tweak(hue=GH).ConvertToRGB32().ColorKeyMask($333333,100)
	BHi = Overlay(Black,blue,mask=c.ShowBlue().Levels(Mid,1,255,Mid,255)).ResetMask().ColorKeyMask($0000A9,1)
	BHi = Layer(black,BHi).ConvertToYUY2().Tweak(hue=BH).ConvertToRGB32().ColorKeyMask($333333,100)
	
	R2 = Layer(RLow,RMed).Layer(RHi)
	G2 = Layer(GLow,GMed).Layer(GHi)
	B2 = Layer(BLow,BMed).Layer(BHi)
	
	Layer(R2,G2,level=128).Layer(B2,level=85).ConvertToYUY2().Tweak(0,3)
	Overlay(last,c,mode="chroma",opacity=0.25)
	Overlay(last,c,mode="luma",opacity=1).ConvertToRGB32()
}
It's not perfect, but it kinda gets the job done for now. Not sure what job it is, but it does it! I might go take a peek at GIMP's CVS and go from there. For the AvsP sliders I caped them at 45, but it can go to 180.

Last edited by mikeytown2; 10th July 2008 at 22:05.
mikeytown2 is offline   Reply With Quote
Old 10th July 2008, 22:16   #9  |  Link
sidewinder711
near the waterfront
 
sidewinder711's Avatar
 
Join Date: Feb 2008
Posts: 38
@mickeytown2

Here is the link for RGBeq. Keep up your good work... looks promising!
sidewinder711 is offline   Reply With Quote
Old 20th August 2008, 23:19   #10  |  Link
mikeytown2
Resize Abuser
 
mikeytown2's Avatar
 
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
Finally got around to downloading Gimp's source. Looked around at online header files. Found some interesting discussions. Even found different code online of the function. All of this to say I got no idea where to go from here. I've never gotten my hands dirty with coding color functions before, so any help would be appreciated!
mikeytown2 is offline   Reply With Quote
Old 21st August 2008, 00:49   #11  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,405
Where to go maybe depends a bit on what is your ultimate goal. Is it to produce an Avisynth plugin, or to emulate the functionality in the script language?

One thing that isn't clear to me is what the parameters in the Gimp's dialog actually mean in terms of raw RGB values. The documentation doesn't really make this clear. Perhaps rooting around in the code you could shed some light on this, and come up with an outline specification. (Or maybe you've already reached that point, at least in your head.)
Gavino is offline   Reply With Quote
Old 21st August 2008, 18:26   #12  |  Link
mikeytown2
Resize Abuser
 
mikeytown2's Avatar
 
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
Ultimate goal is a plugin. There are a bunch of loops and that would be a pain to script; it also appears to go pixel by pixel. Here is the code out of 2.4.6. It doesn't have the GUI code like the online one did.
Code:
/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "config.h"

#include <glib-object.h>

#include "libgimpcolor/gimpcolor.h"
#include "libgimpmath/gimpmath.h"

#include "base-types.h"

#include "color-balance.h"
#include "pixel-region.h"


/*  local function prototypes  */

static void   color_balance_transfer_init (void);


/*  private variables  */

static gboolean transfer_initialized = FALSE;

/*  for lightening  */
static gdouble  highlights_add[256] = { 0 };
static gdouble  midtones_add[256]   = { 0 };
static gdouble  shadows_add[256]    = { 0 };

/*  for darkening  */
static gdouble  highlights_sub[256] = { 0 };
static gdouble  midtones_sub[256]   = { 0 };
static gdouble  shadows_sub[256]    = { 0 };


/*  public functions  */

void
color_balance_init (ColorBalance *cb)
{
  GimpTransferMode range;

  g_return_if_fail (cb != NULL);

  for (range = GIMP_SHADOWS; range <= GIMP_HIGHLIGHTS; range++)
    color_balance_range_reset (cb, range);

  cb->preserve_luminosity = TRUE;
}

void
color_balance_range_reset (ColorBalance     *cb,
                           GimpTransferMode  range)
{
  g_return_if_fail (cb != NULL);

  cb->cyan_red[range]      = 0.0;
  cb->magenta_green[range] = 0.0;
  cb->yellow_blue[range]   = 0.0;
}

void
color_balance_create_lookup_tables (ColorBalance *cb)
{
  gdouble *cyan_red_transfer[3];
  gdouble *magenta_green_transfer[3];
  gdouble *yellow_blue_transfer[3];
  gint     i;
  gint32   r_n, g_n, b_n;

  g_return_if_fail (cb != NULL);

  if (! transfer_initialized)
    {
      color_balance_transfer_init ();
      transfer_initialized = TRUE;
    }

  /*  Set the transfer arrays  (for speed)  */
  cyan_red_transfer[GIMP_SHADOWS] =
    (cb->cyan_red[GIMP_SHADOWS] > 0) ? shadows_add : shadows_sub;
  cyan_red_transfer[GIMP_MIDTONES] =
    (cb->cyan_red[GIMP_MIDTONES] > 0) ? midtones_add : midtones_sub;
  cyan_red_transfer[GIMP_HIGHLIGHTS] =
    (cb->cyan_red[GIMP_HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;

  magenta_green_transfer[GIMP_SHADOWS] =
    (cb->magenta_green[GIMP_SHADOWS] > 0) ? shadows_add : shadows_sub;
  magenta_green_transfer[GIMP_MIDTONES] =
    (cb->magenta_green[GIMP_MIDTONES] > 0) ? midtones_add : midtones_sub;
  magenta_green_transfer[GIMP_HIGHLIGHTS] =
    (cb->magenta_green[GIMP_HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;
  yellow_blue_transfer[GIMP_SHADOWS] =
    (cb->yellow_blue[GIMP_SHADOWS] > 0) ? shadows_add : shadows_sub;
  yellow_blue_transfer[GIMP_MIDTONES] =
    (cb->yellow_blue[GIMP_MIDTONES] > 0) ? midtones_add : midtones_sub;
  yellow_blue_transfer[GIMP_HIGHLIGHTS] =
    (cb->yellow_blue[GIMP_HIGHLIGHTS] > 0) ? highlights_add : highlights_sub;

  for (i = 0; i < 256; i++)
    {
      r_n = i;
      g_n = i;
      b_n = i;

      r_n += cb->cyan_red[GIMP_SHADOWS] * cyan_red_transfer[GIMP_SHADOWS][r_n];
      r_n = CLAMP0255 (r_n);
      r_n += cb->cyan_red[GIMP_MIDTONES] * cyan_red_transfer[GIMP_MIDTONES][r_n];
      r_n = CLAMP0255 (r_n);
      r_n += cb->cyan_red[GIMP_HIGHLIGHTS] * cyan_red_transfer[GIMP_HIGHLIGHTS][r_n];
      r_n = CLAMP0255 (r_n);

      g_n += cb->magenta_green[GIMP_SHADOWS] * magenta_green_transfer[GIMP_SHADOWS][g_n];
      g_n = CLAMP0255 (g_n);
      g_n += cb->magenta_green[GIMP_MIDTONES] * magenta_green_transfer[GIMP_MIDTONES][g_n];
      g_n = CLAMP0255 (g_n);
      g_n += cb->magenta_green[GIMP_HIGHLIGHTS] * magenta_green_transfer[GIMP_HIGHLIGHTS][g_n];
      g_n = CLAMP0255 (g_n);

      b_n += cb->yellow_blue[GIMP_SHADOWS] * yellow_blue_transfer[GIMP_SHADOWS][b_n];
      b_n = CLAMP0255 (b_n);
      b_n += cb->yellow_blue[GIMP_MIDTONES] * yellow_blue_transfer[GIMP_MIDTONES][b_n];
      b_n = CLAMP0255 (b_n);
      b_n += cb->yellow_blue[GIMP_HIGHLIGHTS] * yellow_blue_transfer[GIMP_HIGHLIGHTS][b_n];
      b_n = CLAMP0255 (b_n);

      cb->r_lookup[i] = r_n;
      cb->g_lookup[i] = g_n;
      cb->b_lookup[i] = b_n;
    }
}

void
color_balance (ColorBalance *cb,
               PixelRegion  *srcPR,
               PixelRegion  *destPR)
{
  const guchar *src, *s;
  guchar       *dest, *d;
  gboolean      alpha;
  gint          r, g, b;
  gint          r_n, g_n, b_n;
  gint          w, h;

  h     = srcPR->h;
  src   = srcPR->data;
  dest  = destPR->data;
  alpha = (srcPR->bytes == 4) ? TRUE : FALSE;

  while (h--)
    {
      w = srcPR->w;
      s = src;
      d = dest;

      while (w--)
        {
          r = s[RED_PIX];
          g = s[GREEN_PIX];
          b = s[BLUE_PIX];

          r_n = cb->r_lookup[r];
          g_n = cb->g_lookup[g];
          b_n = cb->b_lookup[b];

          if (cb->preserve_luminosity)
            {
              gimp_rgb_to_hsl_int (&r_n, &g_n, &b_n);
              b_n = gimp_rgb_to_l_int (r, g, b);
              gimp_hsl_to_rgb_int (&r_n, &g_n, &b_n);
            }

          d[RED_PIX]   = r_n;
          d[GREEN_PIX] = g_n;
           d[BLUE_PIX]  = b_n;

          if (alpha)
            d[ALPHA_PIX] = s[ALPHA_PIX];

          s += srcPR->bytes;
          d += destPR->bytes;
        }

      src  += srcPR->rowstride;
      dest += destPR->rowstride;
    }
}


/*  private functions  */

static void
color_balance_transfer_init (void)
{
  gint i;

  for (i = 0; i < 256; i++)
    {
      gdouble low = (1.075 - 1 / ((gdouble) i / 16.0 + 1));
      gdouble mid = 0.667 * (1 - SQR (((gdouble) i - 127.0) / 127.0));

      shadows_add[i]          = low;
      shadows_sub[255 - i]    = low;

      midtones_add[i]         = mid;
      midtones_sub[i]         = mid;

      highlights_add[255 - i] = low;
      highlights_sub[i]       = low;
    }
}
Header File
Code:
/* GIMP - The GNU Image Manipulation Program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef __COLOR_BALANCE_H__
#define __COLOR_BALANCE_H__


struct _ColorBalance
{
  gboolean preserve_luminosity;

  gdouble  cyan_red[3];
  gdouble  magenta_green[3];
  gdouble  yellow_blue[3];

  guchar   r_lookup[256];
  guchar   g_lookup[256];
  guchar   b_lookup[256];
};


void   color_balance_init                 (ColorBalance     *cb);
void   color_balance_range_reset          (ColorBalance     *cb,
                                           GimpTransferMode  range);
void   color_balance_create_lookup_tables (ColorBalance     *cb);
void   color_balance                      (ColorBalance     *cb,
                                           PixelRegion      *srcPR,
                                           PixelRegion      *destPR);


#endif  /*  __COLOR_BALANCE_H__  */

The flow of this is color_balance_create_lookup_tables() pre-calculates all 2304 values (3*3*256; SMH*RGB*levels), then for each pixel color_balance() looks up that adjusted RGB value. I'll worry about preserve_luminosity later. What it's pre-calculating is a mystery to me right now, other then it's multiplying the slider value (-100 to 100) by the value out of color_balance_transfer_init() low,mid for that i value.

So this is the black box of the code
Code:
      gdouble low = (1.075 - 1 / ((gdouble) i / 16.0 + 1));
      gdouble mid = 0.667 * (1 - SQR (((gdouble) i - 127.0) / 127.0));

EDIT1:
Going to look at cinepaint for a 16bit version of this
Found it online here
http://www.sfr-fresh.com/unix/misc/c...olor_balance.c

EDIT2:
Multi threading this shouldn't be that hard (last time I wrote MT code was 3 years ago...), have it split off in these 2 loops:
color_balance() --> while (h--)
color_balance_transfer_init --> for (i = 0; i < 256; i++)


Game plan is to get Gimp code working, then multi thread it, then get 16bit working.

Last edited by mikeytown2; 22nd August 2008 at 00:00.
mikeytown2 is offline   Reply With Quote
Old 22nd August 2008, 00:49   #13  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,405
Quote:
Originally Posted by mikeytown2 View Post
Multi threading this shouldn't be that hard (last time I wrote MT code was 3 years ago...), have it split off in these 2 loops:
color_balance() --> while (h--)
color_balance_transfer_init --> for (i = 0; i < 256; i++)
In Avisynth plugin terms, color_balance() more or less corresponds to GetFrame(), whereas the init stuff (setting up lookup tables, etc) would be done in your constructor, so I don't think there is scope for multi-threading these.

A quick look at the code (although I haven't absorbed the details yet) suggests it should not be overly slow anyway.
Gavino is offline   Reply With Quote
Old 22nd August 2008, 04:08   #14  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,173
Here is a sample script for doing a 3x3 matrix correction of a RGB clip.
Code:
... # RGB clip
# Red mixing ratios
Rr=1.0
Rg=0.0
Rb=0.0
# Green mixing ratios
Gr=0.0
Gg=1.0
Gb=0.0
# Blue mixing ratios
Br=0.0
Bg=0.0
Bb=1.0

Ri=ShowRed("YV12")
Gi=ShowGreen("YV12")
Bi=ShowBlue("YV12")
Z=BlankClip(Ri)

(Rg+Rb !=  0) ? MergeLuma(Gi, Bi, Ratio(Rg, Rb)) : Z
MergeLuma(Ri, Ratio(Rg+Rb, Rr))
(Rr+Rg+Rb !=  1) ? Tweak(Cont=Rr+Rg+Rb, coring=False) : Last
Ro=Last

(Gr+Gb !=  0) ? MergeLuma(Ri, Bi, Ratio(Gr, Gb)) : Z
MergeLuma(Gi, Ratio(Gr+Gb, Gg))
(Gr+Gg+Gb !=  1) ? Tweak(Cont=Gr+Gg+Gb, coring=False) : Last
Go=Last

(Br+Bg !=  0) ? MergeLuma(Ri, Gi, Ratio(Br, Bg)) : Z
MergeLuma(Bi, Ratio(Br+Bg, Bb))
(Rr+Rg+Rb !=  1) ? Tweak(Cont=Br+Bg+Bb, coring=False) : Last
Bo=Last

MergeRGB(Ro, Go, Bo)

Function Ratio(Float A, Float B) {
  Return (A+B == 0) ? 0.5 : B/(A+B)
}
It can easily be adapted to adjust any of the component channels in any way required. e.g. apply 1.2 gamma and 35 offset to the red component of the green mix.
Code:
...
Rg=Levels(0, 1.2, 220, 35, 255, Coring=False)
(Gr+Gb !=  0) ? MergeLuma(Rg, Bi, Ratio(Gr, Gb)) : Z
...
IanB is offline   Reply With Quote
Old 22nd August 2008, 11:42   #15  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,405
@mikeytown2: another observation on your possible ways forward:
Quote:
Originally Posted by mikeytown2 View Post
Ultimate goal is a plugin. There are a bunch of loops and that would be a pain to script; it also appears to go pixel by pixel.
The alternative to a plugin would not be to directly rewrite the code as a script - that would be both painful and misguided.

Instead, the idea would be to figure out what the code was doing at the image level (eg adding x% to the red level over a certain threshold, or whatever), and replicate that in terms of available Avisynth filters. That's what I meant by an outline specification.

IanB's script has shown that just about anything can be achieved - but first you have to know what you want the output to be in terms of the input.
Gavino is offline   Reply With Quote
Old 26th August 2008, 17:05   #16  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,405
@mikeytown2

I've found time to put together a prototype plugin based on the Gimp source you posted. It's basically a straight transcription, amended to fit the Avisynth plugin interface.

I'm quite content for you to take this forward in any way you like. If you need any help, feel free to ask.

The interface is currently as follows:
Code:
ColorBalance(clip,
             float "rs", float "gs", float "bs", # shadows
             float "rm", float "gm", float "bm", # midtones
             float "rh", float "gh", float "bh", # highlights
             bool "keep_luma")
The float parameters correspond to the Gimp sliders for (red, green, blue)x(shadows, midtones, highlights), nominal range -100.0 to +100.0 (though this is not currently checked), defaults 0.0;

keep_luma corresponds to Gimp's 'preserve luminosity' - this functionality is not yet implemented, so the parameter should be set to false (the default).

I am calling it a prototype, but the basic color balancing is fully functional - only keep_luma is not implemented.

Here it is (source + working dll):
Attached Files
File Type: zip ColorBalance.zip (30.8 KB, 258 views)
Gavino is offline   Reply With Quote
Old 27th August 2008, 06:55   #17  |  Link
mikeytown2
Resize Abuser
 
mikeytown2's Avatar
 
Join Date: Apr 2005
Location: Seattle, WA
Posts: 623
@Gavino
You beat me to it! Got simple sample compiled in MS VC++ 2005 and was about to start porting the code.

I'm still waiting for your zip file to be approved, would you mind putting it up on a one-click file hosting site?
mikeytown2 is offline   Reply With Quote
Old 27th August 2008, 08:58   #18  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,405
OK - here's the link: http://rapidshare.com/files/14045831...lance.zip.html
Gavino is offline   Reply With Quote
Old 27th August 2008, 09:26   #19  |  Link
IanB
Avisynth Developer
 
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,173
@Gavino,

Hint: Do not put tests inside inner loops, put the test outside the loop and clone the code with a very simple inner loop.
Code:
...
        for (w = 0; w < src_width; w+=nBytes) {
          if (nBytes == 4) // RGB32
            a = *(srcp + w+3);
          r = *(srcp + w+2);

...
          if (nBytes == 4) // RGB32
            *(dstp + w+3) = a;
          *(dstp + w + 2) = r_n;
...
        }
...
Code:
      if (nBytes == 4) { // RGB32
...
        for (w = 0; w < src_width; w+=4) {
          a = *(srcp + w+3);
          r = *(srcp + w+2);
...
          *(dstp + w+3) = a;
          *(dstp + w+2) = r_n;
...
        }
...
      } else {
...
        for (w = 0; w < src_width; w+=nBytes) {
          r = *(srcp + w+2);
...
          *(dstp + w + 2) = r_n;
...
        }
...
      }
...

Last edited by IanB; 27th August 2008 at 09:31.
IanB is offline   Reply With Quote
Old 27th August 2008, 10:00   #20  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,405
Quote:
Originally Posted by IanB View Post
Do not put tests inside inner loops, put the test outside the loop and clone the code with a very simple inner loop.
Yes, I guess you're right from a performance (or even a 'control flow elegance') point of view, though in general I prefer not to repeat code as it makes it harder to change.

Here your change is worth doing, and there are clearly other optimisations possible (eg eliminate the repeated addition of w in the pointer arithmetic).

Last edited by Gavino; 27th August 2008 at 10:02.
Gavino is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 11:44.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2020, vBulletin Solutions Inc.