Пример #1
0
 public static TAMImageDiagram Combine(TAMImageDiagram first, TAMImageDiagram second)
 {
     return(new TAMImageDiagram()
     {
         _strokes = new List <TAMStroke>(first.Strokes).Union(second.Strokes).ToList()
     });
 }
        public TAMImageDiagram Generate(TAMImageDiagram baseDiagram, TAMTone tone, TAMMipmapLevel mipmapLevel, int seed)
        {
            _strokesGenerator.ResetSeed(seed);
            _random = new System.Random(seed);

            var   diagram         = baseDiagram.Copy();
            float currentCoverage = ComputeCoverage(diagram, mipmapLevel);
            float targetCoverage  = _generationConfiguration.TargetCoverages[tone];

            while (targetCoverage > currentCoverage)
            {
                List <RankedPossibleStroke> possibleStrokes = new List <RankedPossibleStroke>();
                for (int i = 0; i < _generationConfiguration.TriesCount[mipmapLevel]; i++)
                {
                    TAMStroke            newStroke       = _strokesGenerator.CreateRandomStroke(new Vector2(_random.Next(), _random.Next()), tone);
                    RankedPossibleStroke rankedNewStroke = RankStroke(newStroke, diagram);
                    possibleStrokes.Add(rankedNewStroke);
                }

                var bestStroke = possibleStrokes.OrderBy(p => p.Rank).First();
                diagram.AddStroke(bestStroke.Stroke);
                currentCoverage = ComputeCoverage(diagram, mipmapLevel);
            }

            return(diagram);
        }
        public TAMImageDiagram Generate(TAMImageDiagram diagram, TAMTone tone, TAMMipmapLevel mipmapLevel, int seed)
        {
            List <Vector2> currentPoints = diagram.Strokes.Select(c => c.Center).ToList();
            var            newPoints     = _sampler.Generate(_configuration.GenerationCount, _configuration.ExclusionZoneValues[tone][mipmapLevel],
                                                             seed, currentPoints);

            return(new TAMImageDiagram(diagram.Strokes.Union(newPoints.Select(c => _strokesGenerator.CreateRandomStroke(c, tone))).ToList()));
        }
Пример #4
0
 private TAMImageDiagram GetPreviousToneImageDiagram(TAMTone tone, TAMMipmapLevel mipmapLevel)
 {
     if (tone.IsLowestTone)
     {
         return(TAMImageDiagram.CreateEmpty());
     }
     else
     {
         return(_columns[tone.LowerTone][mipmapLevel]);
     }
 }
Пример #5
0
        private Image CreateSoleImage(TAMImageDiagram diagram, TAMMipmapLevel level)
        {
            var margin = _configuration.Margin;
            var soleImageResolution            = _configuration.SoleImagesResolutionPerLevel[level].ToFloatVec();
            var soleImageResolutionWithMargins = soleImageResolution * (1 + margin * 2);

            using (ImageFactory imageFactory = new ImageFactory(preserveExifData: true))
            {
                var factory = imageFactory.Load(_blankImage)
                              .Resize(new Size((int)soleImageResolutionWithMargins.x, (int)soleImageResolutionWithMargins.y));
                foreach (var stroke in diagram.Strokes)
                {
                    using (ImageFactory strokeFactory = new ImageFactory(true))
                    {
                        var strokeSizeInPixels = VectorUtils.MemberwiseMultiply(
                            new Vector2(stroke.Length, stroke.Height * _configuration.StrokeHeightMultiplierPerLevel[level]), soleImageResolution).ToIntVector2();
                        var rotation = Mathf.Rad2Deg * stroke.Rotation;

                        var rotatedStrokeImageFactory = strokeFactory.Load(_strokeImage)
                                                        .Resize(new ResizeLayer(new Size(strokeSizeInPixels.X, strokeSizeInPixels.Y), ResizeMode.Stretch))
                                                        .Rotate(rotation);
                        //if (stroke.Id == 1)
                        //{
                        //    rotatedStrokeImageFactory = rotatedStrokeImageFactory.ReplaceColor(Color.Black, Color.Blue);
                        //}

                        var rotatedStrokeImage = rotatedStrokeImageFactory.Image;
                        var position           = VectorUtils.MemberwiseMultiply(UvToMarginUv(stroke.Center), soleImageResolutionWithMargins).ToIntVector2();
                        //todo przelicz tu aby brac pod uwage multiplier
                        position -= new IntVector2(rotatedStrokeImage.Width / 2, rotatedStrokeImage.Height / 2);

                        factory = factory.Overlay(new ImageLayer()
                        {
                            Image    = rotatedStrokeImage,
                            Opacity  = 100,
                            Position = new Point(position.X, position.Y)
                        });
                    }
                }

                using (Stream stream = new MemoryStream())
                {
                    factory.Save(stream);
                    return(Image.FromStream(stream));
                }
            }
        }
        private float ComputeCoverage(TAMImageDiagram diagram, TAMMipmapLevel mipmapLevel)
        {
            var areaSum = 0.0;

            for (int i = 0; i < diagram.Strokes.Count; i++)
            {
                var currentStroke = diagram.Strokes[i];
                var baseArea      = Mathf.PI * Mathf.Pow(currentStroke.Length, 2) * 0.2; //todo

                for (int k = 0; k < i; k++)
                {
                    var otherStroke      = diagram.Strokes[k];
                    var intersectionArea =
                        MyMathUtils.IntersectionAreaOfTwoCircles(currentStroke.Length, currentStroke.Center, otherStroke.Length, otherStroke.Center);
                    baseArea -= intersectionArea;
                }

                areaSum += Math.Max(0.001f, baseArea); //todo what to do with other mipmapLevels
            }
            return((float)areaSum);
        }
        private RankedPossibleStroke RankStroke(TAMStroke newStroke, TAMImageDiagram diagram)
        {
            // rank the bigger, the better
            var distanceSum      = 0f;
            var intersectionArea = 0f;

            foreach (var stroke in diagram.Strokes)
            {
                var intersection = MyMathUtils.IntersectionAreaOfTwoCircles(newStroke.Length, newStroke.Center, stroke.Length, stroke.Center);
                intersectionArea += intersection;
                distanceSum      += Vector2.Distance(newStroke.Center, stroke.Center);
            }

            var intersectionPercent = intersectionArea / (Math.PI * Math.Pow(newStroke.Length, 2));

            var rank = Mathf.Pow(distanceSum, (float)(2 - intersectionPercent));

            return(new RankedPossibleStroke()
            {
                Rank = rank,
                Stroke = newStroke
            });
        }
