/// <summary>Converts all bitmaps with the base name and animation postfixes to pngs.</summary> /// <exception cref="ExtractHg3Exception">An error occurred while trying to /// convert, save, or delete.</exception> public static void BmpToPng(string bmpFile, Hg3Sorting sorting, string unsortedDir, string sortedDir) { Exception exception = null; try { TryCopyPng(bmpFile, sorting, unsortedDir, sortedDir); } catch (ExtractHg3Exception ex) { exception = ex; } try { TryDeleteBmp(bmpFile); } catch (ExtractHg3Exception ex) { if (exception == null) { exception = ex; } } if (exception != null) { throw exception; } }
/// <summary>Attempts to convert the .bmp file to a .png up to MaxRetries times.</summary> /// <exception cref="ExtractHg3Exception">An error occurred while trying to /// convert or save.</exception> private static void TryCopyPng(string oldFile, Hg3Sorting sorting, string unsortedDir, string sortedDir) { Exception exception = null; for (int retries = 0; retries < MaxRetries; retries++) { try { // Wait a moment in hopes of file access returning if (retries > 0) { Thread.Sleep(100); } /*string fileName = Path.GetFileName(bmpFile); * byte[] B = File.ReadAllBytes(bmpFile); * GCHandle GCH = GCHandle.Alloc(B, GCHandleType.Pinned); * try { * IntPtr Scan0 = (IntPtr) ((int) (GCH.AddrOfPinnedObject()) + 54); * int W = Marshal.ReadInt32(Scan0, -36); * int H = Marshal.ReadInt32(Scan0, -32); * using (Bitmap bitmap = new Bitmap(W, H, 4 * W, PixelFormat.Format32bppArgb, Scan0)) { * bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); * GCH.Free(); * if (sorting.HasFlag(ExtractHg3Sorting.Unsorted)) * TrySavePng(bitmap, unsortedDir, fileName); * if (sorting.HasFlag(ExtractHg3Sorting.Sorted)) * TrySavePng(bitmap, sortedDir, fileName); * return; * }*/ string fileName = Path.GetFileName(oldFile); if (sorting.HasFlag(Hg3Sorting.Unsorted)) { File.Copy(oldFile, Path.Combine(unsortedDir, fileName), true); } if (sorting.HasFlag(Hg3Sorting.Sorted)) { File.Copy(oldFile, Path.Combine(sortedDir, fileName), true); } return; } catch (ExtractHg3Exception) { throw; } catch (UnauthorizedAccessException ex) { exception = ex; } catch (IOException ex) { exception = ex; } catch (Exception ex) { exception = ex; break; } } throw new ExtractHg3Exception( ExtractHg3Result.BmpConvertFailed, oldFile, exception); }
/// <summary>Extracts all .hg3 files that meet the pattern into .png's.</summary> public static ImageIdentifier ExtractHg3s(string inputDir, string outputDir, Hg3Sorting sorting, string pattern, Hgx2pngCallback progressCallback, Hgx2pngErrorCallback errorCallback, string continueFile = null, string[] remainingFiles = null) { ImageIdentifier identifier = new ImageIdentifier(); DateTime startTime = DateTime.UtcNow; string unsortedDir = outputDir; if (sorting.HasFlag(Hg3Sorting.Both)) { unsortedDir = Path.Combine(unsortedDir, "Unsorted"); } Directory.CreateDirectory(unsortedDir); if (string.IsNullOrWhiteSpace(pattern)) { pattern = "*.hg3"; } else if (!pattern.EndsWith(".hg3", StringComparison.OrdinalIgnoreCase) && !pattern.EndsWith(".hg3*", StringComparison.OrdinalIgnoreCase)) { pattern += ".hg3"; } string[] files = Directory.GetFiles(inputDir, pattern); int fileCount = files.Length; Hgx2pngArgs args = new Hgx2pngArgs() { FileCount = fileCount, }; // Skip files if we're continuing from a later point int start = 0; if (continueFile != null) { for (start = 0; start < fileCount; start++) { if (string.Compare(files[start], continueFile, true) >= 0) { break; } } } // Remove non-remaining files. // This will be used for retrying files that had errors. if (remainingFiles != null) { List <string> fileList = new List <string>(files); int remainIndex = 0; int remainCount = remainingFiles.Length; for (int i = 0; i < fileList.Count && remainIndex < remainCount && (continueFile == null || i < start); i++) { if (PathHelper.IsPathTheSame( remainingFiles[remainIndex], fileList[i])) { fileList.RemoveAt(i); if (continueFile != null) { start--; } i--; remainIndex++; } } files = fileList.ToArray(); } DateTime lastRefresh = DateTime.MinValue; Stopwatch writeTime = new Stopwatch(); TimeSpan refreshTime = TimeSpan.FromMilliseconds(20); //Stopwatch processTime = new Stopwatch(); for (int i = start; i < fileCount; i++) { string file = files[i]; string name = Path.GetFileNameWithoutExtension(file); args.FileIndex = i; args.FileName = name; args.FilePath = file; args.Ellapsed = DateTime.UtcNow - startTime; // Round to nearest hundredth args.Percent = Math.Round((double)i / fileCount * 10000) / 100; // If true, cancel operation TimeSpan sinceRefresh = DateTime.UtcNow - lastRefresh; if (sinceRefresh >= refreshTime) { lastRefresh = DateTime.UtcNow; writeTime.Start(); if (progressCallback?.Invoke(args) ?? false) { return(identifier); } writeTime.Stop(); } //processTime.Restart(); List <Exception> exceptions = new List <Exception>(); string[] bmps; try { //bmps = Hg3Convert.UnpackHg3(file, null, true); ImageIdentification image = identifier.PreIdentifyImage(file); bmps = Extracting.Hg3ToBmp(file, image.ExpandImage); image = identifier.IdentifyImage(bmps); string sortedDir = Path.Combine(outputDir, image.OutputDirectory); if (sorting.HasFlag(Hg3Sorting.Sorted)) { Directory.CreateDirectory(sortedDir); } for (int j = 0; j < bmps.Length; j++) { try { BmpToPng(bmps[j], sorting, unsortedDir, sortedDir); } catch (ExtractHg3Exception ex) { exceptions.Add(ex); } } //processTime.Stop(); //if (processTime.ElapsedMilliseconds >= 500) // Trace.WriteLine($"Large File: {new FileInfo(file).Length / 1024:###,###,###,###}KB [{processTime.ElapsedMilliseconds}ms]"); } catch (ExtractHg3Exception ex) { exceptions.Add(ex); } foreach (Exception ex in exceptions) { args.TotalErrors++; // If true, cancel operation if (errorCallback?.Invoke(ex, args) ?? false) { return(identifier); } } } args.Ellapsed = DateTime.UtcNow - startTime; args.Percent = 100.0; progressCallback?.Invoke(args); Trace.WriteLine($"Console Write Time: {writeTime.Elapsed:mm\\:ss\\.fff}"); return(identifier); }