Esempio n. 1
0
        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            //_totalFiles = filesInSourceFolder.Length;

            List <string[]> completeGroups = new List <string[]>();

            int frameDelay = 0;

            //byte[] RGBPositions = new byte[1];
            ShotSetting[] shotSettings             = new ShotSetting[3];
            bool          IsTIFF                   = false;
            bool          IsEXR                    = false;
            int           maxThreads               = Environment.ProcessorCount;
            string        customOutputName         = "";
            int           leadingZeros             = 0;
            bool          overwriteExisting        = false;
            float         HDRClippingPoint         = 0.99f;
            float         HDRFeatherMultiplier     = 1;
            bool          EXRIntegrityVerification = true;

            this.Dispatcher.Invoke(() =>
            {
                frameDelay = 0;
                int.TryParse(delay.Text, out frameDelay);
                int.TryParse(outputNameLeadingZeros_txt.Text, out leadingZeros);
                int.TryParse(maxThreads_txt.Text, out maxThreads);
                //RGBPositions = getRGBPositions();
                shotSettings             = getShots();
                IsTIFF                   = (bool)formatTif.IsChecked;
                IsEXR                    = (bool)formatExr.IsChecked;
                customOutputName         = outputNameBase_txt.Text;
                overwriteExisting        = !(bool)overwrite_no.IsChecked && (bool)overwrite_yes.IsChecked;
                HDRClippingPoint         = getHDRClippingpoint();
                HDRFeatherMultiplier     = getFeatherMultiplier();
                EXRIntegrityVerification = (bool)exrIntegrityVerification_check.IsChecked;
            });

            int groupLength = shotSettings.Length;

            _totalFiles = (int)Math.Floor(filesInSourceFolder.Length / (decimal)groupLength);

            if (maxThreads == 0)
            {
                maxThreads = Environment.ProcessorCount;
            }


            FORMAT inputFormat = getInputFormat();

            TARGETFORMAT targetFormat = TARGETFORMAT.EXR;

            if (IsEXR)
            {
                targetFormat = TARGETFORMAT.EXR;
            }
            else
            {
                targetFormat = TARGETFORMAT.TIF;
            }


            for (int baseIndex = frameDelay; baseIndex < filesInSourceFolder.Length; baseIndex += groupLength)
            {
                if ((baseIndex + (groupLength - 1)) > (filesInSourceFolder.Length - 1))
                {
                    MessageBox.Show("Group incomplete. Skipping.");
                    continue;
                }

                int[]    fileIndizi = new int[groupLength];
                string[] files      = new string[groupLength];
                for (var i = 0; i < groupLength; i++)
                {
                    fileIndizi[i] = baseIndex + i;
                    files[i]      = filesInSourceFolder[baseIndex + i];
                }

                //int[] RGBIndizi = new int[groupLength] { baseIndex + RGBPositions[0], baseIndex + RGBPositions[1], baseIndex + RGBPositions[2] };

                //string[] RGBFiles = new string[groupLength] { filesInSourceFolder[RGBIndizi[0]], filesInSourceFolder[RGBIndizi[1]], filesInSourceFolder[RGBIndizi[2]] };

                completeGroups.Add(files);
            }

            int processFrom = 1;
            int processTo   = completeGroups.Count();

            this.Dispatcher.Invoke(() =>
            {
                int.TryParse(processFrom_txt.Text, out processFrom);
                int.TryParse(processTo_txt.Text, out processTo);
            });

            // Index starting at 0, but GUI starts at 1
            processFrom--;
            processTo--;


            var countLock = new object();

            CurrentProgress = 0;

            _counterTotal           = 0;
            _counterSkippedRange    = 0;
            _counterDone            = 0;
            _counterSkippedExisting = 0;

            if (EXRIntegrityVerification)
            {
                IntegrityChecker.BuildIntegrityVerificationAcceptableLossCache();
            }

            integrityCheckFailCount = 0;

            Parallel.ForEach(completeGroups,
                             new ParallelOptions {
                MaxDegreeOfParallelism = maxThreads
            }, (currentGroup, loopState, index) =>
                             // foreach (string srcFileName in filesInSourceFolder)
            {
                _counterTotal++;
                var percentage = (double)_counterTotal / _totalFiles * 100.0;
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    return;
                }

                if (index < processFrom || index > processTo)
                {
                    // Skip this one.
                    _counterSkippedRange++;
                    lock (countLock) { worker?.ReportProgress((int)percentage); }
                    return;
                }

                string fileNameWithoutFolder = customOutputName == "" ? Path.GetFileNameWithoutExtension(currentGroup[0]) : customOutputName + (leadingZeros == 0 ? index.ToString() : index.ToString("D" + leadingZeros.ToString()));

                string fileNameWithoutExtension =
                    targetFolder + "\\" + fileNameWithoutFolder;
                string fileName = fileNameWithoutExtension + (targetFormat == TARGETFORMAT.EXR ? ".exr" : "") + (targetFormat == TARGETFORMAT.TIF ? ".tif" : "");


                if (File.Exists(fileName) && !overwriteExisting)
                {
                    // Error: File already exists. No overwriting. Move on.
                    //continue;
                    _counterSkippedExisting++;
                    lock (countLock) { worker?.ReportProgress((int)percentage); }
                    return;
                }

                ProcessRAW(currentGroup, shotSettings, fileName, targetFormat, inputFormat, maxThreads, HDRClippingPoint, HDRFeatherMultiplier, EXRIntegrityVerification);
                _counterDone++;
                lock (countLock) { worker?.ReportProgress((int)percentage); }
            });
            this.Dispatcher.Invoke(() =>
            {
                txtStatus.Text = "Finished. " + integrityCheckFailCount + " integrity check fails";
            });
        }