Пример #8
0
        public TAMTemplate Generate(TAMTemplateSpecification specification)
        {
            _specification = specification;
            _columns       = new Dictionary <TAMTone, Dictionary <TAMMipmapLevel, TAMImageDiagram> >();

            var seed = 0; //TODO

            foreach (var tone in _specification.Tones)
            {
                _columns[tone] = new Dictionary <TAMMipmapLevel, TAMImageDiagram>();
                foreach (var mipmapLevel in _specification.MipmapLevels)
                {
                    var previousToneImageDiagram  = GetPreviousToneImageDiagram(tone, mipmapLevel);
                    var previousLevelImageDiagram = GetPreviousLevelImageDiagram(tone, mipmapLevel);
                    var sumImageDiagram           = TAMImageDiagram.Combine(previousLevelImageDiagram, previousToneImageDiagram);
                    var newImageDiagram           = GenerateNewImageDiagram(sumImageDiagram, tone, mipmapLevel, seed);
                    AddNewImageDiagram(newImageDiagram, tone, mipmapLevel);
                    seed++;
                }
            }

            UpdatePerMipmapLevelStrokeParameters();
            return(new TAMTemplate(_columns));
        }
 public TAMImageDiagram UpdatePerMipmapLevelStrokeParameters(TAMImageDiagram diagram, TAMMipmapLevel level)
 {
     return(new TAMImageDiagram(diagram.Strokes.Select(c => _strokesGenerator.UpdatePerMipmapLevelStrokeParameters(c, level)).ToList()));
 }
Пример #10
0
 private void AddNewImageDiagram(TAMImageDiagram template, TAMTone tone, TAMMipmapLevel mipmapLevel)
 {
     _columns[tone][mipmapLevel] = template;
 }
Пример #11
0
 private TAMImageDiagram GenerateNewImageDiagram(TAMImageDiagram baseImageDiagram, TAMTone tone, TAMMipmapLevel mipmapLevel, int seed)
 {
     return(_imageDiagramGenerator.Generate(baseImageDiagram, tone, mipmapLevel, seed));
 }
