private void DrawIMImage(Container imc, List <IMImageCell> cells, float xStartingInch, float yStartingInch, PrintPageEventArgs e) { Bitmap png = IMImageCell.GenerateBitmap(imc.GetStructure <IID>(), cells); IID descriptor = imc.GetStructure <IID>(); int xPos = cells.Min(c => c.CellPosition.XOffset); int yPos = cells.Min(c => c.CellPosition.YOffset); float xInchPos = xStartingInch + (float)(Converters.GetInches(xPos, descriptor.XUnitsPerBase, descriptor.BaseUnit) * 100); float yInchPos = yStartingInch + (float)(Converters.GetInches(yPos, descriptor.YUnitsPerBase, descriptor.BaseUnit) * 100); e.Graphics.DrawImage(png, xInchPos, yInchPos); }
private void btnPreview_Click(object sender, EventArgs e) { // Only display a print preview if it's a paged document. Otherwise, display an image from the page segment if we can switch (DocType) { case eFileType.Document: // Verify they want to view if there are missing resources if (afpFile.Resources.All(r => r.IsLoaded || r.IsNETCodePage) || MessageBox.Show("There are referenced resources that have not been located. Preview anyway?" , "Missing Resources", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes) { // Set up a print preview dialog and wire it to our print parser's build event PrintPreviewDialog ppd = new PrintPreviewDialog() { Document = new PrintDocument() { DocumentName = opts.LastOpenedFile } }; ppd.Controls.OfType <ToolStrip>().First().Items["printToolStripButton"].Visible = false; // Temp disable until we actually might want to print something ((Form)ppd).WindowState = FormWindowState.Maximized; ppd.Document.PrintPage += printParser.BuildPrintPage; // Set page size by checking the first PGD. Width and height are in 1/100 inch PGD pgd = afpFile.Fields.OfType <PGD>().First(); int xWidth = (int)(Converters.GetInches((int)pgd.XSize, pgd.UnitsPerXBase, pgd.BaseUnit) * 100); int yWidth = (int)(Converters.GetInches((int)pgd.YSize, pgd.UnitsPerYBase, pgd.BaseUnit) * 100); ppd.Document.DefaultPageSettings.PaperSize = new PaperSize("Custom", xWidth, yWidth); ppd.ShowDialog(); } break; case eFileType.IOCAImage: case eFileType.IMImage: int fileCounter = 1; if (afpFile.ParsedImages.Any() || afpFile.ParsedIMImages.Any()) { Cursor = Cursors.WaitCursor; // Clear out the directory of existing pngs foreach (string file in Directory.GetFiles(Environment.CurrentDirectory)) { if (new FileInfo(file).Extension.ToUpper() == ".PNG") { File.Delete(file); } } // Generate a .png from the image data and save it to the exe directory if (DocType == eFileType.IOCAImage) { foreach (KeyValuePair <Container, IReadOnlyList <ImageInfo> > kvp in afpFile.ParsedImages) { foreach (ImageInfo image in kvp.Value) { Bitmap png = new Bitmap(new MemoryStream(image.Data)); // Get resolution from descriptor IDD descriptor = kvp.Key.GetStructure <IDD>(); float xScale = (float)Converters.GetInches(png.Width, descriptor.HResolution, descriptor.BaseUnit); float yScale = (float)Converters.GetInches(png.Height, descriptor.VResolution, descriptor.BaseUnit); png.SetResolution(png.Width / xScale, png.Height / yScale); // Generate image png.Save($"{Environment.CurrentDirectory}\\Image {fileCounter++}.png", System.Drawing.Imaging.ImageFormat.Png); } } } else { foreach (KeyValuePair <Container, IReadOnlyList <IMImageCell> > kvp in afpFile.ParsedIMImages) { IMImageCell.GenerateBitmap(kvp.Key.GetStructure <IID>(), kvp.Value.ToList()) .Save($"{Environment.CurrentDirectory}\\Image {fileCounter++}.png", System.Drawing.Imaging.ImageFormat.Png); } } btnPreview.Enabled = false; Cursor = Cursors.Default; if (MessageBox.Show($"{fileCounter} image(s) created in executing directory. Open directory?", "Images Created", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question) == DialogResult.Yes) { System.Diagnostics.Process.Start(Environment.CurrentDirectory); } } else { MessageBox.Show("No image containers found, though this does appear to be an image file."); } break; } }
private void ParseFontAndImageData() { // FONT RASTER PATTERNS Dictionary <Container, IReadOnlyDictionary <FNI.Info, bool[, ]> > rasterPatterns = new Dictionary <Container, IReadOnlyDictionary <FNI.Info, bool[, ]> >(); foreach (Container c in Resources.Where(r => r.ResourceType == Resource.eResourceType.FontCharacterSet && r.IsLoaded) .Select(r => r.Fields[0].LowestLevelContainer)) { // If we have a pattern map, gather raster data FNM patternsMap = c.GetStructure <FNM>(); if (patternsMap != null) { FNI firstFNI = c.GetStructure <FNI>(); Dictionary <FNI.Info, bool[, ]> patternsDictionary = new Dictionary <FNI.Info, bool[, ]>(); byte[] allFNGData = c.GetStructures <FNG>().SelectMany(f => f.Data).ToArray(); int indexCounter = 0; for (int i = 0; i < patternsMap.AllPatternData.Count; i++) { // Subtract the next offset (or length of data if at end) by this one to find out how many bytes to take int bytesToTake = (int)((i < patternsMap.AllPatternData.Count - 1 ? patternsMap.AllPatternData[i + 1].DataOffset : (uint)allFNGData.Length) - patternsMap.AllPatternData[i].DataOffset); // Create an empty array of bools from our box width and height // The array sizes are the number of bits in the minimum number of bytes required to support the bit size int numBitsWide = (int)Math.Ceiling((patternsMap.AllPatternData[i].BoxMaxWidthIndex + 1) / 8.0) * 8; int numRows = bytesToTake / (numBitsWide / 8); bool[,] curPattern = new bool[numBitsWide, numRows]; for (int y = 0; y < numRows; y++) { for (int x = 0; x < numBitsWide; x += 8) { byte curByte = allFNGData[indexCounter++]; for (int b = 0; b < 8; b++) { curPattern[x + b, y] = (curByte & (1 << (7 - b))) > 0; } } } // Lookup the GCGID from the first FNI for this pattern patternsDictionary.Add(firstFNI.InfoList.First(fni => fni.FNMIndex == i), curPattern); } rasterPatterns.Add(c, patternsDictionary); } } ParsedFontPatterns = rasterPatterns; // IM IMAGES Dictionary <Container, IReadOnlyList <IMImageCell> > imImages = new Dictionary <Container, IReadOnlyList <IMImageCell> >(); foreach (Container c in Resources .Where(r => r.IsLoaded && (r.ResourceType == Resource.eResourceType.IMImage || (r.ResourceType == Resource.eResourceType.PageSegment && r.Fields[1] is BII))) .Select(r => r.ResourceType == Resource.eResourceType.PageSegment ? r.Fields[1].LowestLevelContainer : r.Fields[0].LowestLevelContainer)) { IID imageDescriptor = c.GetStructure <IID>(); List <IMImageCell> cellList = new List <IMImageCell>(); if (c.GetStructure <ICP>() == null) { // Since there are no cells, create one ICP newCellPos = new ICP(imageDescriptor.XSize, imageDescriptor.YSize); IMImageCell newCell = new IMImageCell(newCellPos, c.GetStructures <IRD>()); cellList.Add(newCell); } else { // Manually parse a list of cells since they don't have their own container for (int i = 0; i < c.Structures.Count; i++) { if (c.Structures[i].GetType() != typeof(ICP)) { continue; } // Get list of IRDs up to the next ICP or end of structures List <IRD> rasterData = new List <IRD>(); for (int r = i + 1; r < c.Structures.Count; r++) { if (c.Structures[r].GetType() != typeof(IRD)) { break; } rasterData.Add((IRD)c.Structures[r]); } cellList.Add(new IMImageCell((ICP)c.Structures[i], rasterData)); } } imImages.Add(c, cellList); } ParsedIMImages = imImages; // IOCA IMAGES Dictionary <Container, IReadOnlyList <ImageInfo> > iocaImages = new Dictionary <Container, IReadOnlyList <ImageInfo> >(); foreach (Container c in Resources .Where(r => r.IsLoaded && (r.ResourceType == Resource.eResourceType.IOCAImage || (r.ResourceType == Resource.eResourceType.PageSegment && r.Fields[1] is BIM))) .Select(r => r.ResourceType == Resource.eResourceType.PageSegment ? r.Fields[1].LowestLevelContainer : r.Fields[0].LowestLevelContainer)) { // Combine all self defining fields from zero or more IPD fields byte[] allIPDData = c.GetStructures <IPD>().SelectMany(f => f.Data).ToArray(); List <ImageSelfDefiningField> SDFs = ImageSelfDefiningField.GetAllSDFs(allIPDData); // Get all images in our self defining field list foreach (Container sc in SDFs.OfType <BeginImageContent>().Select(s => s.LowestLevelContainer)) { List <Container> allContainers = new List <Container>() { sc }; List <ImageInfo> infoList = new List <ImageInfo>(); // Along with ourself, add any tiles to the list of containers if (sc.Structures.Any(s => s.GetType() == typeof(BeginTile))) { allContainers.AddRange(sc.Structures.OfType <BeginTile>().Select(s => s.LowestLevelContainer)); } // For each container, get image and transparency bytes foreach (Container tc in allContainers) { ImageInfo info = new ImageInfo(); info.Data = tc.DirectGetStructures <ImageData>().SelectMany(s => s.Data).ToArray(); // If there are tiles, store offset information if (tc.Structures[0].GetType() == typeof(BeginTile)) { TilePosition tp = tc.GetStructure <TilePosition>(); info.XOffset = tp.XOffset; info.YOffset = tp.YOffset; } // Add transparency data if needed ImageSelfDefiningField BTM = tc.GetStructure <BeginTransparencyMask>(); if (BTM != null) { info.TransparencyMask = BTM.LowestLevelContainer.GetStructures <ImageData>().SelectMany(s => s.Data).ToArray(); } infoList.Add(info); } iocaImages.Add(c, infoList); } } ParsedImages = iocaImages; }