void calculateBlackAreas() { int[] histogram = new int[4 * 65536 * sizeof(int)]; //memset(histogram, 0, 4 * 65536 * sizeof(int)); int totalpixels = 0; for (int i = 0; i < blackAreas.Count; i++) { BlackArea area = blackAreas[i]; /* Make sure area sizes are multiple of two, * so we have the same amount of pixels for each CFA group */ area.size = area.size - (area.size & 1); /* Process horizontal area */ if (!area.isVertical) { if (area.offset + area.size > uncroppedDim.y) { throw new RawDecoderException("RawImageData::calculateBlackAreas: Offset + size is larger than height of image"); } for (int y = area.offset; y < area.offset + area.size; y++) { ushort[] pixel = previewData.Skip(mOffset.x + dim.x * y).ToArray(); int[] localhist = histogram.Skip((y & 1) * (65536 * 2)).ToArray(); for (int x = mOffset.x; x < dim.x + mOffset.x; x++) { localhist[((x & 1) << 16) + pixel[0]]++; } } totalpixels += area.size * dim.x; } /* Process vertical area */ if (area.isVertical) { if (area.offset + area.size > uncroppedDim.x) { throw new RawDecoderException("RawImageData::calculateBlackAreas: Offset + size is larger than width of image"); } for (int y = mOffset.y; y < dim.y + mOffset.y; y++) { ushort[] pixel = previewData.Skip(area.offset + dim.x * y).ToArray(); int[] localhist = histogram.Skip((y & 1) * (65536 * 2)).ToArray(); for (int x = area.offset; x < area.size + area.offset; x++) { localhist[((x & 1) << 16) + pixel[0]]++; } } totalpixels += area.size * dim.y; } } if (totalpixels == 0) { for (int i = 0; i < 4; i++) { blackLevelSeparate[i] = blackLevel; } return; } /* Calculate median value of black areas for each component */ /* Adjust the number of total pixels so it is the same as the median of each histogram */ totalpixels /= 4 * 2; for (int i = 0; i < 4; i++) { int[] localhist = histogram.Skip(i * 65536).ToArray(); int acc_pixels = localhist[0]; int pixel_value = 0; while (acc_pixels <= totalpixels && pixel_value < 65535) { pixel_value++; acc_pixels += localhist[pixel_value]; } blackLevelSeparate[i] = pixel_value; } /* If this is not a CFA image, we do not use separate blacklevels, use average */ if (!isCFA) { int total = 0; for (int i = 0; i < 4; i++) { total += blackLevelSeparate[i]; } for (int i = 0; i < 4; i++) { blackLevelSeparate[i] = (total + 2) >> 2; } } }
internal static void CalculateBlackArea(RawImage image) { Debug.Assert(image.black == 0); Debug.Assert(image.blackAreas.Count > 0); int[] histogram = new int[4 * 65536 * sizeof(int)]; uint totalpixels = 0; for (int i = 0; i < image.blackAreas.Count; i++) { BlackArea area = image.blackAreas[i]; // Make sure area sizes are multiple of two, // so we have the same amount of pixels for each CFA group area.Size = area.Size - (area.Size & 1); // Process horizontal area if (!area.IsVertical) { if (area.Offset + area.Size > image.fullSize.UncroppedDim.height) { throw new RawDecoderException("RawImageData::calculateBlackAreas: Offset + size is larger than height of image"); } for (uint y = area.Offset; y < area.Offset + area.Size; y++) { ushort[] pixel = image.preview.rawView.Skip((int)(image.fullSize.offset.width + image.fullSize.dim.width * y)).ToArray(); int[] localhist = histogram.Skip((int)(y & 1) * (65536 * 2)).ToArray(); for (uint x = image.fullSize.offset.width; x < image.fullSize.dim.width + image.fullSize.offset.width; x++) { localhist[((x & 1) << 16) + pixel[0]]++; } } totalpixels += area.Size * image.fullSize.dim.width; } // Process vertical area if (area.IsVertical) { if (area.Offset + area.Size > image.fullSize.UncroppedDim.width) { throw new RawDecoderException("RawImageData::calculateBlackAreas: Offset + size is larger than width of image"); } for (uint y = image.fullSize.offset.height; y < image.fullSize.dim.height + image.fullSize.offset.height; y++) { ushort[] pixel = image.preview.rawView.Skip((int)(area.Offset + image.fullSize.dim.width * y)).ToArray(); int[] localhist = histogram.Skip((int)(y & 1) * (65536 * 2)).ToArray(); for (uint x = area.Offset; x < area.Size + area.Offset; x++) { localhist[((x & 1) << 16) + pixel[0]]++; } } totalpixels += area.Size * image.fullSize.dim.height; } } int acc_pixels = histogram[0]; int pixel_value = 0; while (acc_pixels <= totalpixels && pixel_value < 65535) { pixel_value++; acc_pixels += histogram[pixel_value]; } image.black = pixel_value; Debug.Assert(image.black <= image.whitePoint); }