using System; using System.Drawing; using System.Drawing.Imaging; using System.Collections.Generic; using Treko; using Treko3D; using ClassLibrary; namespace Frames { #region Frame public class Frame { double _x0; double _y0; double _width; double _height; int _fW = 1024; int _fH = 768; int _nFile; // Number of File bool _isBlack; // Bitmap marked as black, not for save to file bool _shifted; // Frames in odd rows should be shifted to the left in half frame #region properties public double X0 { get { return _x0; } set { _x0 = value; } } public double Y0 { get { return _y0; } set { _y0 = value; } } public double Width { get { return _width; } set { _width = value; } } public double Height { get { return _height; } set { _height = value; } } public int FrmResW { get { return _fW; } set { _fW = value; } } public int FrmResH { get { return _fH; } set { _fH = value; } } public int NFile { get { return _nFile; } set { _nFile = value; } } public bool IsBlack { get { return _isBlack; } set { _isBlack = value; } } public bool Shifted { get { return _shifted; } set { _shifted = value; } } public Frame(int ResW, int ResH, double sizeW, double sizeH) { _fW = ResW; _fH = ResH; _width = sizeW; _height = sizeH; _isBlack = false; _shifted = false; } #endregion public Rectangle FrameRect(int i, int j) { int x0 = i * FrmResW; int y0 = j * FrmResH; if (_shifted == true) // shift to make bricks x0 += FrmResW / 2; return new Rectangle(x0, y0, FrmResW, FrmResH); } } #endregion #region FrameGroup public class FrameGroup: IDisposable { #region Private double _x0; double _y0; int _mmToPixelsCoeff; Bitmap _frameGroupBmp; bool _isBlack; List _rakurseArcs = new List(); List _colorArcs = new List(); double _frameWidth; double _frameHeight; int _frameWidthPix = 1024; int _frameHeightPix = 768; int _nFramesHor; int _nFramesVert; int _nGroupHor; int _nGroupVert; RectDouble _rect; Frame[,] _frameMap; Bitmap[,] _bmpMap; int _voxelRowRangeStart = 0; int _voxelRowRangeEnd = 0; int _voxelColRangeStart = 0; int _voxelColRangeEnd = 0; int _colorPixelRowRangeStart = 0; int _colorPixelRowRangeEnd = 0; int _colorPixelColRangeStart = 0; int _colorPixelColRangeEnd = 0; #endregion #region Get/Set public double X0 { get { return _x0; } set { _x0 = value; } } public double Y0 { get { return _y0; } set { _y0 = value; } } // Width of frame in mm public double FrameWidth { get { return _frameWidth; } set { _frameWidth = value; } } // Height of frame in mm public double FrameHeight { get { return _frameHeight; } set { _frameHeight = value; } } public int FrmWidthPix { get { return _frameWidthPix; } set { _frameWidthPix = value; } } public int FrmHeightPix { get { return _frameHeightPix; } set { _frameHeightPix = value; } } // To make bricks: extend width of frame group in half of frame public int GrpWidthPix { //get { return _frameWidthPix * NFramesHor + _frameWidthPix / 2; } get { return _frameWidthPix * NFramesHor; } } public int GrpHeightPix { get { return _frameHeightPix * NFramesVert; } } // To make bricks: extend width of frame group in half of frame public double GrpWidth { //get { return _frameWidth * NFramesHor + _frameWidth / 2; } get { return _frameWidth * NFramesHor; } } public double GrpHeight { get { return _frameHeight * NFramesVert; } } // Number of frames in Group horizontally public int NFramesHor { get { return _nFramesHor; } } // Number of frames in Group vertically public int NFramesVert { get { return _nFramesVert; } } // Group's number horizontally public int NGroupHor { get { return _nGroupHor; } } // Group's number vertically public int NGroupVert { get { return _nGroupVert; } } public Bitmap FrameGroupBmp { get { return _frameGroupBmp; } set { _frameGroupBmp = value; } } public Frame[,] FrameMap { get { return _frameMap; } set { _frameMap = value; } } public Bitmap[,] BmpMap { get { return _bmpMap; } set { _bmpMap = value; } } public RectDouble Rect { get { return _rect; } } public List IntersectRakurseArcs { get { return _rakurseArcs; } set { _rakurseArcs = value; } } public List IntersectColorArcs { get { return _colorArcs; } set { _colorArcs = value; } } public int MmToPixelsCoeff { get { //// GrpWidthPix is extended in half frame for bricks construction //if (_mmToPixelsCoeff == 0) // _mmToPixelsCoeff = Convert.ToInt32(GrpWidthPix / (_frameWidth + _frameWidth/2)); if (_mmToPixelsCoeff == 0) _mmToPixelsCoeff = Convert.ToInt32(GrpWidthPix / GrpWidth); return _mmToPixelsCoeff; } set { _mmToPixelsCoeff = value; } } public bool IsBlack { get { return _isBlack; } set { _isBlack = value; } } public int VoxelRowRangeStart { get { return _voxelRowRangeStart; } set { _voxelRowRangeStart = value; } } public int VoxelRowRangeEnd { get { return _voxelRowRangeEnd; } set { _voxelRowRangeEnd = value; } } public int VoxelColRangeStart { get { return _voxelColRangeStart; } set { _voxelColRangeStart = value; } } public int VoxelColRangeEnd { get { return _voxelColRangeEnd; } set { _voxelColRangeEnd = value; } } public int ColorPixelRowRangeStart { get { return _colorPixelRowRangeStart; } set { _colorPixelRowRangeStart = value; } } public int ColorPixelRowRangeEnd { get { return _colorPixelRowRangeEnd; } set { _colorPixelRowRangeEnd = value; } } public int ColorPixelColRangeStart { get { return _colorPixelColRangeStart; } set { _colorPixelColRangeStart = value; } } public int ColorPixelColRangeEnd { get { return _colorPixelColRangeEnd; } set { _colorPixelColRangeEnd = value; } } #endregion string genFileName(int nFile) { //int fileNumber = _nGroupVert * _nFramesHor + _nGroupHor + 1; // Start from 1 not 0 string fName = nFile.ToString(); fName = fName.PadLeft(6, '0'); return fName; } public void CropIntoImageArray() { FastImageCroper fIC = new FastImageCroper(_frameGroupBmp); BmpMap = new Bitmap[_nFramesHor, _nFramesVert]; for (int j = 0; j < _nFramesVert; j++) { for (int i = 0; i < _nFramesHor; i++) { Frame fr = FrameMap[i, j]; Rectangle rect = fr.FrameRect(i, j); Bitmap bmp = fIC.Crop(rect); BmpMap[i, j] = bmp; } } fIC.Dispose(); } // we need to crop group of frames as bricks with shift in half of frame for odd rows public void CropIntoImageArray(int nGroupRow) { //bool nFramesIsEven = (_nFramesVert % 2 == 0); // Number of frames in Row is even (chetnyj) //bool nGroupRowIsEven = (nGroupRow % 2 == 0); // Number of GroupRow is even (chetnyj) // Init Shifted value for (int j = 0; j < _nFramesVert; j++) for (int i = 0; i < _nFramesHor; i++) FrameMap[i, j].Shifted = false; //// Calculate which rows in frame group should be shifted //if (nFramesIsEven == true || nGroupRowIsEven == true) // V gruppe chetnoe kolichestvo strok, v etom sluchae sdvigaem v gruppe vlevo kajduju nechetnuju stroku //{ // for (int j = 1; j < _nFramesVert; j += 2) // for (int i = 0; i < _nFramesHor; i++) // FrameMap[i, j].Shifted = true; //} //else // V gruppe nechetnoe kolichestvo strok, v etom sluchae sdvigaem v gruppe vlevo kajduju nechetnuju stroku dlja chetnyh grupp // // i kajduju chetnuju stroku dlja nechetnyh grupp //{ //for (int j = 0; j < _nFramesVert; j += 2) // for (int i = 0; i < _nFramesHor; i++) // FrameMap[i, j].Shifted = true; //} // shift to the right every even row / because all framegroups shifted initially to the left for (int j = 0; j < _nFramesVert; j += 2) for (int i = 0; i < _nFramesHor; i++) FrameMap[i, j].Shifted = true; FastImageCroper fIC = new FastImageCroper(_frameGroupBmp); BmpMap = new Bitmap[_nFramesHor, _nFramesVert]; for (int j = 0; j < _nFramesVert; j++) for (int i = 0; i < _nFramesHor; i++) { Frame fr = FrameMap[i, j]; Rectangle rect = fr.FrameRect(i, j); Bitmap bmp = fIC.Crop(rect); BmpMap[i, j] = bmp; } fIC.Dispose(); } private int calcNFile(int nGroupsHor, int nGroupsVert, int i, int j, int lenGroupHor, int lenGroupVert) { int lenFramesHor = lenGroupHor * NFramesHor; // Length of line in frames int nFrameVert = nGroupsVert * NFramesVert + j; // Current number of frame's line int nFrameHor = nGroupsHor * NFramesHor + i; // Current number of frame in line int nFrame = lenFramesHor * nFrameVert + nFrameHor + 1; // Current number of frame (file), start file name == 1, not 0 !!!! return nFrame; } public void SaveGroupToFiles(string outDirName, int nGroupHor, int nGroupVert, int lenGroupHor, int lenGroupVert) { for (int j = 0; j < _nFramesVert; j++) { for (int i = 0; i < _nFramesHor; i++) { int nFile = calcNFile(nGroupHor, nGroupVert, i, j, lenGroupHor, lenGroupVert); FrameMap[i, j].NFile = nFile; // nFile nachatx s 1 !!!! string fName = genFileName(nFile); string fPath = outDirName + "\\" + fName + ".png"; if (ImageProcessing.DetectColorAllBlack(BmpMap[i, j]) == false) { BmpMap[i, j].Save(fPath, ImageFormat.Png); FrameMap[i, j].IsBlack = false; } else FrameMap[i, j].IsBlack = true; BmpMap[i, j].Dispose(); } } } public void SaveGroupToFiles(string outDirName, int nFile, int nCol, int nRow) { string fName = genFileName(nFile); string fPath = outDirName + fName + "_" + nCol + "_" + nRow + ".png"; _frameGroupBmp.Save(fPath, ImageFormat.Png); } FrameGroup() { } public FrameGroup(int resW, int resH, double sizeW, double sizeH, int nFramesHor, int nFramesVert, int nGroupHor, int nGroupVert) { _frameWidthPix = resW; _frameHeightPix = resH; _frameWidth = sizeW; _frameHeight = sizeH; _nFramesHor = nFramesHor; _nFramesVert = nFramesVert; _nGroupHor = nGroupHor; _nGroupVert = nGroupVert; // need to transfer this part into frame class !!! _x0 = _frameWidth * nFramesHor * nGroupHor; _y0 = _frameHeight * nFramesVert * nGroupVert; // To make bricks: shift all frame groups to left in half of frame _x0 -= _frameWidth / 2; //if (nGroupVert % 2 == 1) // _x0 -= _frameWidth / 2; // To make bricks: extend width of frame group in half of frame _rect = new RectDouble(_x0, _y0, GrpWidth + (_frameWidth / 2), GrpHeight); _frameMap = new Frame[nFramesHor, nFramesVert]; for (int j = 0; j < nFramesVert; j++) { for (int i = 0; i < nFramesHor; i++) { _frameMap[i, j] = new Frame(resW, resH, sizeW, sizeH); } } // Create just before drawing, then dispose //_frameGroupBmp = new Bitmap(_fW * nFramesHor, _fH * nFramesVert); } public void FillByIntersectVoxelArcs(Strip[] _strips) { _rakurseArcs.Clear(); foreach (Strip strip in _strips) { if (strip.Empty == true) continue; foreach (Voxel voxel in strip.VoxelArray) { if (voxel.Empty == true) continue; foreach (RakurseArc arc in voxel.RakurseArcs) { if (arc.Radius == 0) continue; if (IntersectArc(arc)) { _rakurseArcs.Add(arc); } } } } } // Reduce number of strips and voxels to process public void ContainsVoxelRange(Treko3D.Treko3D treko3DObj) { double rectUpSide = this.Y0 - treko3DObj.RadiusMax; double rectLeftSide = this.X0 - treko3DObj.RadiusMax; double rectDownSide = this.Y0 + this.GrpHeight + treko3DObj.RadiusMax; double rectRightSide = this.X0 + this.GrpWidth + treko3DObj.RadiusMax; Bitmap RakurseBmp = treko3DObj.RakurseBmps[0]; treko3DObj.ImageHeightPix = RakurseBmp.Height; treko3DObj.ImageWidthPix = RakurseBmp.Width; _voxelRowRangeStart = (int)Math.Round(rectUpSide / treko3DObj.Step); if (_voxelRowRangeStart < 0) _voxelRowRangeStart = 0; _voxelColRangeStart = (int)Math.Round(rectLeftSide / treko3DObj.Step); if (_voxelColRangeStart < 0) _voxelColRangeStart = 0; _voxelRowRangeEnd = (int)Math.Round(rectDownSide / treko3DObj.Step); if (_voxelRowRangeEnd > treko3DObj.ImageHeightPix) _voxelRowRangeEnd = treko3DObj.ImageHeightPix; _voxelColRangeEnd = (int)Math.Round(rectRightSide / treko3DObj.Step); if (_voxelColRangeEnd > treko3DObj.ImageWidthPix) _voxelColRangeEnd = treko3DObj.ImageWidthPix; } public void FillByIntersectVoxelArcs(Treko3D.Treko3D treko3DObj) { _rakurseArcs.Clear(); ContainsVoxelRange(treko3DObj); //int nStrips = treko3DObj.RakurseBmps[0].Width; //nStrips = 10; //TraceTotalMemory.WriteTotalMemory(" FrameGroup, step 0"); for (int nStrip = _voxelRowRangeStart; nStrip < _voxelRowRangeEnd; nStrip++) { Strip strip = treko3DObj.GenerateStrip(nStrip, _voxelColRangeStart, _voxelColRangeEnd); if (strip.Empty == true) continue; //TraceTotalMemory.WriteTotalMemory(" FrameGroup, step 1"); for (int nVoxel = _voxelColRangeStart; nVoxel < _voxelColRangeEnd; nVoxel++) { Voxel voxel = strip.VoxelArray[nVoxel]; if (voxel.Empty == true) continue; foreach (RakurseArc arc in voxel.RakurseArcs) { if (arc.Radius == 0) continue; if (IntersectArc(arc)) { _rakurseArcs.Add(arc); } } } //TraceTotalMemory.WriteTotalMemory(" FrameGroup, step 2"); strip.Dispose(); strip = null; //TraceTotalMemory.WriteTotalMemory(" FrameGroup, step 3"); } } // Reduce number of strips and voxels to process public void ContainsColorRange(Treko.Treko trekoObj) { double rectUpSide = this.Y0 - trekoObj.RadiusMax; double rectLeftSide = this.X0 - trekoObj.RadiusMax; double rectDownSide = this.Y0 + this.GrpHeight + trekoObj.RadiusMax; double rectRightSide = this.X0 + this.GrpWidth + trekoObj.RadiusMax; Image ImgDisplayTreko = trekoObj.ImgDisplayTreko; trekoObj.ImgDisplayTrekoHeightPix = ImgDisplayTreko.Height; trekoObj.ImgDisplayTrekoWidthPix = ImgDisplayTreko.Width; ColorPixelRowRangeStart = (int)Math.Round(rectUpSide / trekoObj.Step); if (ColorPixelRowRangeStart < 0) ColorPixelRowRangeStart = 0; ColorPixelColRangeStart = (int)Math.Round(rectLeftSide / trekoObj.Step); if (ColorPixelColRangeStart < 0) ColorPixelColRangeStart = 0; ColorPixelRowRangeEnd = (int)Math.Round(rectDownSide / trekoObj.Step); if (ColorPixelRowRangeEnd > trekoObj.ImgDisplayTrekoHeightPix) ColorPixelRowRangeEnd = trekoObj.ImgDisplayTrekoHeightPix; ColorPixelColRangeEnd = (int)Math.Round(rectRightSide / trekoObj.Step); if (ColorPixelColRangeEnd > trekoObj.ImgDisplayTrekoWidthPix) ColorPixelColRangeEnd = trekoObj.ImgDisplayTrekoWidthPix; } public void FillByIntersectColorArcs(Treko.Treko trekoObj) { _colorArcs.Clear(); ContainsColorRange(trekoObj); for (int nColorPixel = ColorPixelColRangeStart; nColorPixel < ColorPixelColRangeEnd; nColorPixel++) { //trekoObj.GenVectorData(_projectObj.HologramWidth, _projectObj.HologramHeight); foreach (ColorPixel colorPixel in trekoObj.ColorPixels) { if (colorPixel == null) continue; if (colorPixel.ColorArcs == null || colorPixel.ColorArcs.Length == 0) continue; foreach (ColorArc arc in colorPixel.ColorArcs) { if (arc.Radius1 == 0) continue; if (IntersectArc(arc)) { _colorArcs.Add(arc); } } } } } public void FillByIntersectColorArcs(ColorPixel[,] colorPixels) { _colorArcs.Clear(); foreach (ColorPixel colorPixel in colorPixels) { if (colorPixel == null) continue; if (colorPixel.ColorArcs == null || colorPixel.ColorArcs.Length == 0) continue; foreach (ColorArc arc in colorPixel.ColorArcs) { if (arc.Radius1 == 0) continue; if (IntersectArc(arc)) { _colorArcs.Add(arc); } } } } private void fillImageByBlack(Graphics gr) { Color col = Color.FromArgb(0, 0, 0); gr.Clear(col); } public void DrawBitmapByRakurseArcs(int[] profileColor) { List arcs = IntersectRakurseArcs; if (arcs == null || arcs.Count == 0) { _isBlack = true; return; } else { _isBlack = false; } // extend for bricks _frameGroupBmp = new Bitmap(GrpWidthPix + (_frameWidthPix / 2), GrpHeightPix); //Pen whitePen = new Pen(Color.White, 2); Graphics g = Graphics.FromImage(_frameGroupBmp); //.CreateGraphics(); fillImageByBlack(g); foreach (RakurseArc arc in arcs) { arc.DrawArcInFrame(_rect, g, MmToPixelsCoeff, profileColor); } //whitePen.Dispose(); g.Dispose(); } public void MarkFrameGroupAsBlack() { _isBlack = true; } public void DrawBitmapByColorArcs(int[] profileColor) { List arcs = IntersectColorArcs; if (arcs == null || arcs.Count == 0) { _isBlack = true; return; } else { _isBlack = false; } // extend for bricks _frameGroupBmp = new Bitmap(GrpWidthPix + (_frameWidthPix / 2), GrpHeightPix); //_frameGroupBmp = new Bitmap(GrpWidthPix, GrpHeightPix); //Pen whitePen = new Pen(Color.White, 2); Graphics g = Graphics.FromImage(_frameGroupBmp); //.CreateGraphics(); fillImageByBlack(g); foreach (ColorArc arc in arcs) { arc.DrawArcInFrame(_rect, g, MmToPixelsCoeff, profileColor); } //whitePen.Dispose(); g.Dispose(); } public bool IntersectArc(RakurseArc arc) { if (_rect.IntersectWith(arc.RectCircumf) == true) return true; else return false; } public bool Comparepoint(double compX, double compY) { if (compX > _x0 - 0.01 && compX < _x0 + _frameWidth + 0.01 && compY > _y0 - 0.01 && compY < _y0 + _frameHeight + 0.01) return true; else return false; } public bool IntersectArc(ColorArc arc) { return true; // !!! //double CFx = _x0 + _frameWidth * _nFramesHor / 2; //double CFy = _y0 + _frameHeight * _nFramesVert / 2; ////double CFx = _x0 + _frameWidth / 2; ////double CFy = _y0 + _frameHeight / 2; //double AngFrame = Math.Abs(Math.Atan(Math.Sqrt((_frameWidth * _frameWidth + _frameHeight * _frameHeight) / 2 / (arc.X - CFx) * (arc.X - CFx) + (arc.Y - CFy) * (arc.Y - CFy)))); //double AngFrameS = Math.Atan2((CFy - arc.Y), (CFx - arc.X)); //for (double i = AngFrameS - AngFrame; i < AngFrameS + AngFrame; i += AngFrame / 2) //{ // double compX = arc.X + Math.Cos(i) * arc.Radius1; // double compY = arc.Y + Math.Sin(i) * arc.Radius1; // if (Comparepoint(compX, compY) == true) // return true; //} //return false; //if (_rect.IntersectWith(arc.RectCircumf) == true) // return true; //else // return false; } public void DrawBorder(Bitmap frameGroupBitmap, int mmToPixelsCoeff) { Pen whitePen = new Pen(Color.White, 2); Graphics g = Graphics.FromImage(frameGroupBitmap); //.CreateGraphics(); _rect.DrawRectangleFromZeroCoord(g, whitePen, mmToPixelsCoeff); whitePen.Dispose(); g.Dispose(); } public void Dispose() { for (int i = 0; i < _rakurseArcs.Count; i++) _rakurseArcs[i] = null; _rakurseArcs.Clear(); _rakurseArcs = null; if (BmpMap != null) { for (int i = 0; i < BmpMap.GetLength(0); i++) for (int j = 0; j < BmpMap.GetLength(1); j++) { if (BmpMap[i, j] != null) { BmpMap[i, j].Dispose(); BmpMap[i, j] = null; } } } BmpMap = null; if (_frameGroupBmp != null) { _frameGroupBmp.Dispose(); _frameGroupBmp = null; } } } #endregion }