Hi, Oliver Schwartz <oliver.schwa...@gmx.de> writes:
> The Epson 3490 uses 14 bit internally. The gamma table is used to > spread or shrink the values into 8 / 16 bit. I see. So they just lie about 48-bit _in_? http://www.epson.co.uk/products/scanners/product_spec/Perfection3490Photo.htm Not nice, I wouldn't expect that from them. > I'm not sure that's what you really want. You should at least apply > calibration before scanning, because there's no easy way to > compensate different gain / black level of sensor elements > afterwards. I plan to compensate it later, using a previously scanned white (and, if needed, black) data. It seems doing it internally in the scanner lowers the quality dramatically, and I can't make corrections later. > Anyway, if you really want to skip calibration you can > just turn it off in xsane (or whatever frontend you use) by > unchecking the option "quality calibration"). It doesn't seem to work that way - the scanner does the calibration anyway. Cover the calibration area (just behind the last frame, near the end of the lamp) and see for yourself. I can avoid the calibration using "quality calibration" and changing the backend to send fixed data to the scanner: all 0s for black and 255, 0, 0 etc (for each colour) for white-calibration: sane-backends/backend/snapscan-scsi.c: @@ -1292,12 +1273,21 @@ pbuf = pss->buf + SEND_LENGTH; if (is_colour_mode(actual_mode(pss))) { for (k = 0; k < num_bins / 3; k++) { +#if 0 *pbuf++ = bins[k] - r; r = bins[k]; *pbuf++ = bins[k + num_bins/3] - g; g = bins[k + num_bins/3]; *pbuf++ = bins[k + 2*num_bins/3] - b; b = bins[k + 2*num_bins/3]; +#else + u_char v = 0; + if (pass == 0 && k == 0) + v = 255; + *pbuf++ = v; + *pbuf++ = v; + *pbuf++ = v; +#endif } } else { for (k = 0; k < num_bins; k++) { But I'm not sure what the best value is (output from a simple stat util, source attached): 255.ppm: different pixel values: R = 5304 (92-7232) G = 7490 (118-12750) B = 7490 (95-12075) 127.ppm: different pixel values: R = 10209 (187-14919) G = 7199 (241-16383) B = 7199 (199-16383) 63.ppm: different pixel values: R = 11523 (418-16383) G = 12227 (472-16383) B = 12227 (379-16383) 31.ppm: different pixel values: R = 15509 (839-16383) G = 15068 (1144-16383) B = 15068 (774-16383) 255 seems to lose bits (just 5304 different R values, less than 13 bits), 127 and 63 saturates in area not covered by the film, 31 gets saturated even with the film. I.e., I'm not sure what does the value represent - if it's maximum CCD output = 16383 shifted right by 6 bits to fit in 8-bit sample then why 255 gives that bad distribution? I'll have to investigate it further. It would be nice to disable the calibration scan completely because it takes time. > It will calculate something anyway, but if you set brightness / > contrast to 0 and gamma to 1.0 it should result in a linear gamma > table, so you get unchanged data in 16 bit mode. :-). Well, it didn't work that way but a --gamma-table=[0]0-[16383]16383 does the trick. > Note that xsane provides its own sliders for gamma / brightness / > contrast for post-processing. Use the sliders in the "standard > option" window to set the backend values. Sure. The problem with negatives is I don't know the values while scanning, they will be determined later, and while I scan 4 frames at a time, each frame may (or may not) need different corrections. > I'm not sure the calibration data would be of any use. Right, I think I should just do a regular scan with no film, and then with a fully exposed film instead of just some unspecified "black" area. -- Krzysztof Halasa ppm_stat.c util, for 16-bit .ppm files only: #include <math.h> #include <stdio.h> #include <ppm.h> int main(int argc, char *argv[]) { uint16_t vals[3][0x10000]; int f; if (argc < 2) { fprintf(stderr, "Usage: %s file.ppm ...\n", argv[0]); exit(1); } for (f = 1; f < argc; f++) { FILE *input; int i, rgb, x, y, format, cnt[3] = {0, 0, 0}; int minvals[3] = { 65535, 65535, 65535 }; int maxvals[3] = { 0, 0, 0 }; pixval maxval; if ((input = fopen(argv[f], "rb")) == NULL) { fprintf(stderr, "%s: error opening image file %s\n", argv[0], argv[f]); exit(1); } ppm_readppminit(input, &x, &y, &maxval, &format); if (format != RPPM_FORMAT || maxval != 65535) { fprintf(stderr, "%s: invalid image %s format\n", argv[0], argv[f]); exit(1); } memset(vals, 0, sizeof(vals)); for (i = 0; i < x * y; i++) for (rgb = 0; rgb < 3; rgb++) { uint16_t v = getc(input) << 8; v |= getc(input); vals[rgb][v]++; } for (i = 0; i < 0x10000; i++) for (rgb = 0; rgb < 3; rgb++) { if (vals[rgb][i]) { cnt[rgb]++; if (minvals[rgb] > i) minvals[rgb] = i; if (maxvals[rgb] < i) maxvals[rgb] = i; } } fclose(input); printf("%s: different pixel values:\n" "\tR = %i (%i-%i)\n" "\tG = %i (%i-%i)\n" "\tB = %i (%i-%i)\n", argv[f], cnt[0], minvals[0], maxvals[0], cnt[1], minvals[1], maxvals[1], cnt[1], minvals[2], maxvals[2]); } return 0; }