From 05c45874b50cd4a7d43be50ca377d0a41f8177f7 Mon Sep 17 00:00:00 2001 From: motz Date: Sun, 12 Jan 2020 13:14:34 +0100 Subject: [PATCH 01/16] Comma separated file for Gnuplot --- README.md | 10 ++++++++++ lens_shading_analyse.c | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) mode change 100755 => 100644 lens_shading_analyse.c diff --git a/README.md b/README.md index a6db215..79c4f39 100644 --- a/README.md +++ b/README.md @@ -32,3 +32,13 @@ and vcsm_free(state.lens_shading); ``` when finished. + +ls_table.txt is a comma separated file for easy visualization with Gnuplot. For a colored plot of all samples: +``` +set palette defined (0 "red", 1 "yellow", 2 "magenta", 3 "blue") +splot "ls_table.txt" using 1:2:3:4 w p ps 0.75 pt 7 lc palette z notitle +``` +Single sample plot ($4==0 => red): +``` +splot "ls_table.txt" using 1:2:($4==0?$3:1/0) +``` diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c old mode 100755 new mode 100644 index 1710263..c9f8300 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -125,7 +125,7 @@ uint16_t black_level_correct(uint16_t raw_pixel, unsigned int black_level, unsig int main(int argc, char *argv[]) { int in = 0; - FILE *out, *header; + FILE *out, *header, *table; int i, x, y; uint16_t *out_buf[NUM_CHANNELS]; void *mmap_buf; @@ -260,6 +260,7 @@ int main(int argc, char *argv[]) printf("Save data. Bayer order is %d\n", bayer_order); header = fopen("ls_table.h", "wb"); + table = fopen("ls_table.txt", "wb"); fprintf(header, "uint8_t ls_grid[] = {\n"); for (i=0; i Date: Sun, 12 Jan 2020 13:16:48 +0100 Subject: [PATCH 02/16] Add variables for grid size --- lens_shading_analyse.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index c9f8300..bf425bc 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -134,6 +134,7 @@ int main(int argc, char *argv[]) int bayer_order; struct brcm_raw_header *hdr; int width, height, stride; + int grid_width, grid_height; int single_channel_width, single_channel_height; unsigned int black_level = 16; @@ -208,6 +209,10 @@ int main(int argc, char *argv[]) height = hdr->height; single_channel_width = width/2; single_channel_height = height/2; + grid_width = single_channel_width / 32 + (single_channel_width % 32 == 0 ? 0 : 1); + grid_height = single_channel_height / 32 + (single_channel_height % 32 == 0 ? 0 : 1); + printf("Grid size: %d x %d\n", grid_width, grid_height); + //Stride computed via same formula as the firmware uses. stride = (((((width + hdr->padding_right)*5)+3)>>2) + 31)&(~31); @@ -340,8 +345,8 @@ int main(int argc, char *argv[]) } fprintf(header, "};\n"); fprintf(header, "uint32_t ref_transform = %u;\n", hdr->transform); - fprintf(header, "uint32_t grid_width = %u;\n", (single_channel_width>>5)+1); - fprintf(header, "uint32_t grid_height = %u;\n", (single_channel_height>>5)+1); + fprintf(header, "uint32_t grid_width = %u;\n", grid_width); + fprintf(header, "uint32_t grid_height = %u;\n", grid_height); for (i=0; i Date: Sun, 12 Jan 2020 13:21:57 +0100 Subject: [PATCH 03/16] Averaging over the entire grid cell --- lens_shading_analyse.c | 45 ++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index bf425bc..fe575de 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -310,35 +310,32 @@ int main(int argc, char *argv[]) fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]); uint16_t *line; - for (y=16; y=single_channel_height) - line = &channel[(single_channel_height-1)*(single_channel_width)]; - else - line = &channel[y*(single_channel_width)]; - - for(x=16; x 255) - gain = 255; //Clip as uint8_t + gain = 255; //Clip as uint8_t else if (gain < 32) - gain = 32; //Clip at x1.0 + gain = 32; //Clip at x1.0 fprintf(header, "%d, ", gain ); - fprintf(table, "%d %d %d %d\n", x, y, gain, i ); - } - //Compute edge value from the very edge 2 pixels. - { - int avg = line[single_channel_width-2] + line[single_channel_width-1]; - int gain = (middle_val*2) / avg; - if (gain > 255) - gain = 255; //Clip as uint8_t - else if (gain < 32) - gain = 32; //Clip at x1.0 - fprintf(header, "%d,\n", gain ); - fprintf(table, "%d %d %d %d\n", x, y, gain, i ); + fprintf(table, "%d %d %d %d\n", x * 32 + 16, y * 32 + 16, gain, i ); } } From a88923508d4697c979d047902a7128dd33808a83 Mon Sep 17 00:00:00 2001 From: motz Date: Sun, 12 Jan 2020 14:24:17 +0100 Subject: [PATCH 04/16] Read sensor model from the RAW header and set appropriate black level --- lens_shading_analyse.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index fe575de..a5b9a56 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -136,7 +136,7 @@ int main(int argc, char *argv[]) int width, height, stride; int grid_width, grid_height; int single_channel_width, single_channel_height; - unsigned int black_level = 16; + unsigned int black_level = 0; if (argc < 2) { @@ -194,6 +194,28 @@ int main(int argc, char *argv[]) goto unmap; } + char model[ 7 ]; + memcpy( model, &in_buf[ 16 ], 6 ); + model[ 6 ] = '\0'; + if (strncmp(model, "imx219", 6) == 0) + { + printf("Sensor type: %s\n", model); + if (black_level == 0) + { + black_level = 66; + } + } else if (strncmp(model, "ov5647", 6) == 0) + { + printf("Sensor type: %s\n", model); + if (black_level == 0) + { + black_level = 16; + } + } else if (black_level == 0 ){ + black_level = 16; // Default value + } + printf( "Black level: %d\n", black_level ); + hdr = (struct brcm_raw_header*) (in_buf+0xB0); printf("Header decoding: mode %s, width %u, height %u, padding %u %u\n", hdr->name, hdr->width, hdr->height, hdr->padding_right, hdr->padding_down); From 0f526c75f59ee216035b5c9faf6723064866cee3 Mon Sep 17 00:00:00 2001 From: motz Date: Sun, 12 Jan 2020 15:57:42 +0100 Subject: [PATCH 05/16] Lens shading table binary output --- lens_shading_analyse.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index a5b9a56..d1901ff 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -125,7 +125,7 @@ uint16_t black_level_correct(uint16_t raw_pixel, unsigned int black_level, unsig int main(int argc, char *argv[]) { int in = 0; - FILE *out, *header, *table; + FILE *out, *header, *table, *bin; int i, x, y; uint16_t *out_buf[NUM_CHANNELS]; void *mmap_buf; @@ -134,7 +134,7 @@ int main(int argc, char *argv[]) int bayer_order; struct brcm_raw_header *hdr; int width, height, stride; - int grid_width, grid_height; + uint32_t grid_width, grid_height; int single_channel_width, single_channel_height; unsigned int black_level = 0; @@ -288,6 +288,11 @@ int main(int argc, char *argv[]) header = fopen("ls_table.h", "wb"); table = fopen("ls_table.txt", "wb"); + bin = fopen("ls.bin", "wb"); + uint32_t transform = hdr->transform; + fwrite(&transform, sizeof(uint32_t), 1, bin); + fwrite(&grid_width, sizeof(uint32_t), 1, bin); + fwrite(&grid_height, sizeof(uint32_t), 1, bin); fprintf(header, "uint8_t ls_grid[] = {\n"); for (i=0; i Date: Tue, 21 Jan 2020 13:45:04 +0100 Subject: [PATCH 06/16] Search the brightest area in the image --- lens_shading_analyse.c | 53 +++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index d1901ff..ddc2442 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -316,27 +316,48 @@ int main(int argc, char *argv[]) uint16_t *channel = out_buf[channel_ordering[bayer_order][i]]; int mid_value_avg = 0; int count = 0; - //Average out the centre 64 pixels. - for (x=(single_channel_width>>1)-4; x<=(single_channel_width>>1)+4; x++) - { - for (y=(single_channel_height>>1)-4; y<=(single_channel_height>>1)+4; y++) - { - mid_value_avg += channel[x + y*single_channel_width]; - count++; - } - } - uint16_t middle_val = (mid_value_avg / count) << 5; - + uint16_t *line; const char *channel_comments[4] = { "R", "Gr", "Gb", "B" - }; - printf("Middle_val is %d\n", middle_val); + }; + + // Search highest value + float max_val = 0; + for (y=0; y max_val){ + max_val = block_val; + } + } + } + + max_val *= 32; + printf("Max_val is %.0f\n", max_val); fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]); - uint16_t *line; + + // Calculate gain for each block for (y=0; y 255) gain = 255; //Clip as uint8_t else if (gain < 32) - gain = 32; //Clip at x1.0 + gain = 32; //Clip at x1.0, should never happen fprintf(header, "%d, ", gain ); fprintf(table, "%d %d %d %d\n", x * 32 + 16, y * 32 + 16, gain, i ); uint8_t gain_bin = gain; From c0f38775a0bbf835362187c13d3d9c216761dc50 Mon Sep 17 00:00:00 2001 From: Moritz Eheim Date: Tue, 21 Jan 2020 18:07:55 +0100 Subject: [PATCH 07/16] fix indentation --- lens_shading_analyse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index ddc2442..0792e25 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -209,7 +209,7 @@ int main(int argc, char *argv[]) printf("Sensor type: %s\n", model); if (black_level == 0) { - black_level = 16; + black_level = 16; } } else if (black_level == 0 ){ black_level = 16; // Default value From b2a950e8f8a74e3e918f1ede12370e143f8ebce9 Mon Sep 17 00:00:00 2001 From: Moritz Eheim Date: Tue, 21 Jan 2020 18:20:07 +0100 Subject: [PATCH 08/16] Changed calculation of grid_width and grid_height to initial method --- lens_shading_analyse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index 0792e25..d95a2ae 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -231,8 +231,8 @@ int main(int argc, char *argv[]) height = hdr->height; single_channel_width = width/2; single_channel_height = height/2; - grid_width = single_channel_width / 32 + (single_channel_width % 32 == 0 ? 0 : 1); - grid_height = single_channel_height / 32 + (single_channel_height % 32 == 0 ? 0 : 1); + grid_width = (single_channel_width + 31) / 32; + grid_height = (single_channel_height + 31) / 32; printf("Grid size: %d x %d\n", grid_width, grid_height); //Stride computed via same formula as the firmware uses. From f290689ba81fdf565b91831fc26d8b388155ef0c Mon Sep 17 00:00:00 2001 From: motz Date: Thu, 23 Jan 2020 19:48:55 +0100 Subject: [PATCH 09/16] Removed double calculation loop, added parameters for cell size --- lens_shading_analyse.c | 74 ++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index d95a2ae..425b12f 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -134,13 +134,15 @@ int main(int argc, char *argv[]) int bayer_order; struct brcm_raw_header *hdr; int width, height, stride; - uint32_t grid_width, grid_height; + uint32_t grid_width, grid_height, block_px_max; int single_channel_width, single_channel_height; unsigned int black_level = 0; + uint32_t *block_sum; + uint8_t block_size = 4; if (argc < 2) { - printf("%s [black level]\n", argv[0]); + printf("%s [black level] [avg square size]\n", argv[0]); return -1; } @@ -154,6 +156,17 @@ int main(int argc, char *argv[]) { black_level = strtoul(argv[2], NULL, 10); } + if (argc >= 4) + { + block_size = strtoul(argv[3], NULL, 10); + if (block_size<=0 || block_size>32) { + printf("Length of the square for calculation must be between 2 and 32 in size and a multiple of 2\n"); + return -1; + } else if (block_size%2 == 1) + { + block_size++; + } + } fstat(in, &sb); printf("File size is %ld\n", sb.st_size); @@ -233,6 +246,8 @@ int main(int argc, char *argv[]) single_channel_height = height/2; grid_width = (single_channel_width + 31) / 32; grid_height = (single_channel_height + 31) / 32; + block_px_max = block_size*block_size; + block_sum = (uint32_t *)malloc(sizeof(uint32_t) * grid_width * grid_height); printf("Grid size: %d x %d\n", grid_width, grid_height); //Stride computed via same formula as the firmware uses. @@ -324,18 +339,28 @@ int main(int argc, char *argv[]) "B" }; - // Search highest value - float max_val = 0; + // Calculate sum for each block + uint16_t block_idx = 0; + uint32_t max_val = 0; for (y=0; y= single_channel_height) + y_start = single_channel_height-1; + int y_stop = y_start+block_size; + if (y_stop > single_channel_height) + y_stop = single_channel_height; + for (x=0; x= single_channel_width) + x_start = single_channel_width-1; + int x_stop = x_start+block_size; + if (x_stop > single_channel_width) + x_stop = single_channel_width; + + uint32_t block_val = 0; uint16_t block_px = 0; for(int y_px = y_start; y_px < y_stop; y_px++){ @@ -345,39 +370,26 @@ int main(int argc, char *argv[]) block_px++; } } + if (block_px < block_px_max) + block_val = block_val * block_px_max / block_px; // Scale sum in case of small edge blocks - block_val /= block_px; - if(block_val > max_val){ + block_sum[block_idx++] = block_val; + if (block_val > max_val) max_val = block_val; - } } } - max_val *= 32; - printf("Max_val is %.0f\n", max_val); + max_val <<= 5; + printf("Max_val is %d\n", max_val); fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]); // Calculate gain for each block + block_idx = 0; for (y=0; y 255) gain = 255; //Clip as uint8_t else if (gain < 32) From 22f3acf576c2ba436ae08b386c5945b41b25f9d4 Mon Sep 17 00:00:00 2001 From: hasepompase Date: Fri, 7 Feb 2020 17:10:19 +0100 Subject: [PATCH 10/16] Add getop parameter parsing and help text output --- lens_shading_analyse.c | 67 ++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index 425b12f..c206661 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -122,6 +122,24 @@ uint16_t black_level_correct(uint16_t raw_pixel, unsigned int black_level, unsig return ((raw_pixel - black_level) * max_value) / (max_value - black_level); } +void print_help( void ) +{ + printf( "\n" ); + printf( "\n" ); + printf( "\"lens_shading_analyse\" Lens shading analysis tool\n" ); + printf( "\n" ); + printf( "Analyzes the lens shading based on a raw image\n" ); + printf( "\n" ); + printf( "usage: lens_shading_analyse -i [options]\n" ); + printf( "\n" ); + printf( "Parameters\n" ); + printf( "\n" ); + printf( "-i : Raw image file (mandatory)\n" ); + printf( "-b : Black level\n" ); + printf( "-s : Size of the analysis cell. Minimum 2, maximum 32, default 4\n" ); + printf( "\n" ); +} + int main(int argc, char *argv[]) { int in = 0; @@ -142,29 +160,42 @@ int main(int argc, char *argv[]) if (argc < 2) { - printf("%s [black level] [avg square size]\n", argv[0]); + print_help(); return -1; } - in = open(argv[1], O_RDONLY); - if (in < 0) - { - printf("Failed to open %s\n", argv[1]); - return -1; - } - if (argc >= 3) - { - black_level = strtoul(argv[2], NULL, 10); - } - if (argc >= 4) + int nArg; + while ((nArg = getopt(argc, argv, "b:i:s:")) != -1) { - block_size = strtoul(argv[3], NULL, 10); - if (block_size<=0 || block_size>32) { - printf("Length of the square for calculation must be between 2 and 32 in size and a multiple of 2\n"); + switch( nArg ) { + case 'b': + black_level = strtoul(optarg, NULL, 10); + break; + case 'i': + in = open(optarg, O_RDONLY); + if (in < 0) + { + printf("Failed to open %s\n", argv[1]); + return -1; + } + break; + case 's': + block_size = strtoul(optarg, NULL, 10); + if (block_size<=0 || block_size>32) + { + printf("Analysis cell out of range\n"); + return -1; + } + else if (block_size%2 == 1) + { + block_size++; + } + break; + default: + case 'h': + print_help(); return -1; - } else if (block_size%2 == 1) - { - block_size++; + break; } } From 5252078d6e65e552748609c8c21f5395dd6675e6 Mon Sep 17 00:00:00 2001 From: hasepompase Date: Fri, 7 Feb 2020 17:22:04 +0100 Subject: [PATCH 11/16] Add output format parameter --- lens_shading_analyse.c | 109 +++++++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 31 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index c206661..63ec390 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -137,6 +137,11 @@ void print_help( void ) printf( "-i : Raw image file (mandatory)\n" ); printf( "-b : Black level\n" ); printf( "-s : Size of the analysis cell. Minimum 2, maximum 32, default 4\n" ); + printf( "-o : Output format. Formats can be output together, for example 3 = 1 + 2\n" ); + printf( " 1 : Header file (default on)\n" ); + printf( " 2 : Binary file\n" ); + printf( " 4 : Text file\n" ); + printf( " 8 : Channel data\n" ); printf( "\n" ); } @@ -157,6 +162,7 @@ int main(int argc, char *argv[]) unsigned int black_level = 0; uint32_t *block_sum; uint8_t block_size = 4; + uint8_t out_frmt = 1; if (argc < 2) { @@ -165,7 +171,7 @@ int main(int argc, char *argv[]) } int nArg; - while ((nArg = getopt(argc, argv, "b:i:s:")) != -1) + while ((nArg = getopt(argc, argv, "b:i:o:s:")) != -1) { switch( nArg ) { case 'b': @@ -179,6 +185,14 @@ int main(int argc, char *argv[]) return -1; } break; + case 'o': + out_frmt = strtoul(optarg, NULL, 10); + if (!out_frmt & 0x0F) + { + printf("Invalid output format\n"); + return -1; + } + break; case 's': block_size = strtoul(optarg, NULL, 10); if (block_size<=0 || block_size>32) @@ -332,30 +346,48 @@ int main(int argc, char *argv[]) printf("Save data. Bayer order is %d\n", bayer_order); - header = fopen("ls_table.h", "wb"); - table = fopen("ls_table.txt", "wb"); - bin = fopen("ls.bin", "wb"); - uint32_t transform = hdr->transform; - fwrite(&transform, sizeof(uint32_t), 1, bin); - fwrite(&grid_width, sizeof(uint32_t), 1, bin); - fwrite(&grid_height, sizeof(uint32_t), 1, bin); - fprintf(header, "uint8_t ls_grid[] = {\n"); + if(out_frmt&0x01) + { + header = fopen("ls_table.h", "wb"); + } + if(out_frmt&0x02) + { + bin = fopen("ls.bin", "wb"); + } + if(out_frmt&0x04) + { + table = fopen("ls_table.txt", "wb"); + } + if(out_frmt&0x01) + { + fprintf(header, "uint8_t ls_grid[] = {\n"); + } + if(out_frmt&0x02) + { + uint32_t transform = hdr->transform; + fwrite(&transform, sizeof(uint32_t), 1, bin); + fwrite(&grid_width, sizeof(uint32_t), 1, bin); + fwrite(&grid_height, sizeof(uint32_t), 1, bin); + } for (i=0; itransform); - fprintf(header, "uint32_t grid_width = %u;\n", grid_width); - fprintf(header, "uint32_t grid_height = %u;\n", grid_height); + if(out_frmt&0x01) + { + fprintf(header, "};\n"); + fprintf(header, "uint32_t ref_transform = %u;\n", hdr->transform); + fprintf(header, "uint32_t grid_width = %u;\n", grid_width); + fprintf(header, "uint32_t grid_height = %u;\n", grid_height); + } for (i=0; i Date: Fri, 7 Feb 2020 17:26:45 +0100 Subject: [PATCH 12/16] Fix format --- lens_shading_analyse.c | 52 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index 63ec390..7d25124 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -122,27 +122,27 @@ uint16_t black_level_correct(uint16_t raw_pixel, unsigned int black_level, unsig return ((raw_pixel - black_level) * max_value) / (max_value - black_level); } -void print_help( void ) +void print_help(void) { - printf( "\n" ); - printf( "\n" ); - printf( "\"lens_shading_analyse\" Lens shading analysis tool\n" ); - printf( "\n" ); - printf( "Analyzes the lens shading based on a raw image\n" ); - printf( "\n" ); - printf( "usage: lens_shading_analyse -i [options]\n" ); - printf( "\n" ); - printf( "Parameters\n" ); - printf( "\n" ); - printf( "-i : Raw image file (mandatory)\n" ); - printf( "-b : Black level\n" ); - printf( "-s : Size of the analysis cell. Minimum 2, maximum 32, default 4\n" ); - printf( "-o : Output format. Formats can be output together, for example 3 = 1 + 2\n" ); - printf( " 1 : Header file (default on)\n" ); - printf( " 2 : Binary file\n" ); - printf( " 4 : Text file\n" ); - printf( " 8 : Channel data\n" ); - printf( "\n" ); + printf("\n"); + printf("\n"); + printf("\"lens_shading_analyse\" Lens shading analysis tool\n"); + printf("\n"); + printf("Analyzes the lens shading based on a raw image\n"); + printf("\n"); + printf("usage: lens_shading_analyse -i [options]\n"); + printf("\n"); + printf("Parameters\n"); + printf("\n"); + printf("-i : Raw image file (mandatory)\n"); + printf("-b : Black level\n"); + printf("-s : Size of the analysis cell. Minimum 2, maximum 32, default 4\n"); + printf("-o : Output format. Formats can be output together, for example 3 = 1 + 2\n"); + printf(" 1 : Header file (default on)\n"); + printf(" 2 : Binary file\n"); + printf(" 4 : Text file\n"); + printf(" 8 : Channel data\n"); + printf("\n"); } int main(int argc, char *argv[]) @@ -173,7 +173,7 @@ int main(int argc, char *argv[]) int nArg; while ((nArg = getopt(argc, argv, "b:i:o:s:")) != -1) { - switch( nArg ) { + switch (nArg) { case 'b': black_level = strtoul(optarg, NULL, 10); break; @@ -252,9 +252,9 @@ int main(int argc, char *argv[]) goto unmap; } - char model[ 7 ]; - memcpy( model, &in_buf[ 16 ], 6 ); - model[ 6 ] = '\0'; + char model[7]; + memcpy(model, &in_buf[16], 6); + model[6] = '\0'; if (strncmp(model, "imx219", 6) == 0) { printf("Sensor type: %s\n", model); @@ -269,10 +269,10 @@ int main(int argc, char *argv[]) { black_level = 16; } - } else if (black_level == 0 ){ + } else if (black_level == 0){ black_level = 16; // Default value } - printf( "Black level: %d\n", black_level ); + printf("Black level: %d\n", black_level); hdr = (struct brcm_raw_header*) (in_buf+0xB0); printf("Header decoding: mode %s, width %u, height %u, padding %u %u\n", From 18d809e660c72ba5d98492d897ddad1bf338aa04 Mon Sep 17 00:00:00 2001 From: hasepompase Date: Sun, 9 Feb 2020 06:54:29 +0100 Subject: [PATCH 13/16] Fix format --- lens_shading_analyse.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index 7d25124..0d2a101 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -346,23 +346,23 @@ int main(int argc, char *argv[]) printf("Save data. Bayer order is %d\n", bayer_order); - if(out_frmt&0x01) + if (out_frmt&0x01) { header = fopen("ls_table.h", "wb"); } - if(out_frmt&0x02) + if (out_frmt&0x02) { bin = fopen("ls.bin", "wb"); } - if(out_frmt&0x04) + if (out_frmt&0x04) { table = fopen("ls_table.txt", "wb"); } - if(out_frmt&0x01) + if (out_frmt&0x01) { fprintf(header, "uint8_t ls_grid[] = {\n"); } - if(out_frmt&0x02) + if (out_frmt&0x02) { uint32_t transform = hdr->transform; fwrite(&transform, sizeof(uint32_t), 1, bin); @@ -371,7 +371,7 @@ int main(int argc, char *argv[]) } for (i=0; itransform); From b239de66f36b23346cdee30693e27aab673d89e8 Mon Sep 17 00:00:00 2001 From: hasepompase Date: Thu, 24 Jun 2021 20:48:50 +0200 Subject: [PATCH 14/16] Added support for HQ cam --- lens_shading_analyse.c | 829 ++++++++++++++++++++++------------------- 1 file changed, 446 insertions(+), 383 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index 0d2a101..80d2992 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -88,410 +88,473 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //This structure is at offset 0xB0 from the 'BRCM' ident. struct brcm_raw_header { - uint8_t name[32]; - uint16_t width; - uint16_t height; - uint16_t padding_right; - uint16_t padding_down; - uint32_t dummy[6]; - uint16_t transform; - uint16_t format; - uint8_t bayer_order; - uint8_t bayer_format; + uint8_t name[32]; + uint16_t width; + uint16_t height; + uint16_t padding_right; + uint16_t padding_down; + uint32_t dummy[6]; + uint16_t transform; + uint16_t format; + uint8_t bayer_order; + uint8_t bayer_format; }; //Values taken from https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h #define BRCM_FORMAT_BAYER 33 #define BRCM_BAYER_RAW10 3 +#define BRCM_BAYER_RAW12 4 enum bayer_order_t { - RGGB, - GBRG, - BGGR, - GRBG + RGGB, + GBRG, + BGGR, + GRBG }; const int channel_ordering[4][4] = { - { 0, 1, 2, 3 }, - { 2, 3, 0, 1 }, - { 3, 2, 1, 0 }, - { 1, 0, 3, 2 } + { 0, 1, 2, 3 }, + { 2, 3, 0, 1 }, + { 3, 2, 1, 0 }, + { 1, 0, 3, 2 } }; +uint8_t* sensor_model_check(int sensor_model, void* buffer, size_t size) +{ + uint8_t* in_buf = 0; + + switch(sensor_model) { + case 1: + in_buf = ((uint8_t*)buffer) + size - 6404096; + break; + case 2: + in_buf = ((uint8_t*)buffer) + size - 10270208; + break; + case 3: + in_buf = ((uint8_t*)buffer) + size - 18711040; + break; + default: + return 0; + break; + } + + if (memcmp(in_buf, "BRCM", 4) == 0) + { + return in_buf; + } + else + { + return 0; + } +} + uint16_t black_level_correct(uint16_t raw_pixel, unsigned int black_level, unsigned int max_value) { - return ((raw_pixel - black_level) * max_value) / (max_value - black_level); + return ((raw_pixel - black_level) * max_value) / (max_value - black_level); } void print_help(void) { - printf("\n"); - printf("\n"); - printf("\"lens_shading_analyse\" Lens shading analysis tool\n"); - printf("\n"); - printf("Analyzes the lens shading based on a raw image\n"); - printf("\n"); - printf("usage: lens_shading_analyse -i [options]\n"); - printf("\n"); - printf("Parameters\n"); - printf("\n"); - printf("-i : Raw image file (mandatory)\n"); - printf("-b : Black level\n"); - printf("-s : Size of the analysis cell. Minimum 2, maximum 32, default 4\n"); - printf("-o : Output format. Formats can be output together, for example 3 = 1 + 2\n"); - printf(" 1 : Header file (default on)\n"); - printf(" 2 : Binary file\n"); - printf(" 4 : Text file\n"); - printf(" 8 : Channel data\n"); - printf("\n"); + printf("\n"); + printf("\n"); + printf("\"lens_shading_analyse\" Lens shading analysis tool\n"); + printf("\n"); + printf("Analyzes the lens shading based on a raw image\n"); + printf("\n"); + printf("usage: lens_shading_analyse -i [options]\n"); + printf("\n"); + printf("Parameters\n"); + printf("\n"); + printf("-i : Raw image file (mandatory)\n"); + printf("-b : Black level\n"); + printf("-s : Size of the analysis cell. Minimum 2, maximum 32, default 4\n"); + printf("-o : Output format. Formats can be output together, for example 3 = 1 + 2\n"); + printf(" 1 : Header file (default on)\n"); + printf(" 2 : Binary file\n"); + printf(" 4 : Text file\n"); + printf(" 8 : Channel data\n"); + printf("\n"); } int main(int argc, char *argv[]) { - int in = 0; - FILE *out, *header, *table, *bin; - int i, x, y; - uint16_t *out_buf[NUM_CHANNELS]; - void *mmap_buf; - uint8_t *in_buf; - struct stat sb; - int bayer_order; - struct brcm_raw_header *hdr; - int width, height, stride; - uint32_t grid_width, grid_height, block_px_max; - int single_channel_width, single_channel_height; - unsigned int black_level = 0; - uint32_t *block_sum; - uint8_t block_size = 4; - uint8_t out_frmt = 1; - - if (argc < 2) - { - print_help(); - return -1; - } - - int nArg; - while ((nArg = getopt(argc, argv, "b:i:o:s:")) != -1) - { - switch (nArg) { - case 'b': - black_level = strtoul(optarg, NULL, 10); - break; - case 'i': - in = open(optarg, O_RDONLY); - if (in < 0) - { - printf("Failed to open %s\n", argv[1]); - return -1; - } - break; - case 'o': - out_frmt = strtoul(optarg, NULL, 10); - if (!out_frmt & 0x0F) - { - printf("Invalid output format\n"); - return -1; - } - break; - case 's': - block_size = strtoul(optarg, NULL, 10); - if (block_size<=0 || block_size>32) - { - printf("Analysis cell out of range\n"); - return -1; - } - else if (block_size%2 == 1) - { - block_size++; - } - break; - default: - case 'h': - print_help(); - return -1; - break; - } - } - - fstat(in, &sb); - printf("File size is %ld\n", sb.st_size); - - mmap_buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, in, 0); - if (mmap_buf == MAP_FAILED) - { - printf("mmap failed\n"); - goto close_file; - } - - if (!memcmp(mmap_buf, "\xff\xd8", 2)) - { - //JPEG+RAW - find the raw header - //Try the appropriate offsets for the full res modes - //of OV5647 and IMX219. Any other modes will need to be - //stripped down to the bare raw (inc header) before processing - in_buf = ((uint8_t*)mmap_buf) + sb.st_size - 6404096; - if (memcmp(in_buf, "BRCM", 4)) - { - //Failed on OV5647, try IMX219 - in_buf = ((uint8_t*)mmap_buf) + sb.st_size - 10270208; - if (memcmp(in_buf, "BRCM", 4)) - { - //Failed totally - reset to the start of the buffer - in_buf = (uint8_t*)mmap_buf; - } - } - } - else - { - in_buf = (uint8_t*)mmap_buf; - } - - if (strncmp(in_buf, "BRCM", 4)) - { - printf("Raw file missing BRCM header\n"); - goto unmap; - } - - char model[7]; - memcpy(model, &in_buf[16], 6); - model[6] = '\0'; - if (strncmp(model, "imx219", 6) == 0) - { - printf("Sensor type: %s\n", model); - if (black_level == 0) - { - black_level = 66; - } - } else if (strncmp(model, "ov5647", 6) == 0) - { - printf("Sensor type: %s\n", model); - if (black_level == 0) - { - black_level = 16; - } - } else if (black_level == 0){ - black_level = 16; // Default value - } - printf("Black level: %d\n", black_level); - - hdr = (struct brcm_raw_header*) (in_buf+0xB0); - printf("Header decoding: mode %s, width %u, height %u, padding %u %u\n", - hdr->name, hdr->width, hdr->height, hdr->padding_right, hdr->padding_down); - printf("transform %u, image format %u, bayer order %u, bayer format %u\n", - hdr->transform, hdr->format, hdr->bayer_order, hdr->bayer_format); - if (hdr->format != BRCM_FORMAT_BAYER || hdr->bayer_format != BRCM_BAYER_RAW10) - { - printf("Raw file is not Bayer raw10\n"); - goto unmap; - } - bayer_order = hdr->bayer_order; - width = hdr->width; - height = hdr->height; - single_channel_width = width/2; - single_channel_height = height/2; - grid_width = (single_channel_width + 31) / 32; - grid_height = (single_channel_height + 31) / 32; - block_px_max = block_size*block_size; - block_sum = (uint32_t *)malloc(sizeof(uint32_t) * grid_width * grid_height); - printf("Grid size: %d x %d\n", grid_width, grid_height); - - //Stride computed via same formula as the firmware uses. - stride = (((((width + hdr->padding_right)*5)+3)>>2) + 31)&(~31); - - for (i=0; i>1)*single_channel_width); - uint16_t *chan_b_line = out_buf[chan_b] + ((y>>1)*single_channel_width); - for (x=0; x>6), black_level, (1<<10)-1); - chan_a_line++; - lsbs<<=2; - line++; - *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, (1<<10)-1); - chan_b_line++; - lsbs<<=2; - line++; - *(chan_a_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, (1<<10)-1); - chan_a_line++; - lsbs<<=2; - line++; - *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, (1<<10)-1); - chan_b_line++; - lsbs<<=2; - line++; - line++; //skip the LSBs - } - } - - printf("Save data. Bayer order is %d\n", bayer_order); - - if (out_frmt&0x01) - { - header = fopen("ls_table.h", "wb"); - } - if (out_frmt&0x02) - { - bin = fopen("ls.bin", "wb"); - } - if (out_frmt&0x04) - { - table = fopen("ls_table.txt", "wb"); - } - if (out_frmt&0x01) - { - fprintf(header, "uint8_t ls_grid[] = {\n"); - } - if (out_frmt&0x02) - { - uint32_t transform = hdr->transform; - fwrite(&transform, sizeof(uint32_t), 1, bin); - fwrite(&grid_width, sizeof(uint32_t), 1, bin); - fwrite(&grid_height, sizeof(uint32_t), 1, bin); - } - for (i=0; i= single_channel_height) - y_start = single_channel_height-1; - int y_stop = y_start+block_size; - if (y_stop > single_channel_height) - y_stop = single_channel_height; - - for (x=0; x= single_channel_width) - x_start = single_channel_width-1; - int x_stop = x_start+block_size; - if (x_stop > single_channel_width) - x_stop = single_channel_width; - - uint32_t block_val = 0; - uint16_t block_px = 0; - - for (int y_px = y_start; y_px < y_stop; y_px++){ - line = &channel[y_px*(single_channel_width)]; - for (int x_px = x_start; x_px < x_stop; x_px++){ - block_val += line[x_px]; - block_px++; - } - } - if (block_px < block_px_max) - block_val = block_val * block_px_max / block_px; // Scale sum in case of small edge blocks - - block_sum[block_idx++] = block_val; - if (block_val > max_val) - max_val = block_val; - } - } - - max_val <<= 5; - printf("Max_val is %d\n", max_val); - if (out_frmt&0x01) - { - fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]); - } - - // Calculate gain for each block - block_idx = 0; - for (y=0; y 255) - gain = 255; //Clip as uint8_t - else if (gain < 32) - gain = 32; //Clip at x1.0, should never happen - if (out_frmt&0x01) - { - fprintf(header, "%d, ", gain); - } - if (out_frmt&0x02) - { - uint8_t gain_bin = gain; - fwrite(&gain_bin, sizeof(uint8_t), 1, bin); - } - if (out_frmt&0x04) - { - fprintf(table, "%d %d %d %d\n", x * 32 + 16, y * 32 + 16, gain, i); - } - } - } - - } - if (out_frmt&0x01) - { - fprintf(header, "};\n"); - fprintf(header, "uint32_t ref_transform = %u;\n", hdr->transform); - fprintf(header, "uint32_t grid_width = %u;\n", grid_width); - fprintf(header, "uint32_t grid_height = %u;\n", grid_height); - } - - for (i=0; i32) + { + printf("Analysis cell out of range\n"); + return -1; + } + else if (block_size%2 == 1) + { + block_size++; + } + break; + default: + case 'h': + print_help(); + return -1; + break; + } + } + + fstat(in, &sb); + printf("File size is %ld\n", sb.st_size); + + mmap_buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, in, 0); + if (mmap_buf == MAP_FAILED) + { + printf("mmap failed\n"); + goto close_file; + } + + if (!memcmp(mmap_buf, "\xff\xd8", 2)) + { + int sensor_model = 1; + do + { + in_buf = sensor_model_check(sensor_model, mmap_buf, sb.st_size); + } + while(in_buf == 0 && sensor_model++ <= 3); + + if (in_buf == 0) + { + in_buf = (uint8_t*)mmap_buf; + } + } + else + { + in_buf = (uint8_t*)mmap_buf; + } + + if (strncmp(in_buf, "BRCM", 4)) + { + printf("Raw file missing BRCM header\n"); + goto unmap; + } + + char model[7]; + memcpy(model, &in_buf[16], 6); + model[6] = '\0'; + if (strncmp(model, "imx219", 6) == 0) + { + printf("Sensor type: %s\n", model); + if (black_level == 0) + { + black_level = 64; + } + } + else if (strncmp(model, "ov5647", 6) == 0) + { + printf("Sensor type: %s\n", model); + if (black_level == 0) + { + black_level = 16; + } + } + else if (strncmp(model, "testc", 6) == 0 || + strncmp(model, "imx477", 6) == 0) + { + printf("Sensor type: %s\n", model); + if (black_level == 0) + { + black_level = 257; + } + } + else if (black_level == 0) + { + black_level = 16; // Default value + } + printf("Black level: %d\n", black_level); + + hdr = (struct brcm_raw_header*) (in_buf+0xB0); + printf("Header decoding: mode %s, width %u, height %u, padding %u %u\n", + hdr->name, hdr->width, hdr->height, hdr->padding_right, hdr->padding_down); + printf("transform %u, image format %u, bayer order %u, bayer format %u\n", + hdr->transform, hdr->format, hdr->bayer_order, hdr->bayer_format); + if (hdr->format != BRCM_FORMAT_BAYER || + (hdr->bayer_format != BRCM_BAYER_RAW10 && hdr->bayer_format != BRCM_BAYER_RAW12)) + { + printf("Raw file is not Bayer raw10 or raw12\n"); + goto unmap; + } + bayer_order = hdr->bayer_order; + bits_per_sample = hdr->bayer_format * 2 + 4; + max_val = ( 1 << bits_per_sample ) - 1; + width = hdr->width; + height = hdr->height; + single_channel_width = width/2; + single_channel_height = height/2; + grid_width = (single_channel_width + 31) / 32; + grid_height = (single_channel_height + 31) / 32; + block_px_max = block_size*block_size; + block_sum = (uint32_t *)malloc(sizeof(uint32_t) * grid_width * grid_height); + printf("Grid size: %d x %d\n", grid_width, grid_height); + + if (bits_per_sample == 10) { + //Stride computed via same formula as the firmware uses. + stride = (((((width + hdr->padding_right)*5)+3)>>2) + 31)&(~31); + } else { + stride = (((((width + hdr->padding_right)*6)+3)>>2) + 31)&(~31); + } + + for (i=0; i>1)*single_channel_width); + uint16_t *chan_b_line = out_buf[chan_b] + ((y>>1)*single_channel_width); + if (bits_per_sample == 10) { + for (x=0; x>6), black_level, max_val); + chan_a_line++; + lsbs<<=2; + line++; + *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, max_val); + chan_b_line++; + lsbs<<=2; + line++; + *(chan_a_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, max_val); + chan_a_line++; + lsbs<<=2; + line++; + *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, max_val); + chan_b_line++; + lsbs<<=2; + line++; + line++; //skip the LSBs + } + } else { + for (x=0; x>4), black_level, max_val); + chan_a_line++; + line++; + *(chan_b_line) = black_level_correct(((*line)<<4) + (line[ 1 ]&0x0F), black_level, max_val); + chan_b_line++; + line+= 2; + *(chan_a_line) = black_level_correct(((*line)<<4) + (line[ 2 ]>>4), black_level, max_val); + chan_a_line++; + line++; + *(chan_b_line) = black_level_correct(((*line)<<4) + (line[ 1 ]&&0x0F), black_level, max_val); + chan_b_line++; + line+= 2; + } + } + } + + if (out_frmt&0x01) + { + header = fopen("ls_table.h", "wb"); + } + if (out_frmt&0x02) + { + bin = fopen("ls.bin", "wb"); + } + if (out_frmt&0x04) + { + table = fopen("ls_table.txt", "wb"); + } + if (out_frmt&0x01) + { + fprintf(header, "uint8_t ls_grid[] = {\n"); + } + if (out_frmt&0x02) + { + uint32_t transform = hdr->transform; + fwrite(&transform, sizeof(uint32_t), 1, bin); + fwrite(&grid_width, sizeof(uint32_t), 1, bin); + fwrite(&grid_height, sizeof(uint32_t), 1, bin); + } + for (i=0; i= single_channel_height) + y_start = single_channel_height-1; + int y_stop = y_start+block_size; + if (y_stop > single_channel_height) + y_stop = single_channel_height; + + for (x=0; x= single_channel_width) + x_start = single_channel_width-1; + int x_stop = x_start+block_size; + if (x_stop > single_channel_width) + x_stop = single_channel_width; + + uint32_t block_val = 0; + uint16_t block_px = 0; + + for (int y_px = y_start; y_px < y_stop; y_px++) + { + line = &channel[y_px*(single_channel_width)]; + for (int x_px = x_start; x_px < x_stop; x_px++) + { + block_val += line[x_px]; + block_px++; + } + } + if (block_px < block_px_max) + block_val = block_val * block_px_max / block_px; // Scale sum in case of small edge blocks + + block_sum[block_idx++] = block_val ? block_val : 1; + if (block_val > max_blk_val) + max_blk_val = block_val; + } + } + + max_blk_val <<= 5; + if (out_frmt&0x01) + { + fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]); + } + + // Calculate gain for each block + block_idx = 0; + for (y=0; y 255) + gain = 255; //Clip as uint8_t + else if (gain < 32) + gain = 32; //Clip at x1.0, should never happen + if (out_frmt&0x01) + { + fprintf(header, "%d, ", gain); + } + if (out_frmt&0x02) + { + uint8_t gain_bin = gain; + fwrite(&gain_bin, sizeof(uint8_t), 1, bin); + } + if (out_frmt&0x04) + { + fprintf(table, "%d %d %d %d\n", x * 32 + 16, y * 32 + 16, gain, i); + } + } + } + + } + if (out_frmt&0x01) + { + fprintf(header, "};\n"); + fprintf(header, "uint32_t ref_transform = %u;\n", hdr->transform); + fprintf(header, "uint32_t grid_width = %u;\n", grid_width); + fprintf(header, "uint32_t grid_height = %u;\n", grid_height); + } + + for (i=0; i Date: Fri, 25 Jun 2021 18:00:02 +0200 Subject: [PATCH 15/16] Revert "Added support for HQ cam" This reverts commit b239de66f36b23346cdee30693e27aab673d89e8. --- lens_shading_analyse.c | 829 +++++++++++++++++++---------------------- 1 file changed, 383 insertions(+), 446 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index 80d2992..0d2a101 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -88,473 +88,410 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //This structure is at offset 0xB0 from the 'BRCM' ident. struct brcm_raw_header { - uint8_t name[32]; - uint16_t width; - uint16_t height; - uint16_t padding_right; - uint16_t padding_down; - uint32_t dummy[6]; - uint16_t transform; - uint16_t format; - uint8_t bayer_order; - uint8_t bayer_format; + uint8_t name[32]; + uint16_t width; + uint16_t height; + uint16_t padding_right; + uint16_t padding_down; + uint32_t dummy[6]; + uint16_t transform; + uint16_t format; + uint8_t bayer_order; + uint8_t bayer_format; }; //Values taken from https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h #define BRCM_FORMAT_BAYER 33 #define BRCM_BAYER_RAW10 3 -#define BRCM_BAYER_RAW12 4 enum bayer_order_t { - RGGB, - GBRG, - BGGR, - GRBG + RGGB, + GBRG, + BGGR, + GRBG }; const int channel_ordering[4][4] = { - { 0, 1, 2, 3 }, - { 2, 3, 0, 1 }, - { 3, 2, 1, 0 }, - { 1, 0, 3, 2 } + { 0, 1, 2, 3 }, + { 2, 3, 0, 1 }, + { 3, 2, 1, 0 }, + { 1, 0, 3, 2 } }; -uint8_t* sensor_model_check(int sensor_model, void* buffer, size_t size) -{ - uint8_t* in_buf = 0; - - switch(sensor_model) { - case 1: - in_buf = ((uint8_t*)buffer) + size - 6404096; - break; - case 2: - in_buf = ((uint8_t*)buffer) + size - 10270208; - break; - case 3: - in_buf = ((uint8_t*)buffer) + size - 18711040; - break; - default: - return 0; - break; - } - - if (memcmp(in_buf, "BRCM", 4) == 0) - { - return in_buf; - } - else - { - return 0; - } -} - uint16_t black_level_correct(uint16_t raw_pixel, unsigned int black_level, unsigned int max_value) { - return ((raw_pixel - black_level) * max_value) / (max_value - black_level); + return ((raw_pixel - black_level) * max_value) / (max_value - black_level); } void print_help(void) { - printf("\n"); - printf("\n"); - printf("\"lens_shading_analyse\" Lens shading analysis tool\n"); - printf("\n"); - printf("Analyzes the lens shading based on a raw image\n"); - printf("\n"); - printf("usage: lens_shading_analyse -i [options]\n"); - printf("\n"); - printf("Parameters\n"); - printf("\n"); - printf("-i : Raw image file (mandatory)\n"); - printf("-b : Black level\n"); - printf("-s : Size of the analysis cell. Minimum 2, maximum 32, default 4\n"); - printf("-o : Output format. Formats can be output together, for example 3 = 1 + 2\n"); - printf(" 1 : Header file (default on)\n"); - printf(" 2 : Binary file\n"); - printf(" 4 : Text file\n"); - printf(" 8 : Channel data\n"); - printf("\n"); + printf("\n"); + printf("\n"); + printf("\"lens_shading_analyse\" Lens shading analysis tool\n"); + printf("\n"); + printf("Analyzes the lens shading based on a raw image\n"); + printf("\n"); + printf("usage: lens_shading_analyse -i [options]\n"); + printf("\n"); + printf("Parameters\n"); + printf("\n"); + printf("-i : Raw image file (mandatory)\n"); + printf("-b : Black level\n"); + printf("-s : Size of the analysis cell. Minimum 2, maximum 32, default 4\n"); + printf("-o : Output format. Formats can be output together, for example 3 = 1 + 2\n"); + printf(" 1 : Header file (default on)\n"); + printf(" 2 : Binary file\n"); + printf(" 4 : Text file\n"); + printf(" 8 : Channel data\n"); + printf("\n"); } int main(int argc, char *argv[]) { - int in = 0; - FILE *out, *header, *table, *bin; - int i, x, y; - uint16_t *out_buf[NUM_CHANNELS]; - uint16_t max_val; - void *mmap_buf; - uint8_t *in_buf; - struct stat sb; - int bits_per_sample; - int bayer_order; - struct brcm_raw_header *hdr; - int width, height, stride; - uint32_t grid_width, grid_height, block_px_max; - int single_channel_width, single_channel_height; - unsigned int black_level = 0; - uint32_t *block_sum; - uint8_t block_size = 4; - uint8_t out_frmt = 1; - - if (argc < 2) - { - print_help(); - return -1; - } - - int nArg; - while ((nArg = getopt(argc, argv, "b:i:o:s:")) != -1) - { - switch (nArg) { - case 'b': - black_level = strtoul(optarg, NULL, 10); - break; - case 'i': - in = open(optarg, O_RDONLY); - if (in < 0) - { - printf("Failed to open %s\n", argv[1]); - return -1; - } - break; - case 'o': - out_frmt = strtoul(optarg, NULL, 10); - if (!out_frmt & 0x0F) - { - printf("Invalid output format\n"); - return -1; - } - break; - case 's': - block_size = strtoul(optarg, NULL, 10); - if (block_size<=0 || block_size>32) - { - printf("Analysis cell out of range\n"); - return -1; - } - else if (block_size%2 == 1) - { - block_size++; - } - break; - default: - case 'h': - print_help(); - return -1; - break; - } - } - - fstat(in, &sb); - printf("File size is %ld\n", sb.st_size); - - mmap_buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, in, 0); - if (mmap_buf == MAP_FAILED) - { - printf("mmap failed\n"); - goto close_file; - } - - if (!memcmp(mmap_buf, "\xff\xd8", 2)) - { - int sensor_model = 1; - do - { - in_buf = sensor_model_check(sensor_model, mmap_buf, sb.st_size); - } - while(in_buf == 0 && sensor_model++ <= 3); - - if (in_buf == 0) - { - in_buf = (uint8_t*)mmap_buf; - } - } - else - { - in_buf = (uint8_t*)mmap_buf; - } - - if (strncmp(in_buf, "BRCM", 4)) - { - printf("Raw file missing BRCM header\n"); - goto unmap; - } - - char model[7]; - memcpy(model, &in_buf[16], 6); - model[6] = '\0'; - if (strncmp(model, "imx219", 6) == 0) - { - printf("Sensor type: %s\n", model); - if (black_level == 0) - { - black_level = 64; - } - } - else if (strncmp(model, "ov5647", 6) == 0) - { - printf("Sensor type: %s\n", model); - if (black_level == 0) - { - black_level = 16; - } - } - else if (strncmp(model, "testc", 6) == 0 || - strncmp(model, "imx477", 6) == 0) - { - printf("Sensor type: %s\n", model); - if (black_level == 0) - { - black_level = 257; - } - } - else if (black_level == 0) - { - black_level = 16; // Default value - } - printf("Black level: %d\n", black_level); - - hdr = (struct brcm_raw_header*) (in_buf+0xB0); - printf("Header decoding: mode %s, width %u, height %u, padding %u %u\n", - hdr->name, hdr->width, hdr->height, hdr->padding_right, hdr->padding_down); - printf("transform %u, image format %u, bayer order %u, bayer format %u\n", - hdr->transform, hdr->format, hdr->bayer_order, hdr->bayer_format); - if (hdr->format != BRCM_FORMAT_BAYER || - (hdr->bayer_format != BRCM_BAYER_RAW10 && hdr->bayer_format != BRCM_BAYER_RAW12)) - { - printf("Raw file is not Bayer raw10 or raw12\n"); - goto unmap; - } - bayer_order = hdr->bayer_order; - bits_per_sample = hdr->bayer_format * 2 + 4; - max_val = ( 1 << bits_per_sample ) - 1; - width = hdr->width; - height = hdr->height; - single_channel_width = width/2; - single_channel_height = height/2; - grid_width = (single_channel_width + 31) / 32; - grid_height = (single_channel_height + 31) / 32; - block_px_max = block_size*block_size; - block_sum = (uint32_t *)malloc(sizeof(uint32_t) * grid_width * grid_height); - printf("Grid size: %d x %d\n", grid_width, grid_height); - - if (bits_per_sample == 10) { - //Stride computed via same formula as the firmware uses. - stride = (((((width + hdr->padding_right)*5)+3)>>2) + 31)&(~31); - } else { - stride = (((((width + hdr->padding_right)*6)+3)>>2) + 31)&(~31); - } - - for (i=0; i>1)*single_channel_width); - uint16_t *chan_b_line = out_buf[chan_b] + ((y>>1)*single_channel_width); - if (bits_per_sample == 10) { - for (x=0; x>6), black_level, max_val); - chan_a_line++; - lsbs<<=2; - line++; - *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, max_val); - chan_b_line++; - lsbs<<=2; - line++; - *(chan_a_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, max_val); - chan_a_line++; - lsbs<<=2; - line++; - *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, max_val); - chan_b_line++; - lsbs<<=2; - line++; - line++; //skip the LSBs - } - } else { - for (x=0; x>4), black_level, max_val); - chan_a_line++; - line++; - *(chan_b_line) = black_level_correct(((*line)<<4) + (line[ 1 ]&0x0F), black_level, max_val); - chan_b_line++; - line+= 2; - *(chan_a_line) = black_level_correct(((*line)<<4) + (line[ 2 ]>>4), black_level, max_val); - chan_a_line++; - line++; - *(chan_b_line) = black_level_correct(((*line)<<4) + (line[ 1 ]&&0x0F), black_level, max_val); - chan_b_line++; - line+= 2; - } - } - } - - if (out_frmt&0x01) - { - header = fopen("ls_table.h", "wb"); - } - if (out_frmt&0x02) - { - bin = fopen("ls.bin", "wb"); - } - if (out_frmt&0x04) - { - table = fopen("ls_table.txt", "wb"); - } - if (out_frmt&0x01) - { - fprintf(header, "uint8_t ls_grid[] = {\n"); - } - if (out_frmt&0x02) - { - uint32_t transform = hdr->transform; - fwrite(&transform, sizeof(uint32_t), 1, bin); - fwrite(&grid_width, sizeof(uint32_t), 1, bin); - fwrite(&grid_height, sizeof(uint32_t), 1, bin); - } - for (i=0; i= single_channel_height) - y_start = single_channel_height-1; - int y_stop = y_start+block_size; - if (y_stop > single_channel_height) - y_stop = single_channel_height; - - for (x=0; x= single_channel_width) - x_start = single_channel_width-1; - int x_stop = x_start+block_size; - if (x_stop > single_channel_width) - x_stop = single_channel_width; - - uint32_t block_val = 0; - uint16_t block_px = 0; - - for (int y_px = y_start; y_px < y_stop; y_px++) - { - line = &channel[y_px*(single_channel_width)]; - for (int x_px = x_start; x_px < x_stop; x_px++) - { - block_val += line[x_px]; - block_px++; - } - } - if (block_px < block_px_max) - block_val = block_val * block_px_max / block_px; // Scale sum in case of small edge blocks - - block_sum[block_idx++] = block_val ? block_val : 1; - if (block_val > max_blk_val) - max_blk_val = block_val; - } - } - - max_blk_val <<= 5; - if (out_frmt&0x01) - { - fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]); - } - - // Calculate gain for each block - block_idx = 0; - for (y=0; y 255) - gain = 255; //Clip as uint8_t - else if (gain < 32) - gain = 32; //Clip at x1.0, should never happen - if (out_frmt&0x01) - { - fprintf(header, "%d, ", gain); - } - if (out_frmt&0x02) - { - uint8_t gain_bin = gain; - fwrite(&gain_bin, sizeof(uint8_t), 1, bin); - } - if (out_frmt&0x04) - { - fprintf(table, "%d %d %d %d\n", x * 32 + 16, y * 32 + 16, gain, i); - } - } - } - - } - if (out_frmt&0x01) - { - fprintf(header, "};\n"); - fprintf(header, "uint32_t ref_transform = %u;\n", hdr->transform); - fprintf(header, "uint32_t grid_width = %u;\n", grid_width); - fprintf(header, "uint32_t grid_height = %u;\n", grid_height); - } - - for (i=0; i32) + { + printf("Analysis cell out of range\n"); + return -1; + } + else if (block_size%2 == 1) + { + block_size++; + } + break; + default: + case 'h': + print_help(); + return -1; + break; + } + } + + fstat(in, &sb); + printf("File size is %ld\n", sb.st_size); + + mmap_buf = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, in, 0); + if (mmap_buf == MAP_FAILED) + { + printf("mmap failed\n"); + goto close_file; + } + + if (!memcmp(mmap_buf, "\xff\xd8", 2)) + { + //JPEG+RAW - find the raw header + //Try the appropriate offsets for the full res modes + //of OV5647 and IMX219. Any other modes will need to be + //stripped down to the bare raw (inc header) before processing + in_buf = ((uint8_t*)mmap_buf) + sb.st_size - 6404096; + if (memcmp(in_buf, "BRCM", 4)) + { + //Failed on OV5647, try IMX219 + in_buf = ((uint8_t*)mmap_buf) + sb.st_size - 10270208; + if (memcmp(in_buf, "BRCM", 4)) + { + //Failed totally - reset to the start of the buffer + in_buf = (uint8_t*)mmap_buf; + } + } + } + else + { + in_buf = (uint8_t*)mmap_buf; + } + + if (strncmp(in_buf, "BRCM", 4)) + { + printf("Raw file missing BRCM header\n"); + goto unmap; + } + + char model[7]; + memcpy(model, &in_buf[16], 6); + model[6] = '\0'; + if (strncmp(model, "imx219", 6) == 0) + { + printf("Sensor type: %s\n", model); + if (black_level == 0) + { + black_level = 66; + } + } else if (strncmp(model, "ov5647", 6) == 0) + { + printf("Sensor type: %s\n", model); + if (black_level == 0) + { + black_level = 16; + } + } else if (black_level == 0){ + black_level = 16; // Default value + } + printf("Black level: %d\n", black_level); + + hdr = (struct brcm_raw_header*) (in_buf+0xB0); + printf("Header decoding: mode %s, width %u, height %u, padding %u %u\n", + hdr->name, hdr->width, hdr->height, hdr->padding_right, hdr->padding_down); + printf("transform %u, image format %u, bayer order %u, bayer format %u\n", + hdr->transform, hdr->format, hdr->bayer_order, hdr->bayer_format); + if (hdr->format != BRCM_FORMAT_BAYER || hdr->bayer_format != BRCM_BAYER_RAW10) + { + printf("Raw file is not Bayer raw10\n"); + goto unmap; + } + bayer_order = hdr->bayer_order; + width = hdr->width; + height = hdr->height; + single_channel_width = width/2; + single_channel_height = height/2; + grid_width = (single_channel_width + 31) / 32; + grid_height = (single_channel_height + 31) / 32; + block_px_max = block_size*block_size; + block_sum = (uint32_t *)malloc(sizeof(uint32_t) * grid_width * grid_height); + printf("Grid size: %d x %d\n", grid_width, grid_height); + + //Stride computed via same formula as the firmware uses. + stride = (((((width + hdr->padding_right)*5)+3)>>2) + 31)&(~31); + + for (i=0; i>1)*single_channel_width); + uint16_t *chan_b_line = out_buf[chan_b] + ((y>>1)*single_channel_width); + for (x=0; x>6), black_level, (1<<10)-1); + chan_a_line++; + lsbs<<=2; + line++; + *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, (1<<10)-1); + chan_b_line++; + lsbs<<=2; + line++; + *(chan_a_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, (1<<10)-1); + chan_a_line++; + lsbs<<=2; + line++; + *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, (1<<10)-1); + chan_b_line++; + lsbs<<=2; + line++; + line++; //skip the LSBs + } + } + + printf("Save data. Bayer order is %d\n", bayer_order); + + if (out_frmt&0x01) + { + header = fopen("ls_table.h", "wb"); + } + if (out_frmt&0x02) + { + bin = fopen("ls.bin", "wb"); + } + if (out_frmt&0x04) + { + table = fopen("ls_table.txt", "wb"); + } + if (out_frmt&0x01) + { + fprintf(header, "uint8_t ls_grid[] = {\n"); + } + if (out_frmt&0x02) + { + uint32_t transform = hdr->transform; + fwrite(&transform, sizeof(uint32_t), 1, bin); + fwrite(&grid_width, sizeof(uint32_t), 1, bin); + fwrite(&grid_height, sizeof(uint32_t), 1, bin); + } + for (i=0; i= single_channel_height) + y_start = single_channel_height-1; + int y_stop = y_start+block_size; + if (y_stop > single_channel_height) + y_stop = single_channel_height; + + for (x=0; x= single_channel_width) + x_start = single_channel_width-1; + int x_stop = x_start+block_size; + if (x_stop > single_channel_width) + x_stop = single_channel_width; + + uint32_t block_val = 0; + uint16_t block_px = 0; + + for (int y_px = y_start; y_px < y_stop; y_px++){ + line = &channel[y_px*(single_channel_width)]; + for (int x_px = x_start; x_px < x_stop; x_px++){ + block_val += line[x_px]; + block_px++; + } + } + if (block_px < block_px_max) + block_val = block_val * block_px_max / block_px; // Scale sum in case of small edge blocks + + block_sum[block_idx++] = block_val; + if (block_val > max_val) + max_val = block_val; + } + } + + max_val <<= 5; + printf("Max_val is %d\n", max_val); + if (out_frmt&0x01) + { + fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]); + } + + // Calculate gain for each block + block_idx = 0; + for (y=0; y 255) + gain = 255; //Clip as uint8_t + else if (gain < 32) + gain = 32; //Clip at x1.0, should never happen + if (out_frmt&0x01) + { + fprintf(header, "%d, ", gain); + } + if (out_frmt&0x02) + { + uint8_t gain_bin = gain; + fwrite(&gain_bin, sizeof(uint8_t), 1, bin); + } + if (out_frmt&0x04) + { + fprintf(table, "%d %d %d %d\n", x * 32 + 16, y * 32 + 16, gain, i); + } + } + } + + } + if (out_frmt&0x01) + { + fprintf(header, "};\n"); + fprintf(header, "uint32_t ref_transform = %u;\n", hdr->transform); + fprintf(header, "uint32_t grid_width = %u;\n", grid_width); + fprintf(header, "uint32_t grid_height = %u;\n", grid_height); + } + + for (i=0; i Date: Fri, 25 Jun 2021 18:08:09 +0200 Subject: [PATCH 16/16] Added support for HQ cam (with proper indentation) --- lens_shading_analyse.c | 171 ++++++++++++++++++++++++++++------------- 1 file changed, 117 insertions(+), 54 deletions(-) diff --git a/lens_shading_analyse.c b/lens_shading_analyse.c index 0d2a101..16c10c2 100644 --- a/lens_shading_analyse.c +++ b/lens_shading_analyse.c @@ -102,6 +102,7 @@ struct brcm_raw_header { //Values taken from https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h #define BRCM_FORMAT_BAYER 33 #define BRCM_BAYER_RAW10 3 +#define BRCM_BAYER_RAW12 4 enum bayer_order_t { RGGB, @@ -117,6 +118,35 @@ const int channel_ordering[4][4] = { { 1, 0, 3, 2 } }; +uint8_t* sensor_model_check(int sensor_model, void* buffer, size_t size) +{ + uint8_t* in_buf = 0; + + switch(sensor_model) { + case 1: + in_buf = ((uint8_t*)buffer) + size - 6404096; + break; + case 2: + in_buf = ((uint8_t*)buffer) + size - 10270208; + break; + case 3: + in_buf = ((uint8_t*)buffer) + size - 18711040; + break; + default: + return 0; + break; + } + + if (memcmp(in_buf, "BRCM", 4) == 0) + { + return in_buf; + } + else + { + return 0; + } +} + uint16_t black_level_correct(uint16_t raw_pixel, unsigned int black_level, unsigned int max_value) { return ((raw_pixel - black_level) * max_value) / (max_value - black_level); @@ -151,9 +181,11 @@ int main(int argc, char *argv[]) FILE *out, *header, *table, *bin; int i, x, y; uint16_t *out_buf[NUM_CHANNELS]; + uint16_t max_val; void *mmap_buf; uint8_t *in_buf; struct stat sb; + int bits_per_sample; int bayer_order; struct brcm_raw_header *hdr; int width, height, stride; @@ -225,20 +257,16 @@ int main(int argc, char *argv[]) if (!memcmp(mmap_buf, "\xff\xd8", 2)) { - //JPEG+RAW - find the raw header - //Try the appropriate offsets for the full res modes - //of OV5647 and IMX219. Any other modes will need to be - //stripped down to the bare raw (inc header) before processing - in_buf = ((uint8_t*)mmap_buf) + sb.st_size - 6404096; - if (memcmp(in_buf, "BRCM", 4)) + int sensor_model = 1; + do { - //Failed on OV5647, try IMX219 - in_buf = ((uint8_t*)mmap_buf) + sb.st_size - 10270208; - if (memcmp(in_buf, "BRCM", 4)) - { - //Failed totally - reset to the start of the buffer - in_buf = (uint8_t*)mmap_buf; - } + in_buf = sensor_model_check(sensor_model, mmap_buf, sb.st_size); + } + while(in_buf == 0 && sensor_model++ <= 3); + + if (in_buf == 0) + { + in_buf = (uint8_t*)mmap_buf; } } else @@ -260,16 +288,28 @@ int main(int argc, char *argv[]) printf("Sensor type: %s\n", model); if (black_level == 0) { - black_level = 66; + black_level = 64; } - } else if (strncmp(model, "ov5647", 6) == 0) + } + else if (strncmp(model, "ov5647", 6) == 0) { printf("Sensor type: %s\n", model); if (black_level == 0) { black_level = 16; } - } else if (black_level == 0){ + } + else if (strncmp(model, "testc", 6) == 0 || + strncmp(model, "imx477", 6) == 0) + { + printf("Sensor type: %s\n", model); + if (black_level == 0) + { + black_level = 257; + } + } + else if (black_level == 0) + { black_level = 16; // Default value } printf("Black level: %d\n", black_level); @@ -279,12 +319,15 @@ int main(int argc, char *argv[]) hdr->name, hdr->width, hdr->height, hdr->padding_right, hdr->padding_down); printf("transform %u, image format %u, bayer order %u, bayer format %u\n", hdr->transform, hdr->format, hdr->bayer_order, hdr->bayer_format); - if (hdr->format != BRCM_FORMAT_BAYER || hdr->bayer_format != BRCM_BAYER_RAW10) + if (hdr->format != BRCM_FORMAT_BAYER || + (hdr->bayer_format != BRCM_BAYER_RAW10 && hdr->bayer_format != BRCM_BAYER_RAW12)) { - printf("Raw file is not Bayer raw10\n"); + printf("Raw file is not Bayer raw10 or raw12\n"); goto unmap; } bayer_order = hdr->bayer_order; + bits_per_sample = hdr->bayer_format * 2 + 4; + max_val = ( 1 << bits_per_sample ) - 1; width = hdr->width; height = hdr->height; single_channel_width = width/2; @@ -295,8 +338,12 @@ int main(int argc, char *argv[]) block_sum = (uint32_t *)malloc(sizeof(uint32_t) * grid_width * grid_height); printf("Grid size: %d x %d\n", grid_width, grid_height); - //Stride computed via same formula as the firmware uses. - stride = (((((width + hdr->padding_right)*5)+3)>>2) + 31)&(~31); + if (bits_per_sample == 10) { + //Stride computed via same formula as the firmware uses. + stride = (((((width + hdr->padding_right)*5)+3)>>2) + 31)&(~31); + } else { + stride = (((((width + hdr->padding_right)*6)+3)>>2) + 31)&(~31); + } for (i=0; i>1)*single_channel_width); uint16_t *chan_b_line = out_buf[chan_b] + ((y>>1)*single_channel_width); - for (x=0; x>6), black_level, (1<<10)-1); - chan_a_line++; - lsbs<<=2; - line++; - *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, (1<<10)-1); - chan_b_line++; - lsbs<<=2; - line++; - *(chan_a_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, (1<<10)-1); - chan_a_line++; - lsbs<<=2; - line++; - *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, (1<<10)-1); - chan_b_line++; - lsbs<<=2; - line++; - line++; //skip the LSBs + if (bits_per_sample == 10) { + for (x=0; x>6), black_level, max_val); + chan_a_line++; + lsbs<<=2; + line++; + *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, max_val); + chan_b_line++; + lsbs<<=2; + line++; + *(chan_a_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, max_val); + chan_a_line++; + lsbs<<=2; + line++; + *(chan_b_line) = black_level_correct(((*line)<<2) + (lsbs>>6), black_level, max_val); + chan_b_line++; + lsbs<<=2; + line++; + line++; //skip the LSBs + } + } else { + for (x=0; x>4), black_level, max_val); + chan_a_line++; + line++; + *(chan_b_line) = black_level_correct(((*line)<<4) + (line[ 1 ]&0x0F), black_level, max_val); + chan_b_line++; + line+= 2; + *(chan_a_line) = black_level_correct(((*line)<<4) + (line[ 2 ]>>4), black_level, max_val); + chan_a_line++; + line++; + *(chan_b_line) = black_level_correct(((*line)<<4) + (line[ 1 ]&&0x0F), black_level, max_val); + chan_b_line++; + line+= 2; + } } } - printf("Save data. Bayer order is %d\n", bayer_order); - if (out_frmt&0x01) { header = fopen("ls_table.h", "wb"); @@ -383,7 +446,6 @@ int main(int argc, char *argv[]) out = fopen(filenames[i], "wb"); if (out) { - printf("Saving %s data\n", filenames[i]); fwrite(out_buf[i], (single_channel_width*single_channel_height)*sizeof(uint16_t), 1, out); fclose(out); out = NULL; @@ -400,11 +462,11 @@ int main(int argc, char *argv[]) "Gr", "Gb", "B" - }; - + }; + // Calculate sum for each block uint16_t block_idx = 0; - uint32_t max_val = 0; + uint32_t max_blk_val = 0; for (y=0; y max_val) - max_val = block_val; + block_sum[block_idx++] = block_val ? block_val : 1; + if (block_val > max_blk_val) + max_blk_val = block_val; } } - max_val <<= 5; - printf("Max_val is %d\n", max_val); + max_blk_val <<= 5; if (out_frmt&0x01) { fprintf(header, "//%s - Ch %d\n", channel_comments[i], channel_ordering[bayer_order][i]); @@ -455,7 +518,7 @@ int main(int argc, char *argv[]) { for (x=0; x 255) gain = 255; //Clip as uint8_t else if (gain < 32)