Custom processing for JPEG (Tone curve, CA ...) - page 5 - Feature Requests - CHDK Forum supplierdeeply

Custom processing for JPEG (Tone curve, CA ...)

  • 101 Replies
  • 70112 Views
Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #40 on: 07 / May / 2008, 22:20:17 »
Advertisements
Cool. Takes about half less time to apply curves. (Tested with one curve, but still...) :] Will be included in next build.

It take the same time regarless of the number of color provided in the curve.

Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #41 on: 11 / May / 2008, 15:39:29 »
Hi,

This is very neat stuff, very powerful.  I just realized (it may be just me that is slow)  that the curves can be used to change EV values when developing. 

I am not sure that this can be done just by multiplying or dividing the data by constants.  I did some tests and although it works there seems to be a color shift for large multipliers/divisors.  But for small increase in EV it works nicely.  Say multiply by 1.5 or .75 in the code below.

I have hope that it will be possible to figure out curves that develop at various +/- EV and preserve color.

Hopefully these curves could be created on the fly or loaded automatically.  That way someone would not have to master the details of using curves to simply brighten up a photo.

Jon

Here is some code.  (EDIT:Code improved 5/12/2008)
Code: [Select]

#define CURVE_SIZE 1024
unsigned short curve[CURVE_SIZE];

void raw_mul(double mult, double offset) {
short i,j;
unsigned short pixVal0, pixVal1, pixVal2;
unsigned char *src;

for(i=0;i<CURVE_SIZE;i++) {
j = (short) (i * mult + offset);
if(j > 1023) j = 1023;
if(j < 0) j = 0;
curve[i] = j;
}

// Set pointer to picture raw data in memory
src = (unsigned char *) hook_raw_image_addr();

// Loop through picture rows
for (i=CAM_RAW_ROWS; i;i-=2){
// Loop through picture columns
for (j=CAM_RAW_ROWPIX; j; j-=8, src+=10){
pixVal0=curve[((0x3fc&(((unsigned short)(*(src+1)))<<2)) | (*(src+0) >> 6))];
            *(src+1) = (unsigned char) ((pixVal0>>2)); // 0
pixVal1=curve[((0x3f0&(((unsigned short)(*(src+0)))<<4)) | (*(src+3) >> 4))];
            *(src+0) = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); //0, 1
pixVal2=curve[((0x3c0&(((unsigned short)(*(src+3)))<<6)) | (*(src+2) >> 2))];
            *(src+3) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); //1,2
pixVal0=curve[((0x300&(((unsigned short)(*(src+2)))<<8)) | (*(src+5)))];
            *(src+2) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); //2,3 =>(2,0)
            *(src+5) = (unsigned char) ((pixVal0)); //3 (=>0)

pixVal0=curve[((0x3fc&(((unsigned short)(*(src+4)))<<2)) | (*(src+7) >> 6))];
            *(src+4) = (unsigned char) ((pixVal0>>2)); // 4 => 0
pixVal1=curve[((0x3f0&(((unsigned short)(*(src+7)))<<4)) | (*(src+6) >> 4))];
            *(src+7) = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); // 4,5 => (0,1)
pixVal2=curve[((0x3c0&(((unsigned short)(*(src+6)))<<6)) | (*(src+9) >> 2))];
            *(src+6) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); // 5,6 => (1,2)
pixVal0=curve[((0x300&(((unsigned short)(*(src+9)))<<8)) | (*(src+8)))];
            *(src+9) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); // 6,7 =>(2,0)
            *(src+8) = (unsigned char) ((pixVal0)); //7 (=>0)
}

for (j=CAM_RAW_ROWPIX; j; j-=8, src+=10){
pixVal0=curve[((0x3fc&(((unsigned short)(*(src+1)))<<2)) | (*(src+0) >> 6))];
            *(src+1) = (unsigned char) ((pixVal0>>2)); // 0
pixVal1=curve[((0x3f0&(((unsigned short)(*(src+0)))<<4)) | (*(src+3) >> 4))];
            *(src+0) = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); //0, 1
pixVal2=curve[((0x3c0&(((unsigned short)(*(src+3)))<<6)) | (*(src+2) >> 2))];
            *(src+3) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); //1,2
