bayer2bmp
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <stdint.h>
#include <stdio.h>
#include <limits.h>
#include <unistd.h>
#include <sys/types.h> typedef enum {
DC1394_BAYER_METHOD_NEAREST=,
DC1394_BAYER_METHOD_SIMPLE,
DC1394_BAYER_METHOD_BILINEAR,
DC1394_BAYER_METHOD_HQLINEAR,
DC1394_BAYER_METHOD_DOWNSAMPLE,
DC1394_BAYER_METHOD_EDGESENSE,
DC1394_BAYER_METHOD_VNG,
DC1394_BAYER_METHOD_AHD
} dc1394bayer_method_t; typedef enum {
DC1394_COLOR_FILTER_RGGB = ,
DC1394_COLOR_FILTER_GBRG,
DC1394_COLOR_FILTER_GRBG,
DC1394_COLOR_FILTER_BGGR
} dc1394color_filter_t ;
#define DC1394_COLOR_FILTER_MIN DC1394_COLOR_FILTER_RGGB
#define DC1394_COLOR_FILTER_MAX DC1394_COLOR_FILTER_BGGR
#define DC1394_COLOR_FILTER_NUM (DC1394_COLOR_FILTER_MAX - DC1394_COLOR_FILTER_MIN + 1) /**
* Error codes returned by most libdc1394 functions.
*
* General rule: 0 is success, negative denotes a problem.
*/
typedef enum {
DC1394_SUCCESS = ,
DC1394_FAILURE = -,
DC1394_NOT_A_CAMERA = -,
DC1394_FUNCTION_NOT_SUPPORTED = -,
DC1394_CAMERA_NOT_INITIALIZED = -,
DC1394_MEMORY_ALLOCATION_FAILURE = -,
DC1394_TAGGED_REGISTER_NOT_FOUND = -,
DC1394_NO_ISO_CHANNEL = -,
DC1394_NO_BANDWIDTH = -,
DC1394_IOCTL_FAILURE = -,
DC1394_CAPTURE_IS_NOT_SET = -,
DC1394_CAPTURE_IS_RUNNING = -,
DC1394_RAW1394_FAILURE = -,
DC1394_FORMAT7_ERROR_FLAG_1 = -,
DC1394_FORMAT7_ERROR_FLAG_2 = -,
DC1394_INVALID_ARGUMENT_VALUE = -,
DC1394_REQ_VALUE_OUTSIDE_RANGE = -,
DC1394_INVALID_FEATURE = -,
DC1394_INVALID_VIDEO_FORMAT = -,
DC1394_INVALID_VIDEO_MODE = -,
DC1394_INVALID_FRAMERATE = -,
DC1394_INVALID_TRIGGER_MODE = -,
DC1394_INVALID_TRIGGER_SOURCE = -,
DC1394_INVALID_ISO_SPEED = -,
DC1394_INVALID_IIDC_VERSION = -,
DC1394_INVALID_COLOR_CODING = -,
DC1394_INVALID_COLOR_FILTER = -,
DC1394_INVALID_CAPTURE_POLICY = -,
DC1394_INVALID_ERROR_CODE = -,
DC1394_INVALID_BAYER_METHOD = -,
DC1394_INVALID_VIDEO1394_DEVICE = -,
DC1394_INVALID_OPERATION_MODE = -,
DC1394_INVALID_TRIGGER_POLARITY = -,
DC1394_INVALID_FEATURE_MODE = -,
DC1394_INVALID_LOG_TYPE = -,
DC1394_INVALID_BYTE_ORDER = -,
DC1394_INVALID_STEREO_METHOD = -,
DC1394_BASLER_NO_MORE_SFF_CHUNKS = -,
DC1394_BASLER_CORRUPTED_SFF_CHUNK = -,
DC1394_BASLER_UNKNOWN_SFF_CHUNK = -
} dc1394error_t;
#define DC1394_ERROR_MIN DC1394_BASLER_UNKNOWN_SFF_CHUNK
#define DC1394_ERROR_MAX DC1394_SUCCESS
#define DC1394_ERROR_NUM (DC1394_ERROR_MAX-DC1394_ERROR_MIN+1) typedef enum {
DC1394_FALSE= ,
DC1394_TRUE
} dc1394bool_t; #define CLIP(in, out)\
in = in < ? : in;\
in = in > ? : in;\
out=in; #define CLIP16(in, out, bits)\
in = in < ? : in;\
in = in > ((<<bits)-) ? ((<<bits)-) : in;\
out=in; void ClearBorders(uint8_t *rgb, int sx, int sy, int w)
{
int i, j;
// black edges are added with a width w:
i = * sx * w - ;
j = * sx * sy - ;
while (i >= )
{
rgb[i--] = ;
rgb[j--] = ;
} int low = sx * (w - ) * - + w * ;
i = low + sx * (sy - w * + ) * ;
while (i > low)
{
j = * w;
while (j > )
{
rgb[i--] = ;
j--;
}
i -= (sx - * w) * ;
}
} void ClearBorders_uint16(uint16_t *rgb, int sx, int sy, int w)
{
int i, j; // black edges:
i = * sx * w - ;
j = * sx * sy - ;
while (i >= )
{
rgb[i--] = ;
rgb[j--] = ;
} int low = sx * (w - ) * - + w * ;
i = low + sx * (sy - w * + ) * ;
while (i > low)
{
j = * w;
while (j > )
{
rgb[i--] = ;
j--;
}
i -= (sx - * w) * ;
} } /**************************************************************
* Color conversion functions for cameras that can *
* output raw-Bayer pattern images, such as some Basler and *
* Point Grey camera. Most of the algos presented here come *
* from http://www-ise.stanford.edu/~tingchen/ and have been *
* converted from Matlab to C and extended to all elementary *
* patterns. *
**************************************************************/
/* 8-bits versions */
/* insprired by OpenCV's Bayer decoding */ dc1394error_t dc1394_bayer_NearestNeighbor(const uint8_t *restrict bayer, uint8_t *restrict rgb, int sx, int sy, int tile)
{
const int bayerStep = sx;
const int rgbStep = * sx;
int width = sx;
int height = sy;
int blue = tile == DC1394_COLOR_FILTER_BGGR
|| tile == DC1394_COLOR_FILTER_GBRG ? - : ;
int start_with_green = tile == DC1394_COLOR_FILTER_GBRG
|| tile == DC1394_COLOR_FILTER_GRBG;
int i, imax, iinc; if ((tile > DC1394_COLOR_FILTER_MAX) || (tile < DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER; /* add black border */
imax = sx * sy * ;
for (i = sx * (sy - ) * ; i < imax; i++)
{
rgb[i] = ;
}
iinc = (sx - ) * ;
for (i = (sx - ) * ; i < imax; i += iinc)
{
rgb[i++] = ;
rgb[i++] = ;
rgb[i++] = ;
} rgb += ;
width -= ;
height -= ; for (; height--; bayer += bayerStep, rgb += rgbStep)
{
//int t0, t1;
const uint8_t *bayerEnd = bayer + width; if (start_with_green)
{
rgb[-blue] = bayer[];
rgb[] = bayer[bayerStep + ];
rgb[blue] = bayer[bayerStep];
bayer++;
rgb += ;
} if (blue > )
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
rgb[-] = bayer[];
rgb[] = bayer[];
rgb[] = bayer[bayerStep + ]; rgb[] = bayer[];
rgb[] = bayer[bayerStep + ];
rgb[] = bayer[bayerStep + ];
}
}
else
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
rgb[] = bayer[];
rgb[] = bayer[];
rgb[-] = bayer[bayerStep + ]; rgb[] = bayer[];
rgb[] = bayer[bayerStep + ];
rgb[] = bayer[bayerStep + ];
}
} if (bayer < bayerEnd)
{
rgb[-blue] = bayer[];
rgb[] = bayer[];
rgb[blue] = bayer[bayerStep + ];
bayer++;
rgb += ;
} bayer -= width;
rgb -= width * ; blue = -blue;
start_with_green = !start_with_green;
} return DC1394_SUCCESS;
} /* OpenCV's Bayer decoding */
dc1394error_t dc1394_bayer_Bilinear(const uint8_t *restrict bayer, uint8_t *restrict rgb, int sx, int sy, int tile)
{
const int bayerStep = sx;
const int rgbStep = * sx;
int width = sx;
int height = sy;
/*
the two letters of the OpenCV name are respectively
the 4th and 3rd letters from the blinky name,
and we also have to switch R and B (OpenCV is BGR) CV_BayerBG2BGR <-> DC1394_COLOR_FILTER_BGGR
CV_BayerGB2BGR <-> DC1394_COLOR_FILTER_GBRG
CV_BayerGR2BGR <-> DC1394_COLOR_FILTER_GRBG int blue = tile == CV_BayerBG2BGR || tile == CV_BayerGB2BGR ? -1 : 1;
int start_with_green = tile == CV_BayerGB2BGR || tile == CV_BayerGR2BGR;
*/
int blue = tile == DC1394_COLOR_FILTER_BGGR
|| tile == DC1394_COLOR_FILTER_GBRG ? - : ;
int start_with_green = tile == DC1394_COLOR_FILTER_GBRG
|| tile == DC1394_COLOR_FILTER_GRBG; if ((tile > DC1394_COLOR_FILTER_MAX) || (tile < DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER; ClearBorders(rgb, sx, sy, );
rgb += rgbStep + + ;
height -= ;
width -= ; for (; height--; bayer += bayerStep, rgb += rgbStep)
{
int t0, t1;
const uint8_t *bayerEnd = bayer + width; if (start_with_green)
{
/* OpenCV has a bug in the next line, which was
t0 = (bayer[0] + bayer[bayerStep * 2] + 1) >> 1; */
t0 = (bayer[] + bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[bayerStep] + bayer[bayerStep + ] + ) >> ;
rgb[-blue] = (uint8_t) t0;
rgb[] = bayer[bayerStep + ];
rgb[blue] = (uint8_t) t1;
bayer++;
rgb += ;
} if (blue > )
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
t0 = (bayer[] + bayer[] + bayer[bayerStep * ] +
bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[] + bayer[bayerStep] +
bayer[bayerStep + ] + bayer[bayerStep * + ] +
) >> ;
rgb[-] = (uint8_t) t0;
rgb[] = (uint8_t) t1;
rgb[] = bayer[bayerStep + ]; t0 = (bayer[] + bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[bayerStep + ] + bayer[bayerStep + ] +
) >> ;
rgb[] = (uint8_t) t0;
rgb[] = bayer[bayerStep + ];
rgb[] = (uint8_t) t1;
}
}
else
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
t0 = (bayer[] + bayer[] + bayer[bayerStep * ] +
bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[] + bayer[bayerStep] +
bayer[bayerStep + ] + bayer[bayerStep * + ] +
) >> ;
rgb[] = (uint8_t) t0;
rgb[] = (uint8_t) t1;
rgb[-] = bayer[bayerStep + ]; t0 = (bayer[] + bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[bayerStep + ] + bayer[bayerStep + ] +
) >> ;
rgb[] = (uint8_t) t0;
rgb[] = bayer[bayerStep + ];
rgb[] = (uint8_t) t1;
}
} if (bayer < bayerEnd)
{
t0 = (bayer[] + bayer[] + bayer[bayerStep * ] +
bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[] + bayer[bayerStep] +
bayer[bayerStep + ] + bayer[bayerStep * + ] +
) >> ;
rgb[-blue] = (uint8_t) t0;
rgb[] = (uint8_t) t1;
rgb[blue] = bayer[bayerStep + ];
bayer++;
rgb += ;
} bayer -= width;
rgb -= width * ; blue = -blue;
start_with_green = !start_with_green;
}
return DC1394_SUCCESS;
} /* High-Quality Linear Interpolation For Demosaicing Of
Bayer-Patterned Color Images, by Henrique S. Malvar, Li-wei He, and
Ross Cutler, in ICASSP'04 */
dc1394error_t dc1394_bayer_HQLinear(const uint8_t *restrict bayer, uint8_t *restrict rgb, int sx, int sy, int tile)
{
const int bayerStep = sx;
const int rgbStep = * sx;
int width = sx;
int height = sy;
int blue = tile == DC1394_COLOR_FILTER_BGGR
|| tile == DC1394_COLOR_FILTER_GBRG ? - : ;
int start_with_green = tile == DC1394_COLOR_FILTER_GBRG
|| tile == DC1394_COLOR_FILTER_GRBG; if ((tile > DC1394_COLOR_FILTER_MAX) || (tile < DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER; ClearBorders(rgb, sx, sy, );
rgb += * rgbStep + + ;
height -= ;
width -= ; /* We begin with a (+1 line,+1 column) offset with respect to bilinear decoding, so start_with_green is the same, but blue is opposite */
blue = -blue; for (; height--; bayer += bayerStep, rgb += rgbStep)
{
int t0, t1;
const uint8_t *bayerEnd = bayer + width;
const int bayerStep2 = bayerStep * ;
const int bayerStep3 = bayerStep * ;
const int bayerStep4 = bayerStep * ; if (start_with_green)
{
/* at green pixel */
rgb[] = bayer[bayerStep2 + ];
t0 = rgb[] *
+ ((bayer[bayerStep + ] + bayer[bayerStep3 + ]) << )
- bayer[]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep4 + ]
+ ((bayer[bayerStep2] + bayer[bayerStep2 + ] + ) >> );
t1 = rgb[] * +
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ]) << )
- bayer[bayerStep2]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep2 + ]
+ ((bayer[] + bayer[bayerStep4 + ] + ) >> );
t0 = (t0 + ) >> ;
CLIP(t0, rgb[-blue]);
t1 = (t1 + ) >> ;
CLIP(t1, rgb[blue]);
bayer++;
rgb += ;
} if (blue > )
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
/* B at B */
rgb[] = bayer[bayerStep2 + ];
/* R at B */
t0 = ((bayer[bayerStep + ] + bayer[bayerStep + ] +
bayer[bayerStep3 + ] + bayer[bayerStep3 + ]) << )
-
(((bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 +
]) * + ) >> )
+ rgb[] * ;
/* G at B */
t1 = ((bayer[bayerStep + ] + bayer[bayerStep2 + ] +
bayer[bayerStep2 + ] + bayer[bayerStep3 + ]) << )
- (bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 + ])
+ (rgb[] << );
t0 = (t0 + ) >> ;
CLIP(t0, rgb[-]);
t1 = (t1 + ) >> ;
CLIP(t1, rgb[]);
/* at green pixel */
rgb[] = bayer[bayerStep2 + ];
t0 = rgb[] *
+ ((bayer[bayerStep + ] + bayer[bayerStep3 + ]) << )
- bayer[]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep4 + ]
+
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ] +
) >> );
t1 = rgb[] * +
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ]) << )
- bayer[bayerStep2 + ]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep2 + ]
+ ((bayer[] + bayer[bayerStep4 + ] + ) >> );
t0 = (t0 + ) >> ;
CLIP(t0, rgb[]);
t1 = (t1 + ) >> ;
CLIP(t1, rgb[]);
}
}
else
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
/* R at R */
rgb[-] = bayer[bayerStep2 + ];
/* B at R */
t0 = ((bayer[bayerStep + ] + bayer[bayerStep + ] +
bayer[bayerStep3 + ] + bayer[bayerStep3 + ]) << )
-
(((bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 +
]) * + ) >> )
+ rgb[-] * ;
/* G at R */
t1 = ((bayer[bayerStep + ] + bayer[bayerStep2 + ] +
bayer[bayerStep2 + ] + bayer[bayerStep * +
]) << )
- (bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 + ])
+ (rgb[-] << );
t0 = (t0 + ) >> ;
CLIP(t0, rgb[]);
t1 = (t1 + ) >> ;
CLIP(t1, rgb[]); /* at green pixel */
rgb[] = bayer[bayerStep2 + ];
t0 = rgb[] *
+ ((bayer[bayerStep + ] + bayer[bayerStep3 + ]) << )
- bayer[]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep4 + ]
+
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ] +
) >> );
t1 = rgb[] * +
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ]) << )
- bayer[bayerStep2 + ]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep2 + ]
+ ((bayer[] + bayer[bayerStep4 + ] + ) >> );
t0 = (t0 + ) >> ;
CLIP(t0, rgb[]);
t1 = (t1 + ) >> ;
CLIP(t1, rgb[]);
}
} if (bayer < bayerEnd)
{
/* B at B */
rgb[blue] = bayer[bayerStep2 + ];
/* R at B */
t0 = ((bayer[bayerStep + ] + bayer[bayerStep + ] +
bayer[bayerStep3 + ] + bayer[bayerStep3 + ]) << )
-
(((bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 +
]) * + ) >> )
+ rgb[blue] * ;
/* G at B */
t1 = (((bayer[bayerStep + ] + bayer[bayerStep2 + ] +
bayer[bayerStep2 + ] + bayer[bayerStep3 + ])) << )
- (bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 + ])
+ (rgb[blue] << );
t0 = (t0 + ) >> ;
CLIP(t0, rgb[-blue]);
t1 = (t1 + ) >> ;
CLIP(t1, rgb[]);
bayer++;
rgb += ;
} bayer -= width;
rgb -= width * ; blue = -blue;
start_with_green = !start_with_green;
} return DC1394_SUCCESS; } /* coriander's Bayer decoding */
/* Edge Sensing Interpolation II from http://www-ise.stanford.edu/~tingchen/ */
/* (Laroche,Claude A. "Apparatus and method for adaptively
interpolating a full color image utilizing chrominance gradients"
U.S. Patent 5,373,322) */
dc1394error_t dc1394_bayer_EdgeSense(const uint8_t *restrict bayer, uint8_t *restrict rgb, int sx, int sy, int tile)
{
/* Removed due to patent concerns */
return DC1394_FUNCTION_NOT_SUPPORTED;
} /* coriander's Bayer decoding */
dc1394error_t dc1394_bayer_Downsample(const uint8_t *restrict bayer, uint8_t *restrict rgb, int sx, int sy, int tile)
{
uint8_t *outR, *outG, *outB;
register int i, j;
int tmp; switch (tile)
{
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_BGGR:
outR = &rgb[];
outG = &rgb[];
outB = &rgb[];
break;
case DC1394_COLOR_FILTER_GBRG:
case DC1394_COLOR_FILTER_RGGB:
outR = &rgb[];
outG = &rgb[];
outB = &rgb[];
break;
default:
return DC1394_INVALID_COLOR_FILTER;
} switch (tile)
{
case DC1394_COLOR_FILTER_GRBG: //---------------------------------------------------------
case DC1394_COLOR_FILTER_GBRG:
for (i = ; i < sy * sx; i += (sx << ))
{
for (j = ; j < sx; j += )
{
tmp = ((bayer[i + j] + bayer[i + sx + j + ]) >> );
CLIP(tmp, outG[((i >> ) + (j >> )) * ]);
tmp = bayer[i + sx + j + ];
CLIP(tmp, outR[((i >> ) + (j >> )) * ]);
tmp = bayer[i + sx + j];
CLIP(tmp, outB[((i >> ) + (j >> )) * ]);
}
}
break;
case DC1394_COLOR_FILTER_BGGR: //---------------------------------------------------------
case DC1394_COLOR_FILTER_RGGB:
for (i = ; i < sy * sx; i += (sx << ))
{
for (j = ; j < sx; j += )
{
tmp = ((bayer[i + sx + j] + bayer[i + j + ]) >> );
CLIP(tmp, outG[((i >> ) + (j >> )) * ]);
tmp = bayer[i + sx + j + ];
CLIP(tmp, outR[((i >> ) + (j >> )) * ]);
tmp = bayer[i + j];
CLIP(tmp, outB[((i >> ) + (j >> )) * ]);
}
}
break;
} return DC1394_SUCCESS; } /* this is the method used inside AVT cameras. See AVT docs. */
dc1394error_t dc1394_bayer_Simple(const uint8_t *restrict bayer, uint8_t *restrict rgb, int sx, int sy, int tile)
{
const int bayerStep = sx;
const int rgbStep = * sx;
int width = sx;
int height = sy;
int blue = tile == DC1394_COLOR_FILTER_BGGR
|| tile == DC1394_COLOR_FILTER_GBRG ? - : ;
int start_with_green = tile == DC1394_COLOR_FILTER_GBRG
|| tile == DC1394_COLOR_FILTER_GRBG;
int i, imax, iinc; if ((tile > DC1394_COLOR_FILTER_MAX) || (tile < DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER; /* add black border */
imax = sx * sy * ;
for (i = sx * (sy - ) * ; i < imax; i++)
{
rgb[i] = ;
}
iinc = (sx - ) * ;
for (i = (sx - ) * ; i < imax; i += iinc)
{
rgb[i++] = ;
rgb[i++] = ;
rgb[i++] = ;
} rgb += ;
width -= ;
height -= ; for (; height--; bayer += bayerStep, rgb += rgbStep)
{
const uint8_t *bayerEnd = bayer + width; if (start_with_green)
{
rgb[-blue] = bayer[];
rgb[] = (bayer[] + bayer[bayerStep + ] + ) >> ;
rgb[blue] = bayer[bayerStep];
bayer++;
rgb += ;
} if (blue > )
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
rgb[-] = bayer[];
rgb[] = (bayer[] + bayer[bayerStep] + ) >> ;
rgb[] = bayer[bayerStep + ]; rgb[] = bayer[];
rgb[] = (bayer[] + bayer[bayerStep + ] + ) >> ;
rgb[] = bayer[bayerStep + ];
}
}
else
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
rgb[] = bayer[];
rgb[] = (bayer[] + bayer[bayerStep] + ) >> ;
rgb[-] = bayer[bayerStep + ]; rgb[] = bayer[];
rgb[] = (bayer[] + bayer[bayerStep + ] + ) >> ;
rgb[] = bayer[bayerStep + ];
}
} if (bayer < bayerEnd)
{
rgb[-blue] = bayer[];
rgb[] = (bayer[] + bayer[bayerStep] + ) >> ;
rgb[blue] = bayer[bayerStep + ];
bayer++;
rgb += ;
} bayer -= width;
rgb -= width * ; blue = -blue;
start_with_green = !start_with_green;
} return DC1394_SUCCESS; } /* 16-bits versions */ /* insprired by OpenCV's Bayer decoding */
dc1394error_t dc1394_bayer_NearestNeighbor_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
const int bayerStep = sx;
const int rgbStep = * sx;
int width = sx;
int height = sy;
int blue = tile == DC1394_COLOR_FILTER_BGGR
|| tile == DC1394_COLOR_FILTER_GBRG ? - : ;
int start_with_green = tile == DC1394_COLOR_FILTER_GBRG
|| tile == DC1394_COLOR_FILTER_GRBG;
int i, iinc, imax; if ((tile > DC1394_COLOR_FILTER_MAX) || (tile < DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER; /* add black border */
imax = sx * sy * ;
for (i = sx * (sy - ) * ; i < imax; i++)
{
rgb[i] = ;
}
iinc = (sx - ) * ;
for (i = (sx - ) * ; i < imax; i += iinc)
{
rgb[i++] = ;
rgb[i++] = ;
rgb[i++] = ;
} rgb += ;
height -= ;
width -= ; for (; height--; bayer += bayerStep, rgb += rgbStep)
{
//int t0, t1;
const uint16_t *bayerEnd = bayer + width; if (start_with_green)
{
rgb[-blue] = bayer[];
rgb[] = bayer[bayerStep + ];
rgb[blue] = bayer[bayerStep];
bayer++;
rgb += ;
} if (blue > )
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
rgb[-] = bayer[];
rgb[] = bayer[];
rgb[] = bayer[bayerStep + ]; rgb[] = bayer[];
rgb[] = bayer[bayerStep + ];
rgb[] = bayer[bayerStep + ];
}
}
else
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
rgb[] = bayer[];
rgb[] = bayer[];
rgb[-] = bayer[bayerStep + ]; rgb[] = bayer[];
rgb[] = bayer[bayerStep + ];
rgb[] = bayer[bayerStep + ];
}
} if (bayer < bayerEnd)
{
rgb[-blue] = bayer[];
rgb[] = bayer[];
rgb[blue] = bayer[bayerStep + ];
bayer++;
rgb += ;
} bayer -= width;
rgb -= width * ; blue = -blue;
start_with_green = !start_with_green;
} return DC1394_SUCCESS; }
/* OpenCV's Bayer decoding */
dc1394error_t dc1394_bayer_Bilinear_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
const int bayerStep = sx;
const int rgbStep = * sx;
int width = sx;
int height = sy;
int blue = tile == DC1394_COLOR_FILTER_BGGR
|| tile == DC1394_COLOR_FILTER_GBRG ? - : ;
int start_with_green = tile == DC1394_COLOR_FILTER_GBRG
|| tile == DC1394_COLOR_FILTER_GRBG; if ((tile > DC1394_COLOR_FILTER_MAX) || (tile < DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER; rgb += rgbStep + + ;
height -= ;
width -= ; for (; height--; bayer += bayerStep, rgb += rgbStep)
{
int t0, t1;
const uint16_t *bayerEnd = bayer + width; if (start_with_green)
{
/* OpenCV has a bug in the next line, which was
t0 = (bayer[0] + bayer[bayerStep * 2] + 1) >> 1; */
t0 = (bayer[] + bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[bayerStep] + bayer[bayerStep + ] + ) >> ;
rgb[-blue] = (uint16_t) t0;
rgb[] = bayer[bayerStep + ];
rgb[blue] = (uint16_t) t1;
bayer++;
rgb += ;
} if (blue > )
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
t0 = (bayer[] + bayer[] + bayer[bayerStep * ] +
bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[] + bayer[bayerStep] +
bayer[bayerStep + ] + bayer[bayerStep * + ] +
) >> ;
rgb[-] = (uint16_t) t0;
rgb[] = (uint16_t) t1;
rgb[] = bayer[bayerStep + ]; t0 = (bayer[] + bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[bayerStep + ] + bayer[bayerStep + ] +
) >> ;
rgb[] = (uint16_t) t0;
rgb[] = bayer[bayerStep + ];
rgb[] = (uint16_t) t1;
}
}
else
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
t0 = (bayer[] + bayer[] + bayer[bayerStep * ] +
bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[] + bayer[bayerStep] +
bayer[bayerStep + ] + bayer[bayerStep * + ] +
) >> ;
rgb[] = (uint16_t) t0;
rgb[] = (uint16_t) t1;
rgb[-] = bayer[bayerStep + ]; t0 = (bayer[] + bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[bayerStep + ] + bayer[bayerStep + ] +
) >> ;
rgb[] = (uint16_t) t0;
rgb[] = bayer[bayerStep + ];
rgb[] = (uint16_t) t1;
}
} if (bayer < bayerEnd)
{
t0 = (bayer[] + bayer[] + bayer[bayerStep * ] +
bayer[bayerStep * + ] + ) >> ;
t1 = (bayer[] + bayer[bayerStep] +
bayer[bayerStep + ] + bayer[bayerStep * + ] +
) >> ;
rgb[-blue] = (uint16_t) t0;
rgb[] = (uint16_t) t1;
rgb[blue] = bayer[bayerStep + ];
bayer++;
rgb += ;
} bayer -= width;
rgb -= width * ; blue = -blue;
start_with_green = !start_with_green;
} return DC1394_SUCCESS; } /* High-Quality Linear Interpolation For Demosaicing Of
Bayer-Patterned Color Images, by Henrique S. Malvar, Li-wei He, and
Ross Cutler, in ICASSP'04 */
dc1394error_t dc1394_bayer_HQLinear_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
const int bayerStep = sx;
const int rgbStep = * sx;
int width = sx;
int height = sy;
/*
the two letters of the OpenCV name are respectively
the 4th and 3rd letters from the blinky name,
and we also have to switch R and B (OpenCV is BGR) CV_BayerBG2BGR <-> DC1394_COLOR_FILTER_BGGR
CV_BayerGB2BGR <-> DC1394_COLOR_FILTER_GBRG
CV_BayerGR2BGR <-> DC1394_COLOR_FILTER_GRBG int blue = tile == CV_BayerBG2BGR || tile == CV_BayerGB2BGR ? -1 : 1;
int start_with_green = tile == CV_BayerGB2BGR || tile == CV_BayerGR2BGR;
*/
int blue = tile == DC1394_COLOR_FILTER_BGGR
|| tile == DC1394_COLOR_FILTER_GBRG ? - : ;
int start_with_green = tile == DC1394_COLOR_FILTER_GBRG
|| tile == DC1394_COLOR_FILTER_GRBG; if ((tile > DC1394_COLOR_FILTER_MAX) || (tile < DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER; ClearBorders_uint16(rgb, sx, sy, );
rgb += * rgbStep + + ;
height -= ;
width -= ; /* We begin with a (+1 line,+1 column) offset with respect to bilinear decoding, so start_with_green is the same, but blue is opposite */
blue = -blue; for (; height--; bayer += bayerStep, rgb += rgbStep)
{
int t0, t1;
const uint16_t *bayerEnd = bayer + width;
const int bayerStep2 = bayerStep * ;
const int bayerStep3 = bayerStep * ;
const int bayerStep4 = bayerStep * ; if (start_with_green)
{
/* at green pixel */
rgb[] = bayer[bayerStep2 + ];
t0 = rgb[] *
+ ((bayer[bayerStep + ] + bayer[bayerStep3 + ]) << )
- bayer[]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep4 + ]
+ ((bayer[bayerStep2] + bayer[bayerStep2 + ] + ) >> );
t1 = rgb[] * +
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ]) << )
- bayer[bayerStep2]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep2 + ]
+ ((bayer[] + bayer[bayerStep4 + ] + ) >> );
t0 = (t0 + ) >> ;
CLIP16(t0, rgb[-blue], bits);
t1 = (t1 + ) >> ;
CLIP16(t1, rgb[blue], bits);
bayer++;
rgb += ;
} if (blue > )
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
/* B at B */
rgb[] = bayer[bayerStep2 + ];
/* R at B */
t0 = ((bayer[bayerStep + ] + bayer[bayerStep + ] +
bayer[bayerStep3 + ] + bayer[bayerStep3 + ]) << )
-
(((bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 +
]) * + ) >> )
+ rgb[] * ;
/* G at B */
t1 = ((bayer[bayerStep + ] + bayer[bayerStep2 + ] +
bayer[bayerStep2 + ] + bayer[bayerStep * +
]) << )
- (bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 + ])
+ (rgb[] << );
t0 = (t0 + ) >> ;
CLIP16(t0, rgb[-], bits);
t1 = (t1 + ) >> ;
CLIP16(t1, rgb[], bits);
/* at green pixel */
rgb[] = bayer[bayerStep2 + ];
t0 = rgb[] *
+ ((bayer[bayerStep + ] + bayer[bayerStep3 + ]) << )
- bayer[]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep4 + ]
+
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ] +
) >> );
t1 = rgb[] * +
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ]) << )
- bayer[bayerStep2 + ]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep2 + ]
+ ((bayer[] + bayer[bayerStep4 + ] + ) >> );
t0 = (t0 + ) >> ;
CLIP16(t0, rgb[], bits);
t1 = (t1 + ) >> ;
CLIP16(t1, rgb[], bits);
}
}
else
{
for (; bayer <= bayerEnd - ; bayer += , rgb += )
{
/* R at R */
rgb[-] = bayer[bayerStep2 + ];
/* B at R */
t0 = ((bayer[bayerStep + ] + bayer[bayerStep + ] +
bayer[bayerStep * + ] + bayer[bayerStep3 +
]) << )
-
(((bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 +
]) * + ) >> )
+ rgb[-] * ;
/* G at R */
t1 = ((bayer[bayerStep + ] + bayer[bayerStep2 + ] +
bayer[bayerStep2 + ] + bayer[bayerStep3 + ]) << )
- (bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 + ])
+ (rgb[-] << );
t0 = (t0 + ) >> ;
CLIP16(t0, rgb[], bits);
t1 = (t1 + ) >> ;
CLIP16(t1, rgb[], bits); /* at green pixel */
rgb[] = bayer[bayerStep2 + ];
t0 = rgb[] *
+ ((bayer[bayerStep + ] + bayer[bayerStep3 + ]) << )
- bayer[]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep4 + ]
+
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ] +
) >> );
t1 = rgb[] * +
((bayer[bayerStep2 + ] + bayer[bayerStep2 + ]) << )
- bayer[bayerStep2 + ]
- bayer[bayerStep + ]
- bayer[bayerStep + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep3 + ]
- bayer[bayerStep2 + ]
+ ((bayer[] + bayer[bayerStep4 + ] + ) >> );
t0 = (t0 + ) >> ;
CLIP16(t0, rgb[], bits);
t1 = (t1 + ) >> ;
CLIP16(t1, rgb[], bits);
}
} if (bayer < bayerEnd)
{
/* B at B */
rgb[blue] = bayer[bayerStep2 + ];
/* R at B */
t0 = ((bayer[bayerStep + ] + bayer[bayerStep + ] +
bayer[bayerStep3 + ] + bayer[bayerStep3 + ]) << )
-
(((bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 +
]) * + ) >> )
+ rgb[blue] * ;
/* G at B */
t1 = (((bayer[bayerStep + ] + bayer[bayerStep2 + ] +
bayer[bayerStep2 + ] + bayer[bayerStep3 + ])) << )
- (bayer[] + bayer[bayerStep2] +
bayer[bayerStep2 + ] + bayer[bayerStep4 + ])
+ (rgb[blue] << );
t0 = (t0 + ) >> ;
CLIP16(t0, rgb[-blue], bits);
t1 = (t1 + ) >> ;
CLIP16(t1, rgb[], bits);
bayer++;
rgb += ;
} bayer -= width;
rgb -= width * ; blue = -blue;
start_with_green = !start_with_green;
} return DC1394_SUCCESS;
} /* coriander's Bayer decoding */
dc1394error_t dc1394_bayer_EdgeSense_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
/* Removed due to patent concerns */
return DC1394_FUNCTION_NOT_SUPPORTED;
} /* coriander's Bayer decoding */
dc1394error_t dc1394_bayer_Downsample_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
uint16_t *outR, *outG, *outB;
register int i, j;
int tmp; switch (tile)
{
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_BGGR:
outR = &rgb[];
outG = &rgb[];
outB = &rgb[];
break;
case DC1394_COLOR_FILTER_GBRG:
case DC1394_COLOR_FILTER_RGGB:
outR = &rgb[];
outG = &rgb[];
outB = &rgb[];
break;
default:
return DC1394_INVALID_COLOR_FILTER;
} switch (tile)
{
case DC1394_COLOR_FILTER_GRBG: //---------------------------------------------------------
case DC1394_COLOR_FILTER_GBRG:
for (i = ; i < sy * sx; i += (sx << ))
{
for (j = ; j < sx; j += )
{
tmp =
((bayer[i + j] + bayer[i + sx + j + ]) >> );
CLIP16(tmp, outG[((i >> ) + (j >> )) * ], bits);
tmp = bayer[i + sx + j + ];
CLIP16(tmp, outR[((i >> ) + (j >> )) * ], bits);
tmp = bayer[i + sx + j];
CLIP16(tmp, outB[((i >> ) + (j >> )) * ], bits);
}
}
break;
case DC1394_COLOR_FILTER_BGGR: //---------------------------------------------------------
case DC1394_COLOR_FILTER_RGGB:
for (i = ; i < sy * sx; i += (sx << ))
{
for (j = ; j < sx; j += )
{
tmp =
((bayer[i + sx + j] + bayer[i + j + ]) >> );
CLIP16(tmp, outG[((i >> ) + (j >> )) * ], bits);
tmp = bayer[i + sx + j + ];
CLIP16(tmp, outR[((i >> ) + (j >> )) * ], bits);
tmp = bayer[i + j];
CLIP16(tmp, outB[((i >> ) + (j >> )) * ], bits);
}
}
break;
} return DC1394_SUCCESS; } /* coriander's Bayer decoding */
dc1394error_t dc1394_bayer_Simple_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
uint16_t *outR, *outG, *outB;
register int i, j;
int tmp, base; // sx and sy should be even
switch (tile)
{
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_BGGR:
outR = &rgb[];
outG = &rgb[];
outB = &rgb[];
break;
case DC1394_COLOR_FILTER_GBRG:
case DC1394_COLOR_FILTER_RGGB:
outR = &rgb[];
outG = &rgb[];
outB = &rgb[];
break;
default:
return DC1394_INVALID_COLOR_FILTER;
} switch (tile)
{
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_BGGR:
outR = &rgb[];
outG = &rgb[];
outB = &rgb[];
break;
case DC1394_COLOR_FILTER_GBRG:
case DC1394_COLOR_FILTER_RGGB:
outR = &rgb[];
outG = &rgb[];
outB = &rgb[];
break;
default:
outR = NULL;
outG = NULL;
outB = NULL;
break;
} switch (tile)
{
case DC1394_COLOR_FILTER_GRBG: //---------------------------------------------------------
case DC1394_COLOR_FILTER_GBRG:
for (i = ; i < sy - ; i += )
{
for (j = ; j < sx - ; j += )
{
base = i * sx + j;
tmp = ((bayer[base] + bayer[base + sx + ]) >> );
CLIP16(tmp, outG[base * ], bits);
tmp = bayer[base + ];
CLIP16(tmp, outR[base * ], bits);
tmp = bayer[base + sx];
CLIP16(tmp, outB[base * ], bits);
}
}
for (i = ; i < sy - ; i += )
{
for (j = ; j < sx - ; j += )
{
base = i * sx + j;
tmp = ((bayer[base + ] + bayer[base + sx]) >> );
CLIP16(tmp, outG[(base) * ], bits);
tmp = bayer[base];
CLIP16(tmp, outR[(base) * ], bits);
tmp = bayer[base + + sx];
CLIP16(tmp, outB[(base) * ], bits);
}
}
for (i = ; i < sy - ; i += )
{
for (j = ; j < sx - ; j += )
{
base = i * sx + j;
tmp = ((bayer[base + sx] + bayer[base + ]) >> );
CLIP16(tmp, outG[base * ], bits);
tmp = bayer[base + sx + ];
CLIP16(tmp, outR[base * ], bits);
tmp = bayer[base];
CLIP16(tmp, outB[base * ], bits);
}
}
for (i = ; i < sy - ; i += )
{
for (j = ; j < sx - ; j += )
{
base = i * sx + j;
tmp = ((bayer[base] + bayer[base + + sx]) >> );
CLIP16(tmp, outG[(base) * ], bits);
tmp = bayer[base + sx];
CLIP16(tmp, outR[(base) * ], bits);
tmp = bayer[base + ];
CLIP16(tmp, outB[(base) * ], bits);
}
}
break;
case DC1394_COLOR_FILTER_BGGR: //---------------------------------------------------------
case DC1394_COLOR_FILTER_RGGB:
for (i = ; i < sy - ; i += )
{
for (j = ; j < sx - ; j += )
{
base = i * sx + j;
tmp = ((bayer[base + sx] + bayer[base + ]) >> );
CLIP16(tmp, outG[base * ], bits);
tmp = bayer[base + sx + ];
CLIP16(tmp, outR[base * ], bits);
tmp = bayer[base];
CLIP16(tmp, outB[base * ], bits);
}
}
for (i = ; i < sy - ; i += )
{
for (j = ; j < sx - ; j += )
{
base = i * sx + j;
tmp = ((bayer[base] + bayer[base + + sx]) >> );
CLIP16(tmp, outG[(base) * ], bits);
tmp = bayer[base + ];
CLIP16(tmp, outR[(base) * ], bits);
tmp = bayer[base + sx];
CLIP16(tmp, outB[(base) * ], bits);
}
}
for (i = ; i < sy - ; i += )
{
for (j = ; j < sx - ; j += )
{
base = i * sx + j;
tmp = ((bayer[base] + bayer[base + sx + ]) >> );
CLIP16(tmp, outG[base * ], bits);
tmp = bayer[base + sx];
CLIP16(tmp, outR[base * ], bits);
tmp = bayer[base + ];
CLIP16(tmp, outB[base * ], bits);
}
}
for (i = ; i < sy - ; i += )
{
for (j = ; j < sx - ; j += )
{
base = i * sx + j;
tmp = ((bayer[base + ] + bayer[base + sx]) >> );
CLIP16(tmp, outG[(base) * ], bits);
tmp = bayer[base];
CLIP16(tmp, outR[(base) * ], bits);
tmp = bayer[base + + sx];
CLIP16(tmp, outB[(base) * ], bits);
}
}
break;
} /* add black border */
for (i = sx * (sy - ) * ; i < sx * sy * ; i++)
{
rgb[i] = ;
}
for (i = (sx - ) * ; i < sx * sy * ; i += (sx - ) * )
{
rgb[i++] = ;
rgb[i++] = ;
rgb[i++] = ;
} return DC1394_SUCCESS; } /* Variable Number of Gradients, from dcraw <http://www.cybercom.net/~dcoffin/dcraw/> */
/* Ported to libdc1394 by Frederic Devernay */ #define FORC3 for (c=0; c < 3; c++) #define SQR(x) ((x)*(x))
#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#define LIM(x,min,max) MAX(min,MIN(x,max))
#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
/*
In order to inline this calculation, I make the risky
assumption that all filter patterns can be described
by a repeating pattern of eight rows and two columns Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
*/
#define FC(row,col) \
(filters >> ((((row) << & ) + ((col) & )) << ) & ) /*
This algorithm is officially called: "Interpolation using a Threshold-based variable number of gradients" described in http://www-ise.stanford.edu/~tingchen/algodep/vargra.html I've extended the basic idea to work with non-Bayer filter arrays.
Gradients are numbered clockwise from NW=0 to W=7.
*/
static const signed char bayervng_terms[] =
{
-, -, +, -, , 0x01, -, -, +, +, , 0x01, -, -, -, +, , 0x01,
-, -, +, -, , 0x02, -, -, +, +, , 0x03, -, -, +, +, , 0x01,
-, +, +, -, , 0x06, -, +, +, +, , 0x02, -, +, +, +, , 0x03,
-, +, -, +, , 0x04, -, +, +, -, , 0x04, -, +, +, +, , 0x06,
-, +, +, +, , 0x02, -, +, +, +, , 0x04, -, +, +, +, , 0x04,
-, -, -, +, , 0x80, -, -, +, -, , 0x01, -, -, +, -, , 0x01,
-, -, +, +, , 0x01, -, -, -, +, , 0x88, -, -, +, -, , 0x40,
-, -, +, -, , 0x22, -, -, +, +, , 0x33, -, -, +, +, , 0x11,
-, +, -, +, , 0x08, -, +, +, -, , 0x44, -, +, +, +, , 0x11,
-, +, +, -, , 0x40, -, +, +, -, , 0x66, -, +, +, +, , 0x22,
-, +, +, +, , 0x33, -, +, +, +, , 0x10, -, +, +, -, , 0x44,
-, +, +, +, , 0x66, -, +, +, +, , 0x22, -, +, +, +, , 0x10,
-, +, +, +, , 0x04, -, +, +, +, , 0x04, -, +, +, +, , 0x04,
+, -, +, +, , 0x80, +, -, +, +, , 0x88, +, -, +, -, , 0x40,
+, -, +, +, , 0x11, +, -, +, -, , 0x40, +, -, +, -, , 0x20,
+, -, +, +, , 0x30, +, -, +, +, , 0x10, +, +, +, +, , 0x08,
+, +, +, -, , 0x40, +, +, +, -, , 0x60, +, +, +, +, , 0x20,
+, +, +, +, , 0x30, +, +, +, +, , 0x10, +, +, +, +, , 0x44,
+, +, +, +, , 0x10, +, +, +, -, , 0x40, +, +, +, +, , 0x60,
+, +, +, +, , 0x20, +, +, +, +, , 0x10, +, -, +, +, , 0x80,
+, -, +, +, , 0x88, +, +, +, +, , 0x08, +, +, +, -, , 0x40,
+, +, +, +, , 0x10
}, bayervng_chood[] = { -, -, -, , -, +, , +, +, +, +, , +, -, , - }; dc1394error_t dc1394_bayer_VNG(const uint8_t *restrict bayer, uint8_t *restrict dst, int sx, int sy, dc1394color_filter_t pattern)
{
const int height = sy, width = sx;
static const signed char *cp;
/* the following has the same type as the image */
uint8_t (*brow[])[], *pix; /* [FD] */
int code[][][], *ip, gval[], gmin, gmax, sum[];
int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
int g, diff, thold, num, c;
uint32_t filters; /* [FD] */ /* first, use bilinear bayer decoding */
dc1394_bayer_Bilinear(bayer, dst, sx, sy, pattern); switch(pattern)
{
case DC1394_COLOR_FILTER_BGGR:
filters = 0x16161616;
break;
case DC1394_COLOR_FILTER_GRBG:
filters = 0x61616161;
break;
case DC1394_COLOR_FILTER_RGGB:
filters = 0x94949494;
break;
case DC1394_COLOR_FILTER_GBRG:
filters = 0x49494949;
break;
default:
return DC1394_INVALID_COLOR_FILTER;
} for (row = ; row < ; row++) /* Precalculate for VNG */
{
for (col = ; col < ; col++)
{
ip = code[row][col];
for (cp = bayervng_terms, t = ; t < ; t++)
{
y1 = *cp++;
x1 = *cp++;
y2 = *cp++;
x2 = *cp++;
weight = *cp++;
grads = *cp++;
color = FC(row + y1, col + x1);
if (FC(row + y2, col + x2) != color) continue;
diag = (FC(row, col + ) == color && FC(row + , col) == color) ? : ;
if (abs(y1 - y2) == diag && abs(x1 - x2) == diag) continue;
*ip++ = (y1 * width + x1) * + color; /* [FD] */
*ip++ = (y2 * width + x2) * + color; /* [FD] */
*ip++ = weight;
for (g = ; g < ; g++)
if (grads & << g) *ip++ = g;
*ip++ = -;
}
*ip++ = INT_MAX;
for (cp = bayervng_chood, g = ; g < ; g++)
{
y = *cp++;
x = *cp++;
*ip++ = (y * width + x) * ; /* [FD] */
color = FC(row, col);
if (FC(row + y, col + x) != color && FC(row + y * , col + x * ) == color)
*ip++ = (y * width + x) * + color; /* [FD] */
else
*ip++ = ;
}
}
}
brow[] = calloc (width * , sizeof **brow);
//merror (brow[4], "vng_interpolate()");
for (row = ; row < ; row++)
brow[row] = brow[] + row * width;
for (row = ; row < height - ; row++) /* Do VNG interpolation */
{
for (col = ; col < width - ; col++)
{
pix = dst + (row * width + col) * ; /* [FD] */
ip = code[row & ][col & ];
memset (gval, , sizeof gval);
while ((g = ip[]) != INT_MAX) /* Calculate gradients */
{
diff = ABS(pix[g] - pix[ip[]]) << ip[];
gval[ip[]] += diff;
ip += ;
if ((g = ip[-]) == -) continue;
gval[g] += diff;
while ((g = *ip++) != -)
gval[g] += diff;
}
ip++;
gmin = gmax = gval[]; /* Choose a threshold */
for (g = ; g < ; g++)
{
if (gmin > gval[g]) gmin = gval[g];
if (gmax < gval[g]) gmax = gval[g];
}
if (gmax == )
{
memcpy (brow[][col], pix, * sizeof * dst); /* [FD] */
continue;
}
thold = gmin + (gmax >> );
memset (sum, , sizeof sum);
color = FC(row, col);
for (num = g = ; g < ; g++, ip += ) /* Average the neighbors */
{
if (gval[g] <= thold)
{
for (c = ; c < ; c++) /* [FD] */
if (c == color && ip[])
sum[c] += (pix[c] + pix[ip[]]) >> ;
else
sum[c] += pix[ip[] + c];
num++;
}
}
for (c = ; c < ; c++) /* [FD] Save to buffer */
{
t = pix[color];
if (c != color)
t += (sum[c] - sum[color]) / num;
CLIP(t, brow[][col][c]); /* [FD] */
}
}
if (row > ) /* Write buffer to image */
memcpy (dst + * ((row - )*width + ), brow[] + , (width - ) * * sizeof * dst); /* [FD] */
for (g = ; g < ; g++)
brow[(g-) & ] = brow[g];
}
memcpy (dst + * ((row - )*width + ), brow[] + , (width - ) * * sizeof * dst);
memcpy (dst + * ((row - )*width + ), brow[] + , (width - ) * * sizeof * dst);
free (brow[]); return DC1394_SUCCESS;
} dc1394error_t dc1394_bayer_VNG_uint16(const uint16_t *restrict bayer, uint16_t *restrict dst, int sx, int sy, dc1394color_filter_t pattern, int bits)
{
const int height = sy, width = sx;
static const signed char *cp;
/* the following has the same type as the image */
uint16_t (*brow[])[], *pix; /* [FD] */
int code[][][], *ip, gval[], gmin, gmax, sum[];
int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
int g, diff, thold, num, c;
uint32_t filters; /* [FD] */ /* first, use bilinear bayer decoding */ dc1394_bayer_Bilinear_uint16(bayer, dst, sx, sy, pattern, bits); switch(pattern)
{
case DC1394_COLOR_FILTER_BGGR:
filters = 0x16161616;
break;
case DC1394_COLOR_FILTER_GRBG:
filters = 0x61616161;
break;
case DC1394_COLOR_FILTER_RGGB:
filters = 0x94949494;
break;
case DC1394_COLOR_FILTER_GBRG:
filters = 0x49494949;
break;
default:
return DC1394_INVALID_COLOR_FILTER;
} for (row = ; row < ; row++) /* Precalculate for VNG */
{
for (col = ; col < ; col++)
{
ip = code[row][col];
for (cp = bayervng_terms, t = ; t < ; t++)
{
y1 = *cp++;
x1 = *cp++;
y2 = *cp++;
x2 = *cp++;
weight = *cp++;
grads = *cp++;
color = FC(row + y1, col + x1);
if (FC(row + y2, col + x2) != color) continue;
diag = (FC(row, col + ) == color && FC(row + , col) == color) ? : ;
if (abs(y1 - y2) == diag && abs(x1 - x2) == diag) continue;
*ip++ = (y1 * width + x1) * + color; /* [FD] */
*ip++ = (y2 * width + x2) * + color; /* [FD] */
*ip++ = weight;
for (g = ; g < ; g++)
if (grads & << g) *ip++ = g;
*ip++ = -;
}
*ip++ = INT_MAX;
for (cp = bayervng_chood, g = ; g < ; g++)
{
y = *cp++;
x = *cp++;
*ip++ = (y * width + x) * ; /* [FD] */
color = FC(row, col);
if (FC(row + y, col + x) != color && FC(row + y * , col + x * ) == color)
*ip++ = (y * width + x) * + color; /* [FD] */
else
*ip++ = ;
}
}
}
brow[] = calloc (width * , sizeof **brow);
//merror (brow[4], "vng_interpolate()");
for (row = ; row < ; row++)
brow[row] = brow[] + row * width;
for (row = ; row < height - ; row++) /* Do VNG interpolation */
{
for (col = ; col < width - ; col++)
{
pix = dst + (row * width + col) * ; /* [FD] */
ip = code[row & ][col & ];
memset (gval, , sizeof gval);
while ((g = ip[]) != INT_MAX) /* Calculate gradients */
{
diff = ABS(pix[g] - pix[ip[]]) << ip[];
gval[ip[]] += diff;
ip += ;
if ((g = ip[-]) == -) continue;
gval[g] += diff;
while ((g = *ip++) != -)
gval[g] += diff;
}
ip++;
gmin = gmax = gval[]; /* Choose a threshold */
for (g = ; g < ; g++)
{
if (gmin > gval[g]) gmin = gval[g];
if (gmax < gval[g]) gmax = gval[g];
}
if (gmax == )
{
memcpy (brow[][col], pix, * sizeof * dst); /* [FD] */
continue;
}
thold = gmin + (gmax >> );
memset (sum, , sizeof sum);
color = FC(row, col);
for (num = g = ; g < ; g++, ip += ) /* Average the neighbors */
{
if (gval[g] <= thold)
{
for (c = ; c < ; c++) /* [FD] */
if (c == color && ip[])
sum[c] += (pix[c] + pix[ip[]]) >> ;
else
sum[c] += pix[ip[] + c];
num++;
}
}
for (c = ; c < ; c++) /* [FD] Save to buffer */
{
t = pix[color];
if (c != color)
t += (sum[c] - sum[color]) / num;
CLIP16(t, brow[][col][c], bits); /* [FD] */
}
}
if (row > ) /* Write buffer to image */
memcpy (dst + * ((row - )*width + ), brow[] + , (width - ) * * sizeof * dst); /* [FD] */
for (g = ; g < ; g++)
brow[(g-) & ] = brow[g];
}
memcpy (dst + * ((row - )*width + ), brow[] + , (width - ) * * sizeof * dst);
memcpy (dst + * ((row - )*width + ), brow[] + , (width - ) * * sizeof * dst);
free (brow[]); return DC1394_SUCCESS;
} /* AHD interpolation ported from dcraw to libdc1394 by Samuel Audet */
static dc1394bool_t ahd_inited = DC1394_FALSE; /* WARNING: not multi-processor safe */ #define CLIPOUT(x) LIM(x,0,255)
#define CLIPOUT16(x,bits) LIM(x,0,((1<<bits)-1)) static const double xyz_rgb[][] = /* XYZ from RGB */
{
{ 0.412453, 0.357580, 0.180423 },
{ 0.212671, 0.715160, 0.072169 },
{ 0.019334, 0.119193, 0.950227 }
};
static const float d65_white[] = { 0.950456, , 1.088754 }; static void cam_to_cielab (uint16_t cam[], float lab[]) /* [SA] */
{
int c, i, j;
float r, xyz[];
static float cbrt[0x10000], xyz_cam[][]; if (cam == NULL)
{
for (i = ; i < 0x10000; i++)
{
r = i / 65535.0;
cbrt[i] = r > 0.008856 ? pow(r, / 3.0) : 7.787 * r + / 116.0;
}
for (i = ; i < ; i++)
for (j = ; j < ; j++) /* [SA] */
xyz_cam[i][j] = xyz_rgb[i][j] / d65_white[i]; /* [SA] */
}
else
{
xyz[] = xyz[] = xyz[] = 0.5;
FORC3 /* [SA] */
{
xyz[] += xyz_cam[][c] * cam[c];
xyz[] += xyz_cam[][c] * cam[c];
xyz[] += xyz_cam[][c] * cam[c];
}
xyz[] = cbrt[CLIPOUT16((int) xyz[], )]; /* [SA] */
xyz[] = cbrt[CLIPOUT16((int) xyz[], )]; /* [SA] */
xyz[] = cbrt[CLIPOUT16((int) xyz[], )]; /* [SA] */
lab[] = * xyz[] - ;
lab[] = * (xyz[] - xyz[]);
lab[] = * (xyz[] - xyz[]);
}
} /*
Adaptive Homogeneity-Directed interpolation is based on
the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
*/
#define TS 256 /* Tile Size */ dc1394error_t dc1394_bayer_AHD(const uint8_t *restrict bayer, uint8_t *restrict dst, int sx, int sy, dc1394color_filter_t pattern)
{
int i, j, top, left, row, col, tr, tc, fc, c, d, val, hm[];
/* the following has the same type as the image */
uint8_t (*pix)[], (*rix)[]; /* [SA] */
uint16_t rix16[]; /* [SA] */
static const int dir[] = { -, , -TS, TS };
unsigned ldiff[][], abdiff[][], leps, abeps;
float flab[]; /* [SA] */
uint8_t (*rgb)[TS][TS][];
short (*lab)[TS][TS][];
char (*homo)[TS][TS], *buffer; /* start - new code for libdc1394 */
uint32_t filters;
const int height = sy, width = sx;
int x, y; if (ahd_inited == DC1394_FALSE)
{
/* WARNING: this might not be multi-processor safe */
cam_to_cielab (NULL, NULL);
ahd_inited = DC1394_TRUE;
} switch(pattern)
{
case DC1394_COLOR_FILTER_BGGR:
filters = 0x16161616;
break;
case DC1394_COLOR_FILTER_GRBG:
filters = 0x61616161;
break;
case DC1394_COLOR_FILTER_RGGB:
filters = 0x94949494;
break;
case DC1394_COLOR_FILTER_GBRG:
filters = 0x49494949;
break;
default:
return DC1394_INVALID_COLOR_FILTER;
} /* fill-in destination with known exact values */
for (y = ; y < height; y++)
{
for (x = ; x < width; x++)
{
int channel = FC(y, x);
dst[(y*width+x)* + channel] = bayer[y*width+x];
}
}
/* end - new code for libdc1394 */ /* start - code from border_interpolate (int border) */
{
int border = ;
unsigned row, col, y, x, f, c, sum[]; for (row = ; row < height; row++)
for (col = ; col < width; col++)
{
if (col == border && row >= border && row < height - border)
col = width - border;
memset (sum, , sizeof sum);
for (y = row - ; y != row + ; y++)
for (x = col - ; x != col + ; x++)
if (y < height && x < width)
{
f = FC(y, x);
sum[f] += dst[(y*width+x)* + f]; /* [SA] */
sum[f+]++;
}
f = FC(row, col);
FORC3 if (c != f && sum[c+]) /* [SA] */
dst[(row*width+col)* + c] = sum[c] / sum[c+]; /* [SA] */
}
}
/* end - code from border_interpolate (int border) */ buffer = (char *) malloc ( * TS * TS); /* 1664 kB */
/* merror (buffer, "ahd_interpolate()"); */
rgb = (uint8_t( *)[TS][TS][]) buffer; /* [SA] */
lab = (short ( *)[TS][TS][])(buffer + * TS * TS);
homo = (char ( *)[TS][TS]) (buffer + * TS * TS); for (top = ; top < height; top += TS - )
for (left = ; left < width; left += TS - )
{
memset (rgb, , * TS * TS); /* Interpolate green horizontally and vertically: */
for (row = top < ? : top; row < top + TS && row < height - ; row++)
{
col = left + (FC(row, left) == );
if (col < ) col += ;
for (fc = FC(row, col); col < left + TS && col < width - ; col += )
{
pix = (uint8_t ( *)[])dst + (row * width + col); /* [SA] */
val = ((pix[-][] + pix[][fc] + pix[][]) *
- pix[-][fc] - pix[][fc]) >> ;
rgb[][row-top][col-left][] = ULIM(val, pix[-][], pix[][]);
val = ((pix[-width][] + pix[][fc] + pix[width][]) *
- pix[-*width][fc] - pix[*width][fc]) >> ;
rgb[][row-top][col-left][] = ULIM(val, pix[-width][], pix[width][]);
}
}
/* Interpolate red and blue, and convert to CIELab: */
for (d = ; d < ; d++)
for (row = top + ; row < top + TS - && row < height - ; row++)
for (col = left + ; col < left + TS - && col < width - ; col++)
{
pix = (uint8_t ( *)[])dst + (row * width + col); /* [SA] */
rix = &rgb[d][row-top][col-left];
if ((c = - FC(row, col)) == )
{
c = FC(row + , col);
val = pix[][] + (( pix[-][-c] + pix[][-c]
- rix[-][] - rix[][] ) >> );
rix[][-c] = CLIPOUT(val); /* [SA] */
val = pix[][] + (( pix[-width][c] + pix[width][c]
- rix[-TS][] - rix[TS][] ) >> );
}
else
val = rix[][] + (( pix[-width-][c] + pix[-width+][c]
+ pix[+width-][c] + pix[+width+][c]
- rix[-TS-][] - rix[-TS+][]
- rix[+TS-][] - rix[+TS+][] + ) >> );
rix[][c] = CLIPOUT(val); /* [SA] */
c = FC(row, col);
rix[][c] = pix[][c];
rix16[] = rix[][]; /* [SA] */
rix16[] = rix[][]; /* [SA] */
rix16[] = rix[][]; /* [SA] */
cam_to_cielab (rix16, flab); /* [SA] */
FORC3 lab[d][row-top][col-left][c] = * flab[c];
}
/* Build homogeneity maps from the CIELab images: */
memset (homo, , * TS * TS);
for (row = top + ; row < top + TS - && row < height; row++)
{
tr = row - top;
for (col = left + ; col < left + TS - && col < width; col++)
{
tc = col - left;
for (d = ; d < ; d++)
for (i = ; i < ; i++)
ldiff[d][i] = ABS(lab[d][tr][tc][] - lab[d][tr][tc+dir[i]][]);
leps = MIN(MAX(ldiff[][], ldiff[][]),
MAX(ldiff[][], ldiff[][]));
for (d = ; d < ; d++)
for (i = ; i < ; i++)
if (i >> == d || ldiff[d][i] <= leps)
abdiff[d][i] = SQR(lab[d][tr][tc][] - lab[d][tr][tc+dir[i]][])
+ SQR(lab[d][tr][tc][] - lab[d][tr][tc+dir[i]][]);
abeps = MIN(MAX(abdiff[][], abdiff[][]),
MAX(abdiff[][], abdiff[][]));
for (d = ; d < ; d++)
for (i = ; i < ; i++)
if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
homo[d][tr][tc]++;
}
}
/* Combine the most homogenous pixels for the final result: */
for (row = top + ; row < top + TS - && row < height - ; row++)
{
tr = row - top;
for (col = left + ; col < left + TS - && col < width - ; col++)
{
tc = col - left;
for (d = ; d < ; d++)
for (hm[d] = , i = tr - ; i <= tr + ; i++)
for (j = tc - ; j <= tc + ; j++)
hm[d] += homo[d][i][j];
if (hm[] != hm[])
FORC3 dst[(row*width+col)* + c] = CLIPOUT(rgb[hm[] > hm[]][tr][tc][c]); /* [SA] */
else
FORC3 dst[(row*width+col)* + c] =
CLIPOUT((rgb[][tr][tc][c] + rgb[][tr][tc][c]) >> ); /* [SA] */
}
}
}
free (buffer); return DC1394_SUCCESS;
} dc1394error_t dc1394_bayer_AHD_uint16(const uint16_t *restrict bayer, uint16_t *restrict dst, int sx, int sy, dc1394color_filter_t pattern, int bits)
{
int i, j, top, left, row, col, tr, tc, fc, c, d, val, hm[];
/* the following has the same type as the image */
uint16_t (*pix)[], (*rix)[]; /* [SA] */
static const int dir[] = { -, , -TS, TS };
unsigned ldiff[][], abdiff[][], leps, abeps;
float flab[];
uint16_t (*rgb)[TS][TS][]; /* [SA] */
short (*lab)[TS][TS][];
char (*homo)[TS][TS], *buffer; /* start - new code for libdc1394 */
uint32_t filters;
const int height = sy, width = sx;
int x, y; if (ahd_inited == DC1394_FALSE)
{
/* WARNING: this might not be multi-processor safe */
cam_to_cielab (NULL, NULL);
ahd_inited = DC1394_TRUE;
} switch(pattern)
{
case DC1394_COLOR_FILTER_BGGR:
filters = 0x16161616;
break;
case DC1394_COLOR_FILTER_GRBG:
filters = 0x61616161;
break;
case DC1394_COLOR_FILTER_RGGB:
filters = 0x94949494;
break;
case DC1394_COLOR_FILTER_GBRG:
filters = 0x49494949;
break;
default:
return DC1394_INVALID_COLOR_FILTER;
} /* fill-in destination with known exact values */
for (y = ; y < height; y++)
{
for (x = ; x < width; x++)
{
int channel = FC(y, x);
dst[(y*width+x)* + channel] = bayer[y*width+x];
}
}
/* end - new code for libdc1394 */ /* start - code from border_interpolate(int border) */
{
int border = ;
unsigned row, col, y, x, f, c, sum[]; for (row = ; row < height; row++)
for (col = ; col < width; col++)
{
if (col == border && row >= border && row < height - border)
col = width - border;
memset (sum, , sizeof sum);
for (y = row - ; y != row + ; y++)
for (x = col - ; x != col + ; x++)
if (y < height && x < width)
{
f = FC(y, x);
sum[f] += dst[(y*width+x)* + f]; /* [SA] */
sum[f+]++;
}
f = FC(row, col);
FORC3 if (c != f && sum[c+]) /* [SA] */
dst[(row*width+col)* + c] = sum[c] / sum[c+]; /* [SA] */
}
}
/* end - code from border_interpolate(int border) */ buffer = (char *) malloc ( * TS * TS); /* 1664 kB */
/* merror (buffer, "ahd_interpolate()"); */
rgb = (uint16_t( *)[TS][TS][]) buffer; /* [SA] */
lab = (short ( *)[TS][TS][])(buffer + * TS * TS);
homo = (char ( *)[TS][TS]) (buffer + * TS * TS); for (top = ; top < height; top += TS - )
for (left = ; left < width; left += TS - )
{
memset (rgb, , * TS * TS); /* Interpolate green horizontally and vertically: */
for (row = top < ? : top; row < top + TS && row < height - ; row++)
{
col = left + (FC(row, left) == );
if (col < ) col += ;
for (fc = FC(row, col); col < left + TS && col < width - ; col += )
{
pix = (uint16_t ( *)[])dst + (row * width + col); /* [SA] */
val = ((pix[-][] + pix[][fc] + pix[][]) *
- pix[-][fc] - pix[][fc]) >> ;
rgb[][row-top][col-left][] = ULIM(val, pix[-][], pix[][]);
val = ((pix[-width][] + pix[][fc] + pix[width][]) *
- pix[-*width][fc] - pix[*width][fc]) >> ;
rgb[][row-top][col-left][] = ULIM(val, pix[-width][], pix[width][]);
}
}
/* Interpolate red and blue, and convert to CIELab: */
for (d = ; d < ; d++)
for (row = top + ; row < top + TS - && row < height - ; row++)
for (col = left + ; col < left + TS - && col < width - ; col++)
{
pix = (uint16_t ( *)[])dst + (row * width + col); /* [SA] */
rix = &rgb[d][row-top][col-left];
if ((c = - FC(row, col)) == )
{
c = FC(row + , col);
val = pix[][] + (( pix[-][-c] + pix[][-c]
- rix[-][] - rix[][] ) >> );
rix[][-c] = CLIPOUT16(val, bits); /* [SA] */
val = pix[][] + (( pix[-width][c] + pix[width][c]
- rix[-TS][] - rix[TS][] ) >> );
}
else
val = rix[][] + (( pix[-width-][c] + pix[-width+][c]
+ pix[+width-][c] + pix[+width+][c]
- rix[-TS-][] - rix[-TS+][]
- rix[+TS-][] - rix[+TS+][] + ) >> );
rix[][c] = CLIPOUT16(val, bits); /* [SA] */
c = FC(row, col);
rix[][c] = pix[][c];
cam_to_cielab (rix[], flab);
FORC3 lab[d][row-top][col-left][c] = * flab[c];
}
/* Build homogeneity maps from the CIELab images: */
memset (homo, , * TS * TS);
for (row = top + ; row < top + TS - && row < height; row++)
{
tr = row - top;
for (col = left + ; col < left + TS - && col < width; col++)
{
tc = col - left;
for (d = ; d < ; d++)
for (i = ; i < ; i++)
ldiff[d][i] = ABS(lab[d][tr][tc][] - lab[d][tr][tc+dir[i]][]);
leps = MIN(MAX(ldiff[][], ldiff[][]),
MAX(ldiff[][], ldiff[][]));
for (d = ; d < ; d++)
for (i = ; i < ; i++)
if (i >> == d || ldiff[d][i] <= leps)
abdiff[d][i] = SQR(lab[d][tr][tc][] - lab[d][tr][tc+dir[i]][])
+ SQR(lab[d][tr][tc][] - lab[d][tr][tc+dir[i]][]);
abeps = MIN(MAX(abdiff[][], abdiff[][]),
MAX(abdiff[][], abdiff[][]));
for (d = ; d < ; d++)
for (i = ; i < ; i++)
if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
homo[d][tr][tc]++;
}
}
/* Combine the most homogenous pixels for the final result: */
for (row = top + ; row < top + TS - && row < height - ; row++)
{
tr = row - top;
for (col = left + ; col < left + TS - && col < width - ; col++)
{
tc = col - left;
for (d = ; d < ; d++)
for (hm[d] = , i = tr - ; i <= tr + ; i++)
for (j = tc - ; j <= tc + ; j++)
hm[d] += homo[d][i][j];
if (hm[] != hm[])
FORC3 dst[(row*width+col)* + c] = CLIPOUT16(rgb[hm[] > hm[]][tr][tc][c], bits); /* [SA] */
else
FORC3 dst[(row*width+col)* + c] =
CLIPOUT16((rgb[][tr][tc][c] + rgb[][tr][tc][c]) >> , bits); /* [SA] */
}
}
}
free (buffer); return DC1394_SUCCESS;
} dc1394error_t dc1394_bayer_decoding_8bit(const uint8_t *restrict bayer, uint8_t *restrict rgb, uint32_t sx, uint32_t sy, dc1394color_filter_t tile, dc1394bayer_method_t method)
{
switch (method)
{
case DC1394_BAYER_METHOD_NEAREST:
return dc1394_bayer_NearestNeighbor(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_SIMPLE:
return dc1394_bayer_Simple(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_BILINEAR:
return dc1394_bayer_Bilinear(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_HQLINEAR:
return dc1394_bayer_HQLinear(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_DOWNSAMPLE:
return dc1394_bayer_Downsample(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_EDGESENSE:
return dc1394_bayer_EdgeSense(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_VNG:
return dc1394_bayer_VNG(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_AHD:
return dc1394_bayer_AHD(bayer, rgb, sx, sy, tile);
default:
return DC1394_INVALID_BAYER_METHOD;
} } dc1394error_t dc1394_bayer_decoding_16bit(const uint16_t *restrict bayer, uint16_t *restrict rgb, uint32_t sx, uint32_t sy, dc1394color_filter_t tile, dc1394bayer_method_t method, uint32_t bits)
{
switch (method)
{
case DC1394_BAYER_METHOD_NEAREST:
return dc1394_bayer_NearestNeighbor_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_SIMPLE:
return dc1394_bayer_Simple_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_BILINEAR:
return dc1394_bayer_Bilinear_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_HQLINEAR:
return dc1394_bayer_HQLinear_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_DOWNSAMPLE:
return dc1394_bayer_Downsample_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_EDGESENSE:
return dc1394_bayer_EdgeSense_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_VNG:
return dc1394_bayer_VNG_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_AHD:
return dc1394_bayer_AHD_uint16(bayer, rgb, sx, sy, tile, bits);
default:
return DC1394_INVALID_BAYER_METHOD;
} } #if 0
dc1394error_t Adapt_buffer_bayer(dc1394video_frame_t *in, dc1394video_frame_t *out, dc1394bayer_method_t method)
{
uint32_t bpp; // conversions will halve the buffer size if the method is DOWNSAMPLE:
out->size[] = in->size[];
out->size[] = in->size[];
if (method == DC1394_BAYER_METHOD_DOWNSAMPLE)
{
out->size[] /= ; // ODD SIZE CASES NOT TAKEN INTO ACCOUNT
out->size[] /= ;
} // as a convention we divide the image position by two in the case of a DOWNSAMPLE:
out->position[] = in->position[];
out->position[] = in->position[];
if (method == DC1394_BAYER_METHOD_DOWNSAMPLE)
{
out->position[] /= ;
out->position[] /= ;
} // the destination color coding is ALWAYS RGB. Set this.
if ( (in->color_coding == DC1394_COLOR_CODING_RAW16) ||
(in->color_coding == DC1394_COLOR_CODING_MONO16) )
out->color_coding = DC1394_COLOR_CODING_RGB16;
else
out->color_coding = DC1394_COLOR_CODING_RGB8; // keep the color filter value in all cases. If the format is not raw it will not be further used anyway
out->color_filter = in->color_filter; // The output is never YUV, hence nothing to do about YUV byte order // bit depth is conserved for 16 bit and set to 8bit for 8bit:
if ( (in->color_coding == DC1394_COLOR_CODING_RAW16) ||
(in->color_coding == DC1394_COLOR_CODING_MONO16) )
out->data_depth = in->data_depth;
else
out->data_depth = ; // don't know what to do with stride... >>>> TODO: STRIDE SHOULD BE TAKEN INTO ACCOUNT... <<<<
// out->stride=?? // the video mode should not change. Color coding and other stuff can be accessed in specific fields of this struct
out->video_mode = in->video_mode; // padding is kept:
out->padding_bytes = in->padding_bytes; // image bytes changes: >>>> TODO: STRIDE SHOULD BE TAKEN INTO ACCOUNT... <<<<
dc1394_get_color_coding_bit_size(out->color_coding, &bpp);
out->image_bytes = (out->size[] * out->size[] * bpp) / ; // total is image_bytes + padding_bytes
out->total_bytes = out->image_bytes + out->padding_bytes; // bytes-per-packet and packets_per_frame are internal data that can be kept as is.
out->packet_size = in->packet_size;
out->packets_per_frame = in->packets_per_frame; // timestamp, frame_behind, id and camera are copied too:
out->timestamp = in->timestamp;
out->frames_behind = in->frames_behind;
out->camera = in->camera;
out->id = in->id; // verify memory allocation:
if (out->total_bytes > out->allocated_image_bytes)
{
free(out->image);
out->image = (uint8_t *)malloc(out->total_bytes * sizeof(uint8_t));
if (out->image)
out->allocated_image_bytes = out->total_bytes * sizeof(uint8_t);
else
out->allocated_image_bytes = ;
} // Copy padding bytes:
if(out->image)
memcpy(&(out->image[out->image_bytes]), &(in->image[in->image_bytes]), out->padding_bytes); out->little_endian = ; // not used before 1.32 is out.
out->data_in_padding = ; // not used before 1.32 is out. if(out->image)
return DC1394_SUCCESS; return DC1394_MEMORY_ALLOCATION_FAILURE;
} dc1394error_t dc1394_debayer_frames(dc1394video_frame_t *in, dc1394video_frame_t *out, dc1394bayer_method_t method)
{
if ((method < DC1394_BAYER_METHOD_MIN) || (method > DC1394_BAYER_METHOD_MAX))
return DC1394_INVALID_BAYER_METHOD; switch (in->color_coding)
{
case DC1394_COLOR_CODING_RAW8:
case DC1394_COLOR_CODING_MONO8: if(DC1394_SUCCESS != Adapt_buffer_bayer(in, out, method))
return DC1394_MEMORY_ALLOCATION_FAILURE; switch (method)
{
case DC1394_BAYER_METHOD_NEAREST:
return dc1394_bayer_NearestNeighbor(in->image, out->image, in->size[], in->size[], in->color_filter);
case DC1394_BAYER_METHOD_SIMPLE:
return dc1394_bayer_Simple(in->image, out->image, in->size[], in->size[], in->color_filter);
case DC1394_BAYER_METHOD_BILINEAR:
return dc1394_bayer_Bilinear(in->image, out->image, in->size[], in->size[], in->color_filter);
case DC1394_BAYER_METHOD_HQLINEAR:
return dc1394_bayer_HQLinear(in->image, out->image, in->size[], in->size[], in->color_filter);
case DC1394_BAYER_METHOD_DOWNSAMPLE:
return dc1394_bayer_Downsample(in->image, out->image, in->size[], in->size[], in->color_filter);
case DC1394_BAYER_METHOD_EDGESENSE:
return dc1394_bayer_EdgeSense(in->image, out->image, in->size[], in->size[], in->color_filter);
case DC1394_BAYER_METHOD_VNG:
return dc1394_bayer_VNG(in->image, out->image, in->size[], in->size[], in->color_filter);
case DC1394_BAYER_METHOD_AHD:
return dc1394_bayer_AHD(in->image, out->image, in->size[], in->size[], in->color_filter);
}
break;
case DC1394_COLOR_CODING_MONO16:
case DC1394_COLOR_CODING_RAW16: if(DC1394_SUCCESS != Adapt_buffer_bayer(in, out, method))
return DC1394_MEMORY_ALLOCATION_FAILURE; switch (method)
{
case DC1394_BAYER_METHOD_NEAREST:
return dc1394_bayer_NearestNeighbor_uint16((uint16_t *)in->image, (uint16_t *)out->image, in->size[], in->size[], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_SIMPLE:
return dc1394_bayer_Simple_uint16((uint16_t *)in->image, (uint16_t *)out->image, in->size[], in->size[], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_BILINEAR:
return dc1394_bayer_Bilinear_uint16((uint16_t *)in->image, (uint16_t *)out->image, in->size[], in->size[], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_HQLINEAR:
return dc1394_bayer_HQLinear_uint16((uint16_t *)in->image, (uint16_t *)out->image, in->size[], in->size[], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_DOWNSAMPLE:
return dc1394_bayer_Downsample_uint16((uint16_t *)in->image, (uint16_t *)out->image, in->size[], in->size[], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_EDGESENSE:
return dc1394_bayer_EdgeSense_uint16((uint16_t *)in->image, (uint16_t *)out->image, in->size[], in->size[], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_VNG:
return dc1394_bayer_VNG_uint16((uint16_t *)in->image, (uint16_t *)out->image, in->size[], in->size[], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_AHD:
return dc1394_bayer_AHD_uint16((uint16_t *)in->image, (uint16_t *)out->image, in->size[], in->size[], in->color_filter, in->data_depth);
}
break;
default:
return DC1394_FUNCTION_NOT_SUPPORTED;
} return DC1394_SUCCESS;
}
#endif // bmp types: short = 3, int = 4
// Tags: ( 2-byte tag ) ( 2-byte type ) ( 4-byte count ) ( 4-byte data )
// 0100 0003 0000 0001 0064 0000
// | | | |
// tag --+ | | |
// short int -----+ | |
// one value ----------+ |
// value of 100 -----------------+
//
#define TIFF_HDR_NUM_ENTRY 8
#define TIFF_HDR_SIZE 10+TIFF_HDR_NUM_ENTRY*12
uint8_t tiff_header[TIFF_HDR_SIZE] =
{
// I I 42
0x49, 0x49, 0x2a, 0x00,
// ( offset to tags, 0 )
0x08, 0x00, 0x00, 0x00,
// ( num tags )
0x08, 0x00,
// ( newsubfiletype, 0 full-image )
0xfe, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// ( image width )
0x00, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// ( image height )
0x01, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// ( bits per sample )
0x02, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// ( Photometric Interpretation, 2 = RGB )
0x06, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
// ( Strip offsets, 8 )
0x11, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
// ( samples per pixel, 3 - RGB)
0x15, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
// ( Strip byte count )
0x17, 0x01, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
uint8_t *put_tiff(uint8_t *rgb, uint32_t width, uint32_t height, uint16_t bpp)
{
uint32_t ulTemp = ;
uint16_t sTemp = ;
printf("%s\n", __func__);
memcpy(rgb, tiff_header, TIFF_HDR_SIZE); sTemp = TIFF_HDR_NUM_ENTRY;
memcpy(rgb + , &sTemp, ); memcpy(rgb + + * + , &width, );
memcpy(rgb + + * + , &height, );
memcpy(rgb + + * + , &bpp, ); // strip byte count
ulTemp = width * height * (bpp / ) * ;
memcpy(rgb + + * + , &ulTemp, ); //strip offset
sTemp = TIFF_HDR_SIZE;
memcpy(rgb + + * + , &sTemp, );
return rgb + TIFF_HDR_SIZE;
}; #define ALIGN(x, n) (((x)+(n)-1)&~((n)-1))
typedef struct
{
unsigned short bfType; /* 说明文件的类型 */
unsigned int bfSize; /* 说明文件的大小,用字节为单位 */
unsigned short bfReserved1; /* 保留,设置为0 */
unsigned short bfReserved2; /* 保留,设置为0 */
unsigned int bfOffsetBytes; /* 说明从BITMAPFILEHEADER结构开始到实际的图像数据之间的字节偏移量 */
}__attribute__((gcc_struct, packed)) bfh_t; //14字节,但是sizeof计算长度时为16字节 typedef struct
{
unsigned int biSize; /* 说明结构体所需字节数 */
unsigned int biWidth; /* 以像素为单位说明图像的宽度 */
unsigned int biHeight; /* 以像素为单位说明图像的高度 */
unsigned short biPlanes; /* 说明位面数,必须为1 */
unsigned short biBitCount; /* 说明位数/像素,1、2、4、8、24 */
unsigned int biCompression; /* 说明图像是否压缩及压缩类型BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS */
unsigned int biSizeImage; /* 以字节为单位说明图像大小,必须是4的整数倍*/
unsigned int biXPixelsPerMeter; /*目标设备的水平分辨率,像素/米 */
unsigned int biYPixelsPerMeter; /*目标设备的垂直分辨率,像素/米 */
unsigned int biClrUsed; /* 说明图像实际用到的颜色数,如果为0,则颜色数为2的biBitCount次方 */
unsigned int biClrImportant; /*说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。*/
}__attribute__((gcc_struct, packed)) bhi_t; //40字节 int put_bmp_hdr(unsigned char *base, uint32_t w, uint32_t h)
{
bfh_t *bfh_out = base;
bhi_t *bhi_out = base + sizeof(bfh_t); bfh_out->bfType = 0x4d42;
bfh_out->bfSize = ALIGN(w*, ) * h + ;
bfh_out->bfReserved1 = ;
bfh_out->bfReserved2 = ;
bfh_out->bfOffsetBytes = ;
bhi_out->biSize = ;
bhi_out->biWidth = w;
bhi_out->biHeight = h;
bhi_out->biPlanes = ;
bhi_out->biBitCount = ;
bhi_out->biCompression = ;
bhi_out->biSizeImage = ALIGN(w*, ) * h;
bhi_out->biXPixelsPerMeter = ;
bhi_out->biYPixelsPerMeter = ;
bhi_out->biClrUsed = ;
bhi_out->biClrImportant = ;
return ;
} dc1394bayer_method_t getMethod(char *m)
{
if( strcmp(m, "NEAREST") == )
return DC1394_BAYER_METHOD_NEAREST;
if( strcmp(m, "SIMPLE") == )
return DC1394_BAYER_METHOD_SIMPLE;
if( strcmp(m, "BILINEAR") == )
return DC1394_BAYER_METHOD_BILINEAR;
if( strcmp(m, "HQLINEAR") == )
return DC1394_BAYER_METHOD_HQLINEAR;
if( strcmp(m, "DOWNSAMPLE") == )
return DC1394_BAYER_METHOD_DOWNSAMPLE;
if( strcmp(m, "EDGESENSE") == )
return DC1394_BAYER_METHOD_EDGESENSE;
if( strcmp(m, "VNG") == )
return DC1394_BAYER_METHOD_VNG;
if( strcmp(m, "AHD") == )
return DC1394_BAYER_METHOD_AHD; printf("WARNING: Unrecognized method \"%s\", defaulting to BILINEAR\n", m);
return DC1394_BAYER_METHOD_BILINEAR;
} dc1394color_filter_t getFirstColor(char *f)
{
if( strcmp(f, "RGGB") == )
return DC1394_COLOR_FILTER_RGGB;
if( strcmp(f, "GBRG") == )
return DC1394_COLOR_FILTER_GBRG;
if( strcmp(f, "GRBG") == )
return DC1394_COLOR_FILTER_GRBG;
if( strcmp(f, "BGGR") == )
return DC1394_COLOR_FILTER_BGGR; printf("WARNING: Unrecognized first color \"%s\", defaulting to RGGB\n", f);
return DC1394_COLOR_FILTER_RGGB;
} void usage( char *name )
{
printf("usage: %s\n", name);
printf(" --input,-i input file\n");
printf(" --output,-o output file\n");
printf(" --width,-w image width (pixels)\n");
printf(" --height,-v image height (pixels)\n");
printf(" --bpp,-b bits per pixel\n");
printf(" --first,-f first pixel color: RGGB, GBRG, GRBG, BGGR\n");
printf(" --method,-m interpolation method: NEAREST, SIMPLE, BILINEAR, HQLINEAR, DOWNSAMPLE, EDGESENSE, VNG, AHD\n");
printf(" --bmp,-t add a bmp header\n");
printf(" --swap,-s if bpp == 16, swap byte order before conversion\n");
printf(" --help,-h this helpful message\n");
} int main( int argc, char **argv )
{
int in_size = , out_size = , width = , height = , bpp = ;
int first_color = DC1394_COLOR_FILTER_RGGB;
int bmp = ;
int method = DC1394_BAYER_METHOD_BILINEAR;
char *infile = NULL, *outfile = NULL;
FILE *input_fd = NULL;
FILE *output_fd = NULL;
void *bayer = NULL;
void *rgb_buf = NULL, *out_buf = NULL;
char c;
int optidx = ;
int swap = ; struct option longopt[] =
{
{"input", , NULL, 'i'},
{"output", , NULL, 'o'},
{"width", , NULL, 'w'},
{"height", , NULL, 'v'},
{"help", , NULL, 'h'},
{"bpp", , NULL, 'b'},
{"first", , NULL, 'f'},
{"method", , NULL, 'm'},
{"bmp", , NULL, 't'},
{"swap", , NULL, 's'},
{, , , }
}; while ((c = getopt_long(argc, argv, "i:o:w:v:b:f:m:ths", longopt, &optidx)) != -)
{
switch ( c )
{
case 'i':
infile = strdup( optarg );
break;
case 'o':
outfile = strdup( optarg );
break;
case 'w':
width = strtol( optarg, NULL, );
break;
case 'v':
height = strtol( optarg, NULL, );
break;
case 'b':
bpp = strtol( optarg, NULL, );
break;
case 'f':
first_color = getFirstColor( optarg );
break;
case 'm':
method = getMethod( optarg );
break;
case 's':
swap = ;
break;
case 't':
bmp = ;
break;
case 'h':
usage(argv[]);
return ;
break;
default:
printf("bad arg\n");
usage(argv[]);
return ;
}
}
if( infile == NULL || outfile == NULL || bpp == || width == || height == )
{
printf("Bad parameter\n");
usage(argv[]);
return ;
}
input_fd = fopen(infile, "rw+b");
if(input_fd < )
{
printf("Problem opening input: %s\n", infile);
return ;
}
output_fd = fopen(outfile, "w+b");
if(output_fd < )
{
printf("Problem opening output: %s\n", outfile);
return ;
}
fseek(input_fd, , SEEK_END);
in_size = ftell(input_fd);
fseek(input_fd, , SEEK_SET);
if(in_size <= )
{
printf("%s@%d lseek %d err, cur %d errno %d\n", __func__, __LINE__, in_size, lseek(input_fd, 0L, SEEK_CUR), errno);
return -;
} out_size = width * height * (bpp / ) * + bmp;
bayer = malloc(in_size);
if(bayer == NULL)
{
printf("%s@%d malloc(%d) err\n", __func__, __LINE__, in_size);
return -;
}
if ((fread(bayer, , in_size, input_fd)) < in_size)
{
printf("%s@%d err\n", __func__, __LINE__);
return -;
}
out_buf = rgb_buf = malloc(out_size);
if(bmp) rgb_buf += bmp;
if(out_buf == NULL)
{
printf("%s@%d malloc(%d) err\n", __func__, __LINE__, out_size);
return -;
}
if(bmp)
{
put_bmp_hdr(out_buf, width, height);
}
switch(bpp)
{
case :
dc1394_bayer_decoding_8bit((const uint8_t *)bayer, (uint8_t *)rgb_buf, width, height, first_color, method);
break;
case :
default:
if(swap)
{
uint8_t tmp = ;
uint32_t i = ;
for(i = ; i < in_size; i += )
{
tmp = *(((uint8_t *)bayer) + i);
*(((uint8_t *)bayer) + i) = *(((uint8_t *)bayer) + i + );
*(((uint8_t *)bayer) + i + ) = tmp;
}
}
dc1394_bayer_decoding_16bit((const uint16_t *)bayer, (uint16_t *)rgb_buf, width, height, first_color, method, bpp);
break;
}
if ((fwrite(out_buf, , out_size, output_fd)) == )
{
printf("%s@%d err\n", __func__, __LINE__);
return -;
} free(bayer);
free(out_buf); fclose(input_fd);
fclose(output_fd); return ;
}
bayer2bmp的更多相关文章
随机推荐
- Noip2016Day1T2 天天爱跑步
题目链接 problem solution 这是一道一个顶六个的好题!!! 说一下各档部分分怎么写吧. 先看一下\(S_i=1\)和\(T_i=1\)的部分分怎么写. 如果\(S_i=1\) 当且仅当 ...
- golang--redis连接池
通过golang对redis操作,还可以通过redis连接池,流程如下: (1)事先初始化一定数量的连接,投入到连接池: (2)当go需要操作redis时,直接从连接池取出连接即可: (3)这样可以节 ...
- linux下使用mv将递归的文件从多个目录移动到一个目录中
find /data/download/temp \( -iname '*.mp4' -o -iname '*.avi' \) -type f -exec mv -nv -t '/data/downl ...
- C#排序案例
using System; namespace 排序案例 { class Program { static void Main(string[] args) { //定义随机数列 int a, b, ...
- MySQL学习——约束
MySQL学习——约束 摘要:本文主要学习了数据库的约束. primary key(主键) 定义 主键约束是一个列或者多个列,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可以强制 ...
- C# virtual 和 abstract 区别
Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类实例 ...
- uni-app学习(三)好用的插件1
1. uni-app学习(三) 1.1. async/await使用 表示异步处理,可使用then函数继续操作,返回的是Promise async function timeout() { retur ...
- MYSQL 复制整个数据库
同一个服务器 mysqldump old -u root -p123456 | mysql new -u root -p123456 不同服务器(在源数据库服务器上执行) mysqldump old ...
- 顺F分享,你是在裸奔吗?
" 对顺F旗下各APP顺藤摸瓜分析--顺F分享." 前文对顺F速运和顺F速运国际版进行了分析,二者使用同一套接口,虽然保护强度不高,但对代码和数据的保护却区别对待,实在让人诧异. ...
- RSA加密算法破解及原理
- RSA算法原理 - - 加密与解密 在RSA中,Bob想给Alice发一个消息X,Alice公钥为(e,n),私钥为(n,d). 加密和解密的过程如下: - RSA暴力破解 RSA暴力破解,简单理 ...