Пример #12
0
        private List <Image> CreateSoleLayerImages(TAMImageDiagram diagram, TAMMipmapLevel level)
        {
            var margin = _configuration.Margin;
            var soleImageResolution            = _configuration.SoleImagesResolutionPerLevel[level];
            var soleImageResolutionWithMargins = (soleImageResolution * (1 + margin * 2)).ToIntVector2();
            var marginLength = (soleImageResolutionWithMargins - soleImageResolution) / 2;

            var outImages = Enumerable.Range(0, _layersCount)
                            .Select(c => new Bitmap((int)soleImageResolutionWithMargins.X, (int)soleImageResolutionWithMargins.Y, PixelFormat.Format32bppPArgb))
                            .ToList();

            var occupancyArray = new int[(int)soleImageResolutionWithMargins.X, (int)soleImageResolutionWithMargins.Y];

            //Debug.Log($"OutiMages: {outImages[0].Size} || SoleImageResolution {soleImageResolution} Sole with margins {soleImageResolutionWithMargins}");
            foreach (var stroke in diagram.Strokes)
            {
                using (ImageFactory strokeFactory = new ImageFactory(true))
                {
                    var strokeSizeInPixels = VectorUtils.MemberwiseMultiply(
                        new Vector2(stroke.Length, stroke.Height * _configuration.StrokeHeightMultiplierPerLevel[level]), soleImageResolution.ToFloatVec()).ToIntVector2();
                    var rotation = Mathf.Rad2Deg * stroke.Rotation;

                    var rotatedStrokeImage = strokeFactory.Load(_strokeImage)
                                             .Resize(new ResizeLayer(new Size(strokeSizeInPixels.X, strokeSizeInPixels.Y), ResizeMode.Stretch))
                                             .Rotate(rotation).Image;
                    var imageWithId = AddIdToStrokeImage(rotatedStrokeImage, (uint)stroke.Id);

                    var position = VectorUtils.MemberwiseMultiply(UvToMarginUv(stroke.Center), soleImageResolutionWithMargins.ToFloatVec()).ToIntVector2();
                    position -= new IntVector2(rotatedStrokeImage.Width / 2, rotatedStrokeImage.Height / 2);

                    for (int x = 0; x < imageWithId.Size.Width; x++)
                    {
                        for (int y = 0; y < imageWithId.Size.Height; y++)
                        {
                            var inImagePosition = position + new IntVector2(x, y);

                            uint offsetBitX = 0;
                            uint offsetBitY = 0;
                            if (inImagePosition.X - marginLength.X / 2 >= soleImageResolution.X || inImagePosition.X - marginLength.X * 1.5 < 0)
                            {
                                offsetBitX = 1;
                            }
                            if (inImagePosition.Y - marginLength.Y / 2 >= soleImageResolution.Y || inImagePosition.Y - marginLength.Y * 1.5 < 0)
                            {
                                offsetBitY = 1;
                            }

                            inImagePosition.X = inImagePosition.X % soleImageResolutionWithMargins.X; //probably not needed
                            inImagePosition.Y = inImagePosition.Y % soleImageResolutionWithMargins.Y;

                            var strokePixel = imageWithId.GetPixel(x, y);

                            byte newGColor = (byte)((strokePixel.G | (offsetBitX << 6)) | offsetBitY << 7);
                            strokePixel = Color.FromArgb(strokePixel.A, strokePixel.R, newGColor, strokePixel.B);

                            if (strokePixel.A > 0)
                            {
                                var layerIndex = 0;
                                var occupancy  = occupancyArray[inImagePosition.X, inImagePosition.Y];
                                if (occupancy != 0)
                                {
                                    layerIndex = (occupancy) % _layersCount;
                                }
                                occupancyArray[inImagePosition.X, inImagePosition.Y]++;

                                if (!_configuration.UseSmoothAlpha)
                                {
                                    var a = strokePixel.A;
                                    if (a > 0)
                                    {
                                        a = 255;
                                    }

                                    strokePixel = Color.FromArgb(a, strokePixel.R, strokePixel.G, strokePixel.B);
                                }

                                if (!_configuration.UseDithering)
                                {
                                    outImages[layerIndex].SetPixel(inImagePosition.X, inImagePosition.Y, strokePixel);
                                }
                                else
                                {
                                    var oldPixel = outImages[layerIndex].GetPixel(inImagePosition.X, inImagePosition.Y);
                                    if (_configuration.UseSmoothAlpha)
                                    {
                                        var oldAlpha = oldPixel.A;
                                        var maxAlpha = Mathf.Max(oldAlpha, strokePixel.A);
                                        strokePixel = Color.FromArgb(maxAlpha, strokePixel.R, strokePixel.G, strokePixel.B);

                                        if (layerIndex != 0)
                                        {
                                            var layer0Pixel    = outImages[0].GetPixel(inImagePosition.X, inImagePosition.Y);
                                            var layer0OldAlpha = layer0Pixel.A;
                                            if (layer0OldAlpha < strokePixel.A)
                                            {
                                                var newLayer0Pixel = Color.FromArgb(strokePixel.A, layer0Pixel.R, layer0Pixel.G, layer0Pixel.B);
                                                outImages[0].SetPixel(inImagePosition.X, inImagePosition.Y, newLayer0Pixel);
                                            }
                                        }
                                    }

                                    var  ditheringModuler  = Mathf.CeilToInt((float)occupancy / _layersCount) + 1;
                                    bool ditherPixelActive = (inImagePosition.X + inImagePosition.Y) % ditheringModuler == 0;

                                    if (ditherPixelActive)
                                    {
                                        outImages[layerIndex].SetPixel(inImagePosition.X, inImagePosition.Y, strokePixel);
                                    }
                                    else
                                    {
                                        var updatedOldPixel = Color.FromArgb(strokePixel.A, oldPixel.R, oldPixel.G, oldPixel.B);
                                        outImages[layerIndex].SetPixel(inImagePosition.X, inImagePosition.Y, updatedOldPixel);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(outImages.Cast <Image>().ToList());
        }