pixVal0=curve[((0x300&(((unsigned short)(*(src+2)))<<8)) | (*(src+5)))];
            *(src+2) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); //2,3 =>(2,0)
            *(src+5) = (unsigned char) ((pixVal0)); //3 (=>0)

pixVal0=curve[((0x3fc&(((unsigned short)(*(src+4)))<<2)) | (*(src+7) >> 6))];
            *(src+4) = (unsigned char) ((pixVal0>>2)); // 4 => 0
pixVal1=curve[((0x3f0&(((unsigned short)(*(src+7)))<<4)) | (*(src+6) >> 4))];
            *(src+7) = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); // 4,5 => (0,1)
pixVal2=curve[((0x3c0&(((unsigned short)(*(src+6)))<<6)) | (*(src+9) >> 2))];
            *(src+6) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); // 5,6 => (1,2)
pixVal0=curve[((0x300&(((unsigned short)(*(src+9)))<<8)) | (*(src+8)))];
            *(src+9) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); // 6,7 =>(2,0)
            *(src+8) = (unsigned char) ((pixVal0)); //7 (=>0)
}
}
}

« Last Edit: 12 / May / 2008, 10:24:15 by hiker_jon »

*

Offline mkmenuts

  • **
  • 61
  • SD700 (1.01b)
Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #42 on: 15 / May / 2008, 16:05:02 »
Is there a place on the Wiki for curves? Is there a basic set in place?

Since I'm often slightly under-exposing (-2/3 EV) to avoid blow-out, I'm looking for a curve to bring out the shadows (a-la D-Lighting in Nikon DSLRs).

Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #43 on: 15 / May / 2008, 20:02:04 »
Is there a place on the Wiki for curves? Is there a basic set in place?

No not really. I'll be glad to see if somebody create it.
BTW: Curve is not even an official feature of CHDK.

Quote
Since I'm often slightly under-exposing (-2/3 EV) to avoid blow-out, I'm looking for a curve to bring out the shadows (a-la D-Lighting in Nikon DSLRs).

We may one day be able to load  Nikon curves into CHDK. There are a whole bunch out there (just -OO- photogenic curve).
Not too soon though:
1. I don't know anything about the Nikon curves
2. I believe that the Nikon curves would be working on 14/16 bits instead of the 10 bits for CHDK.
3. Some one would also have to figure out the difference and correction between a Nikon and Canon sensor response.
.... Other stuff I may have forgotten here since I am pretty much a novice in the subject.


Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #44 on: 30 / May / 2008, 11:35:21 »
Is it possible to turn off noise reduction and sharpen for JPEG? This will greatly improve the room of post processing. Actually, this is the main reason that I use raw now. The PC base noise reduction software, like noiseware, neatimage, and noise ninja, are much better than the in-camera noise reduction.

Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #45 on: 03 / June / 2008, 00:27:39 »
This is very neat stuff, very powerful.  I just realized (it may be just me that is slow)  that the curves can be used to change EV values when developing. 

I am not sure that this can be done just by multiplying or dividing the data by constants.  I did some tests and although it works there seems to be a color shift for large multipliers/divisors.  But for small increase in EV it works nicely.  Say multiply by 1.5 or .75 in the code below.

The overall implementation of the curve is FLAWED and would barely work for multipliers/divisors. That's why things seems to work at some extend for you.
The color shift is due to the non linear response of the RAW data. Since the non linear response of the sensor is not known, it will be very hard to work out something to correct it.

Quote
I have hope that it will be possible to figure out curves that develop at various +/- EV and preserve color.

Hopefully these curves could be created on the fly or loaded automatically.  That way someone would not have to master the details of using curves to simply brighten up a photo.

If the curve becomes non linear color shift may even worsen.
The correct way to do it would be to interpolate, then convert the RGB RAW into for example a HSI space, adjust I and convert back to Bayer RAW for the camera to develop. Which is a double operation and will be to CPU intensive for the camera.

Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #46 on: 03 / June / 2008, 01:42:33 »
The overall implementation of the curve is FLAWED and would barely work for multipliers/divisors. That's why things seems to work at some extend for you.
The color shift is due to the non linear response of the RAW data. Since the non linear response of the sensor is not known, it will be very hard to work out something to correct it.


