コード例 #1
0
        private void SaveBitmapsAsFont()
        {
            // Open each bitmap, and convert pure black pixels to an array of bools
            List <CharInfo> charInfos = new List <CharInfo>();

            foreach (FileInfo f in new DirectoryInfo(Path.Combine(Environment.CurrentDirectory, "..\\..\\..\\Sample Files\\Barcode Chars")).GetFiles())
            {
                Bitmap png      = new Bitmap(f.FullName);
                char   thisChar = f.Name == "Asterisk.png" ? '*' : f.Name[0];
                bool[,] boolVals = new bool[png.Width + 1, png.Height];

                for (int y = 0; y < png.Height; y++)
                {
                    for (int x = 0; x < png.Width; x++)
                    {
                        boolVals[x + 1, y] = png.GetPixel(x, y).GetBrightness() < 0.5;
                    }
                }

                charInfos.Add(new CharInfo(thisChar, boolVals));
            }

            // Create an AFP font file (BFN, FND, FNC, FNM, FNO, FNP, FNIs, FNGs, EFN) using bool arrays as FNGs
            BFN newBFN = new BFN("BARCOD39");

            FND newFND = new FND("Code 39 Barcode", 172);

            ushort maxBitsWideIdx   = (ushort)(charInfos.Max(c => c.BitWidth) - 1);
            ushort maxBitsTallIdx   = (ushort)(charInfos.Max(c => c.BitHeight) - 1);
            int    totalRasterBytes = charInfos.Sum(c => c.RoundedBitWidth * c.BitHeight);
            FNC    newFNC           = new FNC(maxBitsWideIdx, maxBitsTallIdx, totalRasterBytes);

            uint curFNMIndex = 0;
            List <FNM.PatternData> fnmPatData = new List <FNM.PatternData>();

            foreach (CharInfo c in charInfos)
            {
                fnmPatData.Add(new FNM.PatternData((ushort)(c.BitWidth - 1), (ushort)(c.BitHeight - 1), curFNMIndex));
                curFNMIndex += (uint)((c.RoundedBitWidth * c.BitHeight) / 8);
            }
            FNM newFNM = new FNM(fnmPatData);

            List <FNO.Info> fnoInfos   = new List <FNO.Info>();
            ushort          maxCharInc = charInfos.Max(c => c.CharIncrement);

            for (int i = 0; i < 4; i++)
            {
                Type eType = typeof(CommonMappings.eRotations);
                CommonMappings.eRotations curRot = (CommonMappings.eRotations)Enum.Parse(eType, Enum.GetNames(eType)[i]);
                ushort curBaseline           = (i == 0 || i == 2) ? (ushort)1000 : maxCharInc;
                ushort curCharInc            = (i == 0 || i == 2) ? maxCharInc : (ushort)1000;
                FNO.Info.eControlFlags flags = i == 0 ? 0 : i == 1 ? FNO.Info.eControlFlags.FNI1 : i == 2 ? FNO.Info.eControlFlags.FNI2 : FNO.Info.eControlFlags.FNI3;
                fnoInfos.Add(new FNO.Info(curRot, (short)curBaseline, curCharInc, 0, curBaseline, flags, 1000, curCharInc, curCharInc, curBaseline, 0));
            }
            FNO newFNO = new FNO(fnoInfos);

            List <FNP.Info> fnpInfos = new List <FNP.Info>();

            for (int i = 0; i < 4; i++)
            {
                short curAsc = (short)((i == 0 || i == 2) ? maxCharInc : 1000);
                fnpInfos.Add(new FNP.Info(1000, 1000, curAsc, 0, 1000, 100));
            }
            FNP newFNP = new FNP(fnpInfos);

            List <FNI> newFNIs = new List <FNI>();

            for (int i = 0; i < 4; i++)
            {
                ushort fnmIndex = 0;

                List <FNI.Info> fniInfos = new List <FNI.Info>();
                foreach (CharInfo c in charInfos)
                {
                    string gid          = CodePages.C1140[Converters.EBCDIC.GetBytes(new[] { c.Character })[0]];
                    ushort curCharInc   = (ushort)((i == 0 || i == 2) ? c.CharIncrement : 1000);
                    short  curAscHeight = (short)((i == 0 || i == 2) ? 1000 : c.CharIncrement);
                    fniInfos.Add(new FNI.Info(gid, c.CharIncrement, curAscHeight, 0, fnmIndex++, 0, curCharInc, 0, curAscHeight));
                }
                newFNIs.Add(new FNI(fniInfos));
            }

            List <byte> fngBytes = new List <byte>();

            foreach (CharInfo c in charInfos)
            {
                for (int y = 0; y < c.BitHeight; y++)
                {
                    for (int x = 0; x < c.BitWidth; x += 8)
                    {
                        int[]       curByte = new int[1];
                        List <bool> bitRow  = new List <bool>();
                        for (int i = 0; i < 8; i++)
                        {
                            if (c.RawBits.GetUpperBound(0) >= x + i)
                            {
                                bitRow.Add(c.RawBits[x + i, y]);
                            }
                            else
                            {
                                bitRow.Add(false);
                            }
                        }
                        if (BitConverter.IsLittleEndian)
                        {
                            bitRow.Reverse();
                        }
                        new BitArray(bitRow.ToArray()).CopyTo(curByte, 0);
                        fngBytes.Add((byte)curByte[0]);
                    }
                }
            }
            FNG newFNG = new FNG(fngBytes.ToArray());

            EFN newEFN = new EFN(newBFN.ObjectName);

            string path = Path.Combine(Environment.CurrentDirectory, "..\\..\\..\\Sample Files\\FONTS\\FONTTEST");
            List <StructuredField> fields = new List <StructuredField>()
            {
                newBFN, newFND, newFNC, newFNM, newFNO, newFNP
            };

            fields.AddRange(newFNIs);
            fields.AddRange(new StructuredField[] { newFNG, newEFN });
            List <byte> encoded = new List <byte>();

            foreach (StructuredField field in fields)
            {
                encoded.Add(0x5A);
                encoded.AddRange(field.Introducer);
                encoded.AddRange(field.Data);
            }
            File.WriteAllBytes(path, encoded.ToArray());
        }
コード例 #2
0
        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;
        }