Esempio n. 2
0
        private void ProcessRAW(string[] srcRGBTriplet, ShotSetting[] shotSettings, string targetFilename, TARGETFORMAT targetFormat, FORMAT inputFormat, int maxThreads, float HDRClippingPoint, float HDRFeatherMultiplier, bool EXRIntegrityVerification)
        {
            int groupLength = shotSettings.Length;

            byte[][] buffers = new byte[groupLength][];
            for (int i = 0; i < groupLength; i++)
            {
                buffers[i] = File.ReadAllBytes(srcRGBTriplet[i]);
                if (inputFormat == FORMAT.MONO12p)
                {
                    buffers[i] = convert12pto16bit(buffers[i]);
                }
            }


            int width  = 4096;
            int height = 3000;

            this.Dispatcher.Invoke(() =>
            {
                width = 1;
                int.TryParse(rawWidth.Text, out width);
                height = 1;
                int.TryParse(rawHeight.Text, out height);
            });


            byte[][] RGBBuffers = HDRMerge(buffers, shotSettings, HDRClippingPoint, HDRFeatherMultiplier);

            byte[] buffR = RGBBuffers[0];
            byte[] buffG = RGBBuffers[1];
            byte[] buffB = RGBBuffers[2];

            // Interleave
            int pixelCount  = width * height;
            int totalLength = width * height * 3;

            byte[] buff = new byte[totalLength * 2];


            if (buffR.Count() < pixelCount * 2)
            {
                this.Dispatcher.Invoke(() =>
                {
                    MessageBox.Show("Red file too short: " + srcRGBTriplet[0]);
                });
                return;
            }
            if (buffG.Count() < pixelCount * 2)
            {
                this.Dispatcher.Invoke(() =>
                {
                    MessageBox.Show("Green file too short: " + srcRGBTriplet[1]);
                });
                return;
            }
            if (buffB.Count() < pixelCount * 2)
            {
                this.Dispatcher.Invoke(() =>
                {
                    MessageBox.Show("Blue file too short: " + srcRGBTriplet[2]);
                });
                return;
            }

            for (int pixelIndex = 0; pixelIndex < pixelCount; pixelIndex++)
            {
                /*
                 * // BGR
                 * buff[pixelIndex * 3 * 2] = buffB[pixelIndex * 2];
                 * buff[pixelIndex * 3 * 2 + 1] = buffB[pixelIndex * 2 + 1];
                 * buff[pixelIndex * 3 * 2 +4] = buffR[pixelIndex*2];
                 * buff[pixelIndex * 3 * 2 +5] = buffR[pixelIndex * 2 + 1];
                 * buff[pixelIndex * 3 * 2 +2] = buffG[pixelIndex * 2];
                 * buff[pixelIndex * 3 * 2 +3] = buffG[pixelIndex * 2 + 1];
                 */
                // RGB
                buff[pixelIndex * 3 * 2]     = buffR[pixelIndex * 2];
                buff[pixelIndex * 3 * 2 + 1] = buffR[pixelIndex * 2 + 1];
                buff[pixelIndex * 3 * 2 + 2] = buffG[pixelIndex * 2];
                buff[pixelIndex * 3 * 2 + 3] = buffG[pixelIndex * 2 + 1];
                buff[pixelIndex * 3 * 2 + 4] = buffB[pixelIndex * 2];
                buff[pixelIndex * 3 * 2 + 5] = buffB[pixelIndex * 2 + 1];
            }



            string fileName = targetFilename;

            if (targetFormat == TARGETFORMAT.EXR)
            {
                ResourceLimits.Thread = (ulong)maxThreads;
                ResourceLimits.LimitMemory(new Percentage(90));

                MagickReadSettings settings = new MagickReadSettings();
                settings.Width  = width;
                settings.Height = height;
                settings.Format = MagickFormat.Rgb; // Correction, this is actually right, I had flipped RGB to BGR elsewhere in the code before. Fixed now.

                /*ColorManager.ICC.ICCProfileWriter iccWriter = new ColorManager.ICC.ICCProfileWriter();
                 * iccWriter.WriteProfile(new ColorManager.ICC.ICCProfile());
                 */

                if (EXRIntegrityVerification)
                {
                    /*
                     * Info on half float format: https://www.openexr.com/about.html
                     */
                    // What does this mean for precision of converting 16 bit integers to 16 bit floating point?
                    // We need to know the maximum precision achievable to be able to tell rounding errors from actual integrity fails.
                    // More info here: https://en.wikipedia.org/wiki/Half-precision_floating-point_format
                    // Basically, precision at any given value is 11 bits or 2048 values.


                    int  integrityCheckFailCountLocal = 0;
                    bool integrityCheckPassed         = false;
                    bool retriesExhausted             = false;
                    while (!integrityCheckPassed && !retriesExhausted)
                    {
                        using (var image = new MagickImage(buff, settings))
                        {
                            //ExifProfile profile = new ExifProfile();
                            //profile.SetValue(ExifTag.UserComment, Encoding.ASCII.GetBytes(srcRGBTriplet[0] + "," + srcRGBTriplet[1] + "," + srcRGBTriplet[2]));
                            //image.SetProfile(profile);
                            image.Format = MagickFormat.Exr;
                            image.Settings.Compression = CompressionMethod.Piz;

                            //image.Write(fileName);

                            byte[] exrFile = image.ToByteArray();

                            bool integrityCheckFailed = false;
                            using (var reloadedImage = new MagickImage(exrFile))
                            {
                                reloadedImage.Depth      = 16;
                                reloadedImage.ColorSpace = ColorSpace.Undefined;
                                byte[] reloadedImageBytes = reloadedImage.ToByteArray(MagickFormat.Rgb);

                                integrityCheckFailed = integrityCheckFailed | !IntegrityChecker.VerifyIntegrityUInt16InHalfPrecisionFloat(buff, reloadedImageBytes);
                            }
                            if (integrityCheckFailed)
                            {
                                integrityCheckFailCount++;
                                integrityCheckFailCountLocal++;
                                continue;
                            }
                            else
                            {
                                integrityCheckPassed = true;
                                File.WriteAllBytes(fileName, exrFile);
                            }
                            if (integrityCheckFailCountLocal > integrityCheckRetries)
                            {
                                retriesExhausted = true;
                                // At this point just write it into a subfolder and be done with it.
                                string failedFolder = Path.GetDirectoryName(fileName) + Path.DirectorySeparatorChar + "FAILED" + Path.DirectorySeparatorChar;
                                Directory.CreateDirectory(failedFolder);
                                string failedFile = failedFolder + Path.GetFileName(fileName);

                                File.WriteAllBytes(failedFile, exrFile);
                            }
                        }
                    }
                }
                else
                {
                    using (var image = new MagickImage(buff, settings))
                    {
                        //ExifProfile profile = new ExifProfile();
                        //profile.SetValue(ExifTag.UserComment, Encoding.ASCII.GetBytes(srcRGBTriplet[0] + "," + srcRGBTriplet[1] + "," + srcRGBTriplet[2]));
                        //image.SetProfile(profile);
                        image.Format = MagickFormat.Exr;
                        image.Settings.Compression = CompressionMethod.Piz;

                        //image.Write(fileName);
                        byte[] exrFile = image.ToByteArray();
                        File.WriteAllBytes(fileName, exrFile);
                    }
                }
            }
            else if (targetFormat == TARGETFORMAT.TIF)
            {
                using (Tiff output = Tiff.Open(fileName, "w"))
                {
                    output.SetField(TiffTag.SUBFILETYPE, 0);
                    //output.SetField(TiffTag.ORIGINALRAWFILENAME, srcRGBTriplet[0]+","+srcRGBTriplet[1]+","+srcRGBTriplet[2]);
                    output.SetField(TiffTag.IMAGEWIDTH, width);
                    output.SetField(TiffTag.IMAGELENGTH, height);
                    output.SetField(TiffTag.SAMPLESPERPIXEL, 3);
                    output.SetField(TiffTag.BITSPERSAMPLE, 16);
                    output.SetField(TiffTag.ORIENTATION, Orientation.TOPLEFT);
                    output.SetField(TiffTag.PHOTOMETRIC, Photometric.RGB);
                    output.SetField(TiffTag.FILLORDER, FillOrder.MSB2LSB);
                    output.SetField(TiffTag.COMPRESSION, Compression.DEFLATE);

                    output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);


                    output.WriteEncodedStrip(0, buff, width * height * 2 * 3);
                }
            }
        }