Do you mean that the whole idea of using curves is flawed?  If so I think that you are too pessimistic.  For instance, one curve certainly works great: the identity curve.  Others will probably work well also, the trick is to figure out what sort of curves will work.



Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #47 on: 04 / June / 2008, 10:09:41 »
Do you mean that the whole idea of using curves is flawed?  If so I think that you are too pessimistic.  For instance, one curve certainly works great: the identity curve.  Others will probably work well also, the trick is to figure out what sort of curves will work.

The identity tone curve does nothing. The way the tone curve is implemented will yield unexpected color shift depending on the ratio of and level of each R/G/B component (i.e. on the contents of the picture)

Current implementation:
R' = LookUpRed1(R)
G' = LookUpGreen1(G)
B' = LookUpBlue1(B)

A correct implementation would be to convert the RGB in a HSV space, change V using a look up table and back to RGB assuming that RGB are linear.

An approximate implementation (yet to be tested) would be
L = Luminance(R,G,B)
R' = LookUpRed2(L,R)
G' = LookUpGreen2(L,G)
B' = LookUpBlue2(L,B)

R,G,B will be extracted from the interpolation of the Bayer pattern.
R',G',B' will be reapplied back to the Bayer pattern (not sure how yet).
L function yet to be defined - May be (2R+G1+G2+2B)/6

The computation complexity is much worst and the memory cost would be really bad 1024x1024x3x2 Bytes.
« Last Edit: 14 / July / 2008, 01:09:30 by toinech »


Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #48 on: 04 / June / 2008, 10:50:50 »
Hi,

Thanks for the reply.  The details of developing from sensor data are a mystery to me.  This is what I guessed (not based on any real knowledge) :  The red, green and blue sensors are linear, but may have different gain and offset.  I hope this gain and offset just depend on the color, but it might be that green sensors in even rows behave differently than ones in odd rows.  To get a consistent linear Rl,Gl,Bl value you calc Rl = R0 + Rg * R, etc.   Once we know what the offset and gain values of each sensor type are, we can anticipate the Canon calculation and produce curves that will work.  At least for changing ev this should be possible.

Jon

Re: Custom processing for JPEG (Tone curve, CA ...)
« Reply #49 on: 14 / June / 2008, 19:18:17 »
Hi,

I have done some testing with my camera and the curves work great for changing the ev. 

I use my routine
void raw_mul(double mult, double offset)
posted previously in this topic.  This routine multiplies the raw data by mult then adds offset.  Use it on the raw data before raw develop.
The trick is to know what the black value is for your sensor.  This is the nominal value that the sensor records when there is no light.  It is higher than 0 to accommodate noise.  I found this value out by doing the following:
Take a picture of a scene with a black object (inside of a pipe, say) and save the raw data.  Outside the camera I used dcraw -D -4 CRW_1815.CRW.  This produces a 16bit image of the raw data.  ImageJ can read such data.  Looking at the values in the pipe interior I saw that they averaged about 32 (ISO80,A720IS).  This seemed to be the same for the R,G,B sensors.  I think the black value is also the same for other ISO's, but will need to do more testing.
Now to increase or decrease the ev I set mult to what I want (say 2 for ev +1 or .5 for ev -1) and calculate offset = black - mult * black.  (i.e. this effectively subtracts black before doing the mult and adds it back after).

Using this routine enables developing with +/- ev.  Very useful in case the wimpy flash does not sufficiently illuminate your subject.  Or for "shooting right", i.e. deliberately overexposing your subject then developing the raw at minus ev to get a properly exposed and less noisy image.

Of course our cameras only have 10bit raws so the usefulness of this is limited to low changes in ev.  Probably +- 1 is the limit for high quality, but +2 has worked for me in redeveloping a picture I took in a cave where my flash could not reach.

Implementing curves that are usually applied in RGB space should also work.  You just have to remember to deal with the black offset and also to convert the curve to linear space.

Jon
« Last Edit: 14 / June / 2008, 19:20:09 by hiker_jon »

 

Related Topics