Пример #1
0
		public Graphic SwapChannelsToGRB()
		{
            if(channelFormat!=Format.RGB) return this.ConvertToRGB().SwapChannelsToBRG();
            Graphic ret=new Graphic(width, height, Format.RGB);
			if(ret.imageData==null) return ret;

			uint count=width*height;
			byte[] src=imageData;
			uint ind=0;
			byte[] dst=ret.imageData;
			uint inds=0;

			//Channel Swap RGB
			for(uint i=0; i<count; i++)
			{
				byte r=src[inds++];
				byte g=src[inds++];
				byte b=src[inds++];
				dst[ind++]=g;
				dst[ind++]=r;
				dst[ind++]=b;
			}

			return ret;
		}
Пример #2
0
		/// <summary>
		/// Applies an edge filter to the bitmap.
		/// </summary>
		/// <param name="bitmap">A bitmap.</param>
		/// <returns>Edge bitmap.</returns>
		public static Graphic DetectEdges(Graphic bitmap)
		{
			Graphic grayscaleMap=bitmap.ConvertToGray();

			Graphic edgeMap=new Graphic(grayscaleMap.Width, grayscaleMap.Height, Format.RGB);

			for(int y=1; y<edgeMap.Height-1; y++)
			{
				for(int x=1; x<edgeMap.Width-1; x++)
				{
					int sum=System.Math.Abs(grayscaleMap.GetPixel(x-1, y-1).R+grayscaleMap.GetPixel(x, y-1).R+grayscaleMap.GetPixel(x+1, y-1).R
						-grayscaleMap.GetPixel(x-1, y+1).R-grayscaleMap.GetPixel(x, y+1).R-grayscaleMap.GetPixel(x+1, y+1).R);

					System.Drawing.Color z1=grayscaleMap.GetPixel(x-1, y-1);
					System.Drawing.Color z2=grayscaleMap.GetPixel(x, y-1);
					System.Drawing.Color z3=grayscaleMap.GetPixel(x+1, y-1);
					System.Drawing.Color z4=grayscaleMap.GetPixel(x-1, y+1);
					System.Drawing.Color z5=grayscaleMap.GetPixel(x, y+1);
					System.Drawing.Color z6=grayscaleMap.GetPixel(x+1, y+1);

					int foo=z1.R+z2.R+z3.R-z4.R-z5.R-z6.R;
					if(sum>255)
						sum=255;

					sum=255-sum;

					edgeMap.SetPixel(x, y, System.Drawing.Color.FromArgb(255, sum, sum, sum));
				}
			}

			return edgeMap;
		}
Пример #3
0
		public static Graphic FromStream(Stream stream)
		{
			Image img=Image.FromStream(stream);
			uint width=(uint)img.Size.Width;
			uint height=(uint)img.Size.Height;

			Graphic ret=null;

			if ((img.PixelFormat&PixelFormat.Alpha)==PixelFormat.Alpha)
			{
				ret=new Graphic(width, height, Format.RGBA);

				Bitmap bmp=new Bitmap(img);
				BitmapData data=bmp.LockBits(new Rectangle(0, 0, (int)width, (int)height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
				Marshal.Copy(data.Scan0, ret.imageData, 0, (int)(width*height*4));
				bmp.UnlockBits(data);
			}
			else
			{
				ret=new Graphic(width, height, Format.RGB);

				Bitmap bmp=new Bitmap(img);
				BitmapData data=bmp.LockBits(new Rectangle(0, 0, (int)width, (int)height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
				if (((int)width*3)==data.Stride)
				{
					Marshal.Copy(data.Scan0, ret.imageData, 0, (int)(width*height*3));
				}
				else
				{
					if (IntPtr.Size==4)
					{
						for (uint i=0; i<height; i++)
						{
							Marshal.Copy((IntPtr)(data.Scan0.ToInt32()+(int)(i*data.Stride)), ret.imageData, (int)(width*3*i), (int)(width*3));
						}
					}
					else if (IntPtr.Size==8)
					{
						for (uint i=0; i<height; i++)
						{
							Marshal.Copy((IntPtr)(data.Scan0.ToInt64()+(long)(i*data.Stride)), ret.imageData, (int)(width*3*i), (int)(width*3));
						}
					}
				}

				bmp.UnlockBits(data);
				data=null;
				bmp.Dispose();
				bmp=null;
			}

			img.Dispose();
			img=null;

			return ret;
		}
Пример #4
0
		/// <summary>
		/// Computes the difference between to different bitmap regions.
		/// </summary>
		/// <param name="grayscaleBitmapA">First bitmap.</param>
		/// <param name="compareRectA">First bitmap region.</param>
		/// <param name="grayscaleBitmapB">Secound bitmap</param>
		/// <param name="compareRectB">Secound bitmap region.</param>
		/// <returns></returns>
		public static int ComputeDistance(Graphic grayscaleBitmapA,
							System.Drawing.Rectangle compareRectA,
							Graphic grayscaleBitmapB,
							System.Drawing.Rectangle compareRectB)
		{
			int averageA=GetAvarageGrayscale(grayscaleBitmapA, compareRectA);
			int averageB=GetAvarageGrayscale(grayscaleBitmapB, compareRectB);

			return System.Math.Abs(averageA-averageB);
		}
Пример #5
0
		Graphic NearestPixelResizeV(uint h)
		{
			double delta=(double)height/h;

			Graphic ret=new Graphic(width, h, channelFormat);
			if(ret.imageData==null) return ret;

			uint bpp=BytePerPixel;
			uint bw=width*bpp;

			uint dst=0;
			for(uint y=0; y<h; y++)
			{
				uint src=((uint)(y*delta+delta/2))*bw;
				for(uint i=0; i<bw; i++) ret.imageData[dst++]=imageData[src++];
			}
			return ret;
		}
Пример #6
0
		/// <summary>
		/// Computes the avarange grayscale value of a certain bitmap region.
		/// </summary>
		/// <param name="grayscaleBitmap">A grayscale bitmap.</param>
		/// <param name="rectangle">Defines a region.</param>
		/// <returns></returns>
		public static int GetAvarageGrayscale(Graphic grayscaleBitmap, System.Drawing.Rectangle rectangle)
		{
			int average=0;

			try
			{
				for(int y=rectangle.Y; y<rectangle.Bottom; y++)
					for(int x=rectangle.X; x<rectangle.Right; x++)
					{
						average+=grayscaleBitmap.GetPixel(x, y).R;
					}
			}
			catch(System.Exception ex)
			{
				return 128;
			}

			return average/(rectangle.Width*rectangle.Height);
		}
Пример #7
0
        public void Display()
        {
            CSCL.Imaging.Graphic image=new CSCL.Imaging.Graphic((uint)width, (uint)height, Format.RGB);

            for(Int64 i=Constants.GraphicMemoryDisplayAdressStart; i<width*height; i++)
            {
                Int64 x=i%width;
                Int64 y=i/width;

                byte r=data[i+0];
                byte g=data[i+1];
                byte b=data[i+2];
                byte a=data[i+3];

                image.SetPixel((int)x, (int)y, Color.FromArgb(a, r, g, b));
            }

            image.SaveToPNG("display.png");
        }
Пример #8
0
		public Graphic ConvertToGray()
		{
			if(channelFormat==Format.GRAY) return this;
			Graphic ret=new Graphic(width, height, Format.GRAY);
			if(ret.imageData==null) return ret;

			uint count=width*height;
			byte[] src=imageData;
			uint ind=0;
			byte[] dst=ret.imageData;
			uint inds=0;

			switch(channelFormat)
			{
				case Format.GRAYAlpha:
					{
						for(uint i=0; i<count; i++) { dst[ind++]=src[inds++]; inds++; }
						break;
					}
				case Format.BGR:
					{
						for(uint i=0; i<count; i++) { byte r=src[inds++]; byte g=src[inds++]; byte b=src[inds++]; dst[ind++]=(byte)(0.299*r+0.587*g+0.114*b); }
						break;
					}
				case Format.RGB:
					{
						for(uint i=0; i<count; i++) { byte b=src[inds++]; byte g=src[inds++]; byte r=src[inds++]; dst[ind++]=(byte)(0.299*r+0.587*g+0.114*b); }
						break;
					}
				case Format.BGRA:
					{
						for(uint i=0; i<count; i++) { byte r=src[inds++]; byte g=src[inds++]; byte b=src[inds++]; inds++; dst[ind++]=(byte)(0.299*r+0.587*g+0.114*b); }
						break;
					}
				case Format.RGBA:
					{
						for(uint i=0; i<count; i++) { byte b=src[inds++]; byte g=src[inds++]; byte r=src[inds++]; inds++; dst[ind++]=(byte)(0.299*r+0.587*g+0.114*b); }
						break;
					}
			}

			return ret;
		}
Пример #9
0
		public Graphic ToFlippedHorizontal()
		{
			Graphic ret=new Graphic(width, height, channelFormat);
			if(ret.imageData==null) return ret;

			uint bw=width*BytePerPixel;

			uint src=0;
			uint dst=height*bw;

			for(uint y=0; y<height; y++)
			{
				dst-=bw;
				for(uint x=0; x<bw; x++) ret.imageData[dst++]=imageData[src++];
				dst-=bw;
			}

			return ret;
		}
Пример #10
0
        /// <summary>
        /// Gibt ein Bitmap zurück
        /// </summary>
        /// <returns></returns>
        public CSCL.Imaging.Graphic GetImage(string dmttable, int sitenumber)
        {
            CSCL.Imaging.Graphic ret=new CSCL.Imaging.Graphic();

            try
            {
                string sqlCommand=String.Format("SELECT DmtSiteNumber, DmtFileType, DmtData FROM \"{0}\"", dmttable);
                DataTable tmpDT=Globals.InstSQLite.ExecuteQuery(sqlCommand);

                string fileType=tmpDT.Rows[0]["DmtFileType"].ToString();

                MemoryStream ms=new MemoryStream((byte[])tmpDT.Rows[0]["DmtData"]);

                switch(fileType)
                {
                    case "odt":
                        {
                            //TextDocument odtDocument=new TextDocument();
                            //odtDocument.Load
                            break;
                        }
                    default:
                        {
                            ret=new CSCL.Imaging.Graphic(400, 800, Format.RGB);
                            ret.FillWithMandelbrot();
                            break;
                        }
                }

                //ret=gtImage.FromStream(ms);

                ms.Close();
            }
            catch
            {
                throw new Exception();
            }

            return ret;
        }
Пример #11
0
		public Graphic ToRot90()
		{
			Graphic ret=new Graphic(height, width, channelFormat);
			if(ret.imageData==null) return ret;

			uint bpp=BytePerPixel;
			uint bw=height*bpp;

			uint src=0;
			uint dst_=(width-1)*bw;

			for(uint y=0; y<height; y++)
			{
				uint dst=dst_;
				for(uint x=0; x<width; x++)
				{
					for(uint i=0; i<bpp; i++) ret.imageData[dst++]=imageData[src++];
					dst-=bw+bpp;
				}
				dst_+=bpp;
			}
			return ret;
		}
Пример #12
0
		public Graphic ToFlippedVertical()
		{
			Graphic ret=new Graphic(width, height, channelFormat);
			if(ret.imageData==null) return ret;

			uint bpp=BytePerPixel;
			uint bw=width*bpp;

			uint src=0;
			uint dst=bw;
			dst-=bpp;

			for(uint y=0; y<height; y++)
			{
				for(uint x=0; x<width; x++)
				{
					for(uint i=0; i<bpp; i++) ret.imageData[dst++]=imageData[src++];
					dst-=2*bpp;
				}
				dst+=2*bw;
			}

			return ret;
		}
Пример #13
0
		public void Draw(int x, int y, Graphic source)
		{
			if(x>=width||y>=height) throw new ArgumentOutOfRangeException("x or y", "Out of image.");
			if(x+source.width<0||y+source.height<0) throw new ArgumentOutOfRangeException("x or y", "Out of image.");

			Graphic srcimg=source.ConvertTo(channelFormat);
			if(srcimg==null) return;

			uint bpp=ConvertToBytePerPixel(channelFormat);

			unsafe
			{
				fixed(byte* src_=srcimg.imageData, dst_=imageData)
				{
                    uint start=(uint)System.Math.Max(-x, 0)*bpp;
                    uint end=(uint)System.Math.Min(source.width, width-x)*bpp;

                    uint jstart=(uint)System.Math.Max(-y, 0);
                    uint jend=(uint)System.Math.Min(source.height, height-y);

					byte* src__=src_+start;
					byte* dst__=dst_+x*bpp+start;

					uint sw=source.width*bpp;
					uint dw=width*bpp;

					for(uint j=jstart; j<jend; j++)
					{
						byte* src=src__+sw*j;
						byte* dst=dst__+dw*(y+j);

						for(uint i=start; i<end; i++) *dst++=*src++;
					}
				}
			}
		}
Пример #14
0
		Graphic NearestPixelResizeVH(uint w, uint h)
		{
			double deltah=(double)height/h;
			double deltaw=(double)width/w;

			uint bpp=BytePerPixel;

			uint[] dx=new uint[w];
			for(uint x=0; x<w; x++) dx[x]=(uint)(x*deltaw+deltaw/2);

			if(bpp==1)
			{
				Graphic ret=new Graphic(w, h, channelFormat);
				if(ret.imageData==null) return ret;

				uint dst=0;
				for(uint y=0; y<h; y++)
				{
					uint src=(uint)(y*deltah+deltah/2)*width;
					for(uint x=0; x<w; x++) ret.imageData[dst++]=imageData[src+dx[x]];
				}
				return ret;
			}

			if(bpp==4)
			{
				Graphic ret=new Graphic(w, h, channelFormat);
				if(ret.imageData==null) return ret;

				uint dst=0;
				uint w4=width*4;
				for(uint y=0; y<h; y++)
				{
					uint src=(uint)(y*deltah+deltah/2)*w4;
					for(uint x=0; x<w; x++)
					{
						uint s=src+dx[x]*4;
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s];
					}
				}
				return ret;
			}

			if(bpp==3)
			{
				Graphic ret=new Graphic(w, h, channelFormat);
				if(ret.imageData==null) return ret;

				uint dst=0;
				uint w3=width*3;
				for(uint y=0; y<h; y++)
				{
					uint src=(uint)(y*deltah+deltah/2)*w3;
					for(uint x=0; x<w; x++)
					{
						uint s=src+dx[x]*3;
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s];
					}
				}
				return ret;
			}

			if(bpp==2)
			{
				Graphic ret=new Graphic(w, h, channelFormat);
				if(ret.imageData==null) return ret;

				uint dst=0;
				uint w2=width*2;
				for(uint y=0; y<h; y++)
				{
					uint src=(uint)(y*deltah+deltah/2)*w2;
					for(uint x=0; x<w; x++)
					{
						uint s=src+dx[x]*2;
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s];
					}
				}
				return ret;
			}

			return new Graphic(0, 0, channelFormat);
		}
Пример #15
0
        /// <summary>
        /// Speichert eine Karte welche je nach Monsterstärke eingefärbt wird
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="img"></param>
        /// <param name="map"></param>
        public static void SaveFeatureMapMonsterSpreading(string clientdata, string filename, Graphic img, TMX map)
        {
            //Farben
            Color green=Color.FromArgb(128, 0, 255, 0);
            Color yellow=Color.FromArgb(128, 255, 255, 0);
            Color red=Color.FromArgb(128, 255, 0, 0);
            Color blue=Color.FromArgb(128, 0, 0, 255);

            //Images
            Graphic tmpImage=img.GetImage();
            Graphic tmpDraw=new Graphic(tmpImage.Width, tmpImage.Height, tmpImage.ChannelFormat);

            //Ermittlung der Durchschnittswerte
            string fnMonsterXml=clientdata+"monsters.xml";
            List<Monster> monsters=Monster.GetMonstersFromMonsterXml(fnMonsterXml);
            monsters.Sort();

            Int64 minFightingStrength=999999999999;
            Int64 maxFightingStrength=-999999999999;

            Int64 medianFightingStrength=0;

            Dictionary<int, Int64> MonsterIDsAndFightingStrength=new Dictionary<int, Int64>();

            foreach(Monster monster in monsters)
            {
                if(monster.ID==1) continue; //Killermade ignorieren
                if(monster.ID==31) continue; //Seraphim Nex ignorieren
                if(monster.ID>9999) continue; //Experimentelle Monster ignorieren
                Int64 fightingStrength=monster.FightingStrength;

                if(fightingStrength<minFightingStrength) minFightingStrength=fightingStrength;
                if(fightingStrength>maxFightingStrength) maxFightingStrength=fightingStrength;

                MonsterIDsAndFightingStrength.Add(monster.ID, fightingStrength);
            }

            medianFightingStrength=(maxFightingStrength+minFightingStrength)/2;

            //Monster der Karte ermitteln
            List<MonsterSpawn> mSpawns=Monsters.GetMonsterSpawnFromMap(map);

            if(mSpawns.Count>0)
            {
                Int64 fss=0;

                foreach(MonsterSpawn spawn in mSpawns)
                {
                    if(spawn.MonsterID==1) continue; //Killermade ignorieren
                    if(spawn.MonsterID==31) continue; //Seraphim Nex ignorieren
                    if(spawn.MonsterID>=10000) continue; //Pflanzen etc ignorieren
                    fss+=MonsterIDsAndFightingStrength[spawn.MonsterID];
                }

                fss=fss/mSpawns.Count;

                //Einfärben je nach Stärke
                Int64 vSmarterGreen=(medianFightingStrength+minFightingStrength)/2;
                Int64 vSmarterYellow=(maxFightingStrength+medianFightingStrength)/2;

                if(fss<vSmarterGreen)
                {
                    tmpDraw.Fill(green);
                }
                else if(fss<vSmarterYellow)
                {
                    tmpDraw.Fill(yellow);
                }
                else
                {
                    tmpDraw.Fill(red);
                }
            }
            else //Keine Monster auf der Karte vorhanden
            {
                tmpDraw.Fill(blue);
            }

            //Drawen
            tmpImage.Draw(0, 0, tmpDraw, true);
            tmpImage.SaveToFile(filename);
        }
Пример #16
0
		/// <summary>
		/// Erzeugt ein Thumbnail 
		/// EXPERIMENTEL Muss getestet werdne
		/// Quadrates Thumbnail unter beibehaltung der Seitenverhälntisse
		/// </summary>
		/// <param name="size"></param>
		/// <returns></returns>
		public Graphic ToThumbnail(uint size)
		{
			Graphic bmp=null;
			Graphic crapped=null;
			uint x=0, y=0;
			double prop=0;

			if (width>size)
			{
				// compute proportation
				prop=(double)width/(double)height;

				if (width>height)
				{
                    x=(uint)System.Math.Round(size*prop, 0);
					y=size;
				}
				else
				{
					x=size;
                    y=(uint)System.Math.Round(size/prop, 0);
				}

				//TESTEN

				bmp=new Graphic(x, y);
				//bmp=new System.Drawing.Bitmap((Image)image, new Size(x, y));

				crapped=new Graphic(size, size, channelFormat);
				crapped.Draw(0, 0, bmp);

				//crapped=new System.Drawing.Bitmap(75, 75);
				//Graphics g=Graphics.FromImage(crapped);
				//g.DrawImage(bmp,
				//    new Rectangle(0, 0, 75, 75),
				//    new Rectangle(0, 0, 75, 75),
				//    GraphicsUnit.Pixel);

				bmp=crapped;
			}
			else
			{
				crapped=this;
			}

			return bmp;
		}
Пример #17
0
		/// <summary>
		/// Converts a bitmap to ascii art.
		/// </summary>
		/// <param name="bitmap">A bitmap.</param>
		/// <returns>Ascii art.</returns>
		/// <example>
		/* 0:::::::::::::::::::::::::::::$MMMMM%:::::::::::::::::::::::::::::::::::::M
			%                            (#''` !M8                                    M
			%                    :QMMMMMMMM849640MMM@(                                M
			%                 "MMMMMMM4*' HM:  !MB#MMMMMM$                            M
			%               'MMMM3        ''$844$    `6MMMMM'                         M
			% '#MNN#H@@@@@@HMMM!          '''`           $MMM3                        M
			%1M@99889QB81!!M*M4'`                          @QM:                       M
			%1Q'"B000008MMM*`MM:`''`                       !M@3                :&$;`  M
			%0`  $`      !B  `*MM6  ''''`                 'MM(!:            $MMMMMMMMMM
			%!&  `8'     #`    ''1MM@H3'`'''`         '$MMMH   %          4M$''!@BMMM4M
			% ;0   46   (3       `''''1#@HBH#&$&$448MMMM0'     :'       (M& ':@BQ@"   M
			%  !B(16BMQ`B                       :894:          `*     'MH   B8Q0`     M
			%    &MM` *M&                      !4               ;:"Q#M#'  !@3Q`       M
			%      4MM;&`                      "                (01'`'''`"Q0"         M
			%        :MN                      `(                `'''`  '84B'          M
			%                                 &                 `` `''QB09`           M
			%          !                     :(                 '389088@;             M
			%          1:                   '9                  !"6QQQ!               M
			%          `#                  :B                  `84'                   M
			%           (#                04                   &'                     M
			%            1M6           `9B!                   $:                      M
			%             !M#006(:'"6490`                   `Q:                       M
			%               4B! :(1!                      `48`                        M
			%                 4@9'                      ;@B!                          M
			%                   '9QB0!              ;8QB3                             M
			%                       `&88909444099898%                                 M
			0:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::M 
		*/
		/// </example>
		public string ToAscii()
		{
			Graphic edgeMap=DetectEdges(this);

			string output="";

			for(int y=0; y<edgeMap.Height; y+=13)
			{
				for(int x=0; x<edgeMap.Width; x+=8)
				{
					int minDistance=999999999;
					char minChar=' ';

					for(int i=32; i<127; i++)
					{
						char c=(char)i;
						string str=""+c;

						Graphic characterMap=new Graphic(8, 13, Format.RGB);
						//System.Drawing.Graphics g=System.Drawing.Graphics.FromImage(characterMap);
						characterMap.Fill(System.Drawing.Color.White);

						//characterMap.Rendertex
						Graphic mytext=Graphic.RenderText(new System.Drawing.Font("Courier New", 10), str, System.Drawing.Color.Blue);
						characterMap.Draw(-2, -2, mytext);

						int tmp=ComputeDistance(characterMap,
							new System.Drawing.Rectangle(0, 0, (int)characterMap.Width, (int)characterMap.Height),
							edgeMap,
							new System.Drawing.Rectangle(x, y, (int)characterMap.Width, (int)characterMap.Height));

						if(tmp<minDistance)
						{
							minDistance=tmp;
							minChar=c;
						}
					}

					output+=minChar;
				}

				output+="\r\n";
			}

			return output;
		}
Пример #18
0
        static void SaveFeatureMapMusic(string filename, Graphic img, TMX map)
        {
            //Farben
            Color green=Color.FromArgb(128, 0, 255, 0);
            //Color yellow=Color.FromArgb(128, 255, 255, 0);
            Color red=Color.FromArgb(128, 255, 0, 0);
            //Color blue=Color.FromArgb(128, 0, 0, 255);

            //Images
            Graphic tmpImage=img.GetImage();
            Graphic tmpDraw=new Graphic(tmpImage.Width, tmpImage.Height, tmpImage.ChannelFormat);

            //Properties durchsuchen
            bool found=false;

            foreach(Property prop in map.Properties)
            {
                if(prop.Name=="music")
                {
                    found=true;
                    break;
                }
            }

            if(found)
                tmpDraw.Fill(green);
            else
                tmpDraw.Fill(red);

            //Drawen
            tmpImage.Draw(0, 0, tmpDraw, true);
            tmpImage.SaveToFile(filename);
        }
Пример #19
0
		public Graphic ConvertToBGRA()
		{
			if(channelFormat==Format.BGRA) return this;
			Graphic ret=new Graphic(width, height, Format.BGRA);
			if(ret.imageData==null) return ret;

			uint count=width*height;
			byte[] src=imageData;
			uint ind=0;
			byte[] dst=ret.imageData;
			uint inds=0;
			switch(channelFormat)
			{
				case Format.GRAY:
					for(uint i=0; i<count; i++) { byte g=src[inds++]; dst[ind++]=g; dst[ind++]=g; dst[ind++]=g; dst[ind++]=255; }
					break;
				case Format.GRAYAlpha:
					for(uint i=0; i<count; i++) { byte g=src[inds++]; dst[ind++]=g; dst[ind++]=g; dst[ind++]=g; dst[ind++]=src[inds++]; }
					break;
				case Format.RGB:
					for(uint i=0; i<count; i++) { byte r=src[inds++]; byte g=src[inds++]; dst[ind++]=src[inds++]; dst[ind++]=g; dst[ind++]=r; dst[ind++]=255; }
					break;
				case Format.RGBA:
					for(uint i=0; i<count; i++) { byte r=src[inds++]; byte g=src[inds++]; dst[ind++]=src[inds++]; dst[ind++]=g; dst[ind++]=r; dst[ind++]=src[inds++]; }
					break;
				case Format.BGR:
					for(uint i=0; i<count; i++) { dst[ind++]=src[inds++]; dst[ind++]=src[inds++]; dst[ind++]=src[inds++]; dst[ind++]=255; }
					break;
			}
			return ret;
		}
Пример #20
0
		/// <summary>
		/// Invertiert den Alphakanal
		/// </summary>
		/// <returns></returns>
		public Graphic InvertAlpha()
		{
			if (channelFormat!=Format.RGBA&&channelFormat!=Format.BGRA&&channelFormat!=Format.GRAYAlpha) return this;

			Graphic ret=new Graphic(width, height, channelFormat);
			if (ret.imageData==null) return ret;

			uint count=width*height*BytePerPixel;
			if (channelFormat==Format.BGRA||channelFormat==Format.RGBA)
			{
				for (uint i=0; i<count; i+=4)
				{
					ret.imageData[i]=(byte)(imageData[i]);
					ret.imageData[i+1]=(byte)(imageData[i+1]);
					ret.imageData[i+2]=(byte)(imageData[i+2]);
					ret.imageData[i+3]=(byte)(255-imageData[i+3]);
				}
			}
			else if (channelFormat==Format.GRAYAlpha)
			{
				for (uint i=0; i<count; i+=2)
				{
					ret.imageData[i]=(byte)(imageData[i]);
					ret.imageData[i+1]=(byte)(255-imageData[i+1]);
				}
			}

			return ret;
		}
Пример #21
0
		/////////////////////////////////////////////////////////////////
		// noch mehr Bildverarbeitung
		/////////////////////////////////////////////////////////////////
		public double Compare(Graphic ImageToCompare, uint Threshold)
		{
			if(ImageToCompare==null) throw new Exception("Image is null");
			if(Width!=ImageToCompare.Width) throw new Exception("Image have different sizes");
			if(Height!=ImageToCompare.Height) throw new Exception("Image have different sizes");
			if(channelFormat!=ImageToCompare.channelFormat) throw new Exception("Image have different formats");

			uint divergency=0;

			for(uint y=0; y<Width; y++)
			{
				for(uint x=0; x<Height; x++)
				{
					Color picA=GetPixel(x, y);
					Color picB=ImageToCompare.GetPixel(x, y);

					int dif=0;

                    dif+=System.Math.Abs(picA.R-picB.R);
                    dif+=System.Math.Abs(picA.G-picB.G);
                    dif+=System.Math.Abs(picA.B-picB.B);
					dif/=3;

					if(dif>Threshold) divergency++;
				}
			}

			//Gibt in % zurück wie stark die Bilder von einander abweichen
			//0 % == Bilder sind Identisch
			return (double)(100*(divergency/(double)(Width*Height)));
		}
Пример #22
0
        private Graphic Render(int width, int height, string onlyLayer)
        {
            Graphic ret=new Graphic((uint)width, (uint)height, Format.RGBA);
            ret=ret.InvertAlpha();

            foreach(LayerData i in Layers)
            {
                if(onlyLayer=="")
                {
                    if(i.name=="Collision")
                        continue; //Collision Layer überspringen
                }
                else
                {
                    if(i.name!=onlyLayer)
                        continue;
                }

                //Für jedes Tile in X bzw Y Richtung
                for(int y=0;y<i.height;y++)
                {
                    for(int x=0;x<i.width;x++)
                    {
                        int number=i.data[x, y];
                        if(number<=0)
                            continue; //Kein Tile zugewiesen //TODO was genau meint eine Zahl kleiner 0 genau
                        Graphic Tile=GetTile(number);

                        //Korrekturfaktor für Tiles welche breiter bzw. 
                        //höher sind als normal
                        int CorFactorX=0; //Korrekturfaktor für x wird nicht benötigt (denke ich)
                        //int CorFactorX=(int)(Tile.Width-TileWidth);
                        int CorFactorY=(int)(Tile.Height-TileHeight);

                        ret.Draw(x*TileWidth-CorFactorX, y*TileHeight-CorFactorY, Tile, true);
                    }
                }
			
            }

            return ret;
        }
Пример #23
0
		Graphic NearestPixelResizeH(uint w)
		{
			double delta=(double)width/w;

			uint bpp=BytePerPixel;

			uint[] dx=new uint[w];
			for(uint x=0; x<w; x++) dx[x]=(uint)(x*delta+delta/2);

			if(bpp==1)
			{
				Graphic ret=new Graphic(w, height, channelFormat);
				if(ret.imageData==null) return ret;

				uint dst=0;
				for(uint y=0; y<height; y++)
				{
					uint src=y*width;
					for(uint x=0; x<w; x++) ret.imageData[dst++]=imageData[src+dx[x]];
				}
				return ret;
			}

			if(bpp==4)
			{
				Graphic ret=new Graphic(w, height, channelFormat);
				if(ret.imageData==null) return ret;

				uint bw=width*4;
				uint dst=0;
				for(uint y=0; y<height; y++)
				{
					uint src=y*bw;

					for(uint x=0; x<w; x++)
					{
						uint s=src+dx[x]*4;
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s];
					}
				}
				return ret;
			}

			if(bpp==3)
			{
				Graphic ret=new Graphic(w, height, channelFormat);
				if(ret.imageData==null) return ret;

				uint bw=width*3;
				uint dst=0;
				for(uint y=0; y<height; y++)
				{
					uint src=y*bw;

					for(uint x=0; x<w; x++)
					{
						uint s=src+dx[x]*3;
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s];
					}
				}
				return ret;
			}

			if(bpp==2)
			{
				Graphic ret=new Graphic(w, height, channelFormat);
				if(ret.imageData==null) return ret;

				uint bw=width*2;
				uint dst=0;
				for(uint y=0; y<height; y++)
				{
					uint src=y*bw;

					for(uint x=0; x<w; x++)
					{
						uint s=src+dx[x]*2;
						ret.imageData[dst++]=imageData[s++];
						ret.imageData[dst++]=imageData[s];
					}
				}
				return ret;
			}

			return new Graphic(0, 0, channelFormat);
		}
Пример #24
0
		public static Graphic FromTGAFile(string filename)
		{
			Graphic ret=null;

			using(FileStream fs=new FileStream(filename, FileMode.Open, FileAccess.Read))
			{
				uint fsize=(uint)fs.Length;
				if(fsize<19) throw new EndOfStreamException("File to small to be a Truevision Image.");

				BinaryReader br=new BinaryReader(fs);

				// Read Header (18 bytes)
				byte ID_Length=br.ReadByte();
				byte Color_Map_Type=br.ReadByte();
				byte Image_Type=br.ReadByte();
				ushort First_Entry_Index=br.ReadUInt16();
				ushort Color_Map_Length=br.ReadUInt16();
				byte Color_Map_Entry_Size=br.ReadByte();
				ushort X_Origin=br.ReadUInt16();
				ushort Y_Origin=br.ReadUInt16();
				ushort Width=br.ReadUInt16();
				ushort Height=br.ReadUInt16();
				byte Pixel_Depth=br.ReadByte();
				byte Image_Descriptor=br.ReadByte();

				// Offsets
				//uint pImage_ID=0;
				uint pImage_Data=0;
				uint pColor_Map_Data=0;
				uint pDeveloper_Directory=0;
				uint pExtension_Area=0;
				uint pScan_Line_Table=0;			// *Field 25 == Field 23 // Height*4 bytes

				// Vars
				uint width=0, height=0;
				uint bpp=0;	// 8 | 16 | 24 | 32
				bool isAlpha=false;
				bool hor_flipped=false, ver_flipped=false, rle=false;

				uint[] scan_line_table;

				//if(ID_Length!=0)
				//	pImage_ID=18;
				pImage_Data=18u+ID_Length;
				if(Color_Map_Type!=0)
				{
					pColor_Map_Data=18u+ID_Length;
					if(Color_Map_Length==0) throw new Exception("Color Map Type=1, but Length=0.");

					if(Color_Map_Entry_Size==15||Color_Map_Entry_Size==16) pImage_Data+=Color_Map_Length*2u;
					else if(Color_Map_Entry_Size==24) pImage_Data+=Color_Map_Length*3u;
					else if(Color_Map_Entry_Size==32) pImage_Data+=Color_Map_Length*4u;
					else throw new Exception("Illegal Color Map Entry Size.");
				}

				rle=false;
				switch(Image_Type)
				{
					case 10:
						{
							rle=true;
							if(Pixel_Depth==16) bpp=2;
							else if(Pixel_Depth==24) bpp=3;
							else if(Pixel_Depth==32) { bpp=4; isAlpha=true; }
							else throw new Exception("Illegal or unsupported Pixel Depth (RGB).");
						}
						break;
					case 2:
						{
							if(Pixel_Depth==16) bpp=2;
							else if(Pixel_Depth==24) bpp=3;
							else if(Pixel_Depth==32) { bpp=4; isAlpha=true; }
							else throw new Exception("Illegal or unsupported Pixel Depth (RGB).");
						}
						break;
					case 9:
						{
							rle=true;
							if(Pixel_Depth==8) bpp=1;
							else if(Pixel_Depth==16) { bpp=2; isAlpha=true; }
							else throw new Exception("Illegal or unsupported Pixel Depth (GRAY).");
						}
						break;
					case 11:
						{
							rle=true;
							if(Pixel_Depth==8) bpp=1;
							else if(Pixel_Depth==16) { bpp=2; isAlpha=true; }
							else throw new Exception("Illegal or unsupported Pixel Depth (GRAY).");
						}
						break;
					case 1:
						{
							if(Pixel_Depth==8) bpp=1;
							else if(Pixel_Depth==16) { bpp=2; isAlpha=true; }
							else throw new Exception("Illegal or unsupported Pixel Depth (GRAY).");
						}
						break;
					case 3:
						{
							if(Pixel_Depth==8) bpp=1;
							else if(Pixel_Depth==16) { bpp=2; isAlpha=true; }
							else throw new Exception("Illegal or unsupported Pixel Depth (GRAY).");
						}
						break;
					default:
						throw new Exception("Illegal or unsupported Image Type.");
				}

				if(Width==0) throw new Exception("Illegal Image Width.");
				if(Height==0) throw new Exception("Illegal Image Height.");
				width=Width;
				height=Height;

				if((Image_Descriptor&0x0F)!=(isAlpha?8:0)) throw new Exception("Illegal Alpha Channel Bits Count.");
				if((Image_Descriptor&0xC0)!=0) throw new Exception("Unsed Bits in Image Description not zero.");

				hor_flipped=(Image_Descriptor&0x20)!=0;
				ver_flipped=(Image_Descriptor&0x10)!=0;

				// checken ob pImage_Data-Offsets in File
				if((pImage_Data+height)>=fsize) throw new Exception("File to small to fold the complete Image Data.");

				// Extension Format
				fs.Seek(fsize-26, SeekOrigin.Begin);
				pExtension_Area=br.ReadUInt32();
				pDeveloper_Directory=br.ReadUInt32();
				String sig=br.ReadChars(17).ToString();

				scan_line_table=new uint[height];

				if(sig=="TRUEVISION-XFILE.")	// in der Hoffung, dass nicht zufällig
				{ // diese Zeichenfolge in der Pixeldaten steht
					if(pExtension_Area!=0)
					{
						fs.Seek(pExtension_Area, SeekOrigin.Begin);
						pScan_Line_Table=0;
						ushort Extension_Size=br.ReadUInt16();

						if(Extension_Size>=495)
						{
							fs.Seek(pExtension_Area+490, SeekOrigin.Begin);
							pScan_Line_Table=br.ReadUInt32();
						}

						if(pScan_Line_Table!=0)
						{
							fs.Seek(pScan_Line_Table, SeekOrigin.Begin);
							for(int i=0; i<height; i++) scan_line_table[i]=br.ReadUInt32();
						}
					}
				}
				else pExtension_Area=pDeveloper_Directory=0;

				if(pScan_Line_Table==0)
				{
					if(!rle)
					{
						for(uint i=0; i<height; i++) scan_line_table[i]=pImage_Data+i*width*bpp;
					}
					else
					{
						fs.Seek(pImage_Data, SeekOrigin.Begin);

						for(uint i=0; i<height; i++)
						{
							scan_line_table[i]=(uint)fs.Position;

							uint internalwidth=0;
							while(width>internalwidth)
							{
								try
								{
									byte ph=br.ReadByte();
									uint count=(uint)((ph&0x7F)+1);
									if((ph&0x80)>0)
									{ // rle packet
										if(br.ReadBytes((int)bpp).Length<bpp) throw new Exception("Error reading rle-packed Image Data.");
									}
									else
									{ // raw packet
										if(br.ReadBytes((int)(count*bpp)).Length<(count*bpp)) throw new Exception("Error reading rle-packed Image Data.");
									}
									internalwidth+=count;
								}
								catch(Exception)
								{
									throw new EndOfStreamException("Error reading rle-packed Image Data.");
								}
							}
							if(internalwidth>width) throw new Exception("Error reading rle-packed Image Data. (Line too long.)");
						}
					}
				}

				uint bpp_=bpp;

				if(!isAlpha&&bpp==2) bpp_=3; // RGB24 statt RGB15

				uint lineLen=width*bpp_;

				byte[] bits=new byte[height*lineLen];

				//for(int i=0; i<lineLen*height; i++) bits[i]=0; // Ziel säubern

				for(uint y=0; y<height; y++)
				{
					uint p=y*lineLen;
					uint dest=p;

					uint end=width;

					if(ver_flipped) dest-=(width+1)*bpp_;

					uint startOfLine;
					if(hor_flipped) startOfLine=scan_line_table[y];
					else startOfLine=scan_line_table[height-y-1];

					if(!rle)
					{
						uint blocksize=end*bpp;
						fs.Seek(startOfLine, SeekOrigin.Begin);
						byte[] buffer=br.ReadBytes((int)blocksize);
						if(buffer.Length<blocksize) throw new EndOfStreamException();

						int ind=0;
						for(uint myX=0; myX<end; myX++)
						{
							if(bpp<3)
							{ // 8 oder 16 Bit
								if(bpp==1||isAlpha)
								{// GRAY8
									bits[dest++]=buffer[ind++];
									if(isAlpha) bits[dest++]=buffer[ind++];
								}
								else
								{
									ushort w1=buffer[ind++];
									ushort w2=buffer[ind++];
									ushort w=(ushort)((w2<<8)&w1);
									ushort r=(ushort)(w&0x7c00); r>>=7;
									ushort g=(ushort)(w&0x03e0); g>>=2;
									ushort b=(ushort)(w&0x001f); b<<=3;
									bits[dest++]=(byte)b;
									bits[dest++]=(byte)g;
									bits[dest++]=(byte)r;
								}
							}
							else
							{
								bits[dest++]=buffer[ind++];
								bits[dest++]=buffer[ind++];
								bits[dest++]=buffer[ind++];
								if(bpp>3) bits[dest++]=buffer[ind++];
							}

							if(ver_flipped) dest-=2*bpp_;
						}
					}
					else
					{
						fs.Seek(startOfLine, SeekOrigin.Begin);

						byte[] buffer=new byte[width*bpp];
						uint ind=0;

						uint internalwidth=0;
						while(width>internalwidth)
						{
							try
							{
								byte ph=br.ReadByte();
								uint count=(uint)((ph&0x7F)+1);
								if((ph&0x80)>0)
								{ // rle packet
									byte[] tbuffer=br.ReadBytes((int)bpp);
									if(tbuffer.Length<bpp) throw new Exception("Error reading rle-packed Image Data.");

									for(uint i=0; i<count; i++)
									{
										tbuffer.CopyTo(buffer, ind);
										ind+=bpp;
									}
								}
								else
								{ // raw packet
									byte[] tbuffer=br.ReadBytes((int)(count*bpp));
									if(tbuffer.Length<(count*bpp)) throw new Exception("Error reading rle-packed Image Data.");
									tbuffer.CopyTo(buffer, ind);
									ind+=count*bpp;
								}
								internalwidth+=count;
							}
							catch(Exception)
							{
								throw new EndOfStreamException("Error reading rle-packed Image Data.");
							}
						}

						if(internalwidth>width) throw new EndOfStreamException("Error reading rle-packed Image Data. (Line too long.)");

						ind=0;
						for(uint myX=0; myX<end; myX++)
						{
							if(bpp<3)
							{ // 8 oder 16 Bit
								if(bpp==1||isAlpha)
								{// GRAY8
									bits[dest++]=buffer[ind++];
									if(isAlpha) bits[dest++]=buffer[ind++];
								}
								else
								{
									ushort w1=buffer[ind++];
									ushort w2=buffer[ind++];
									ushort w=(ushort)((w2<<8)&w1);
									ushort r=(ushort)(w&0x7c00); r>>=7;
									ushort g=(ushort)(w&0x03e0); g>>=2;
									ushort b=(ushort)(w&0x001f); b<<=3;
									bits[dest++]=(byte)b;
									bits[dest++]=(byte)g;
									bits[dest++]=(byte)r;
								}
							}
							else
							{
								bits[dest++]=buffer[ind++];
								bits[dest++]=buffer[ind++];
								bits[dest++]=buffer[ind++];
								if(bpp>3)
									bits[dest++]=buffer[ind++];
							}

							if(ver_flipped) dest-=2*bpp_;
						}
					}
				}

				ret=new Graphic();

				switch(bpp_)
				{
					case 1: ret.channelFormat=Format.GRAY; break;
					case 2: ret.channelFormat=Format.GRAYAlpha; break;
					case 3: ret.channelFormat=Format.RGB; break;
					case 4: ret.channelFormat=Format.RGBA; break;
					default: ret.channelFormat=Format.GRAY; break;
				}

				ret.imageData=bits;
				ret.width=width;
				ret.height=height;

				br.Close();
				fs.Close();
			} // using(br)

			return ret;
		}
Пример #25
0
		public void Draw(int x, int y, Graphic source, bool considerAlpha)
		{
			if(!considerAlpha||source.channelFormat==Format.BGR||
				source.channelFormat==Format.RGB||source.channelFormat==Format.GRAY)
			{
				Draw(x, y, source); return;
			}

			if(x>=width||y>=height) throw new ArgumentOutOfRangeException("x or y", "Out of image.");
			if(x+source.width<0||y+source.height<0) throw new ArgumentOutOfRangeException("x or y", "Out of image.");

			Graphic srcimg=null;

			switch(channelFormat)
			{
				case Format.GRAY: srcimg=source.ConvertToGrayAlpha(); break;
				case Format.GRAYAlpha: srcimg=source.ConvertToGrayAlpha(); break;
				case Format.RGB: srcimg=source.ConvertToRGBA(); break;
				case Format.RGBA: srcimg=source.ConvertToRGBA(); break;
				case Format.BGR: srcimg=source.ConvertToBGRA(); break;
				case Format.BGRA: srcimg=source.ConvertToBGRA(); break;
			}

			uint bpp=ConvertToBytePerPixel(source.channelFormat);

			unsafe
			{
				fixed(byte* src_=srcimg.imageData, dst_=imageData)
				{
                    uint start=(uint)System.Math.Max(-x, 0);
                    uint end=(uint)System.Math.Min(source.width, width-x);

                    uint jstart=(uint)System.Math.Max(-y, 0);
                    uint jend=(uint)System.Math.Min(source.height, height-y);

					if(channelFormat==Format.BGR||channelFormat==Format.RGB||channelFormat==Format.GRAY)
					{
						uint dbpp=ConvertToBytePerPixel(channelFormat);

						byte* src__=src_+start*bpp;
						byte* dst__=dst_+x*dbpp+start*dbpp;

						uint sw=source.width*bpp;
						uint dw=width*dbpp;

						if(channelFormat==Format.BGR||channelFormat==Format.RGB)
						{
							for(uint j=jstart; j<jend; j++)
							{
								byte* src=src__+sw*j;
								byte* dst=dst__+dw*(y+j);

								for(uint i=start; i<end; i++)
								{
									byte sr=*src++; byte sg=*src++; byte sb=*src++; byte sa=*src++;

									if(sa!=0)
									{
										byte dr=*dst++; byte dg=*dst++; byte db=*dst++;
										dst-=3;

										double a2=sa/255.0;
										double a1=1-a2;
										*dst++=(byte)(dr*a1+sr*a2);
										*dst++=(byte)(dg*a1+sg*a2);
										*dst++=(byte)(db*a1+sb*a2);
									}
									else dst+=3;
								}
							}
						}
						else // GRAY
						{
							for(uint j=jstart; j<jend; j++)
							{
								byte* src=src__+sw*j;
								byte* dst=dst__+dw*(y+j);

								for(uint i=start; i<end; i++)
								{
									byte sg=*src++; byte sa=*src++;

									if(sa!=0)
									{
										byte dg=*dst;

										double a2=sa/255.0;
										double a1=1-a2;
										*dst++=(byte)(dg*a1+sg*a2);
									}
									else dst++;
								}
							}
						} // end if RGB || BGR
					}
					else // 2x Alpha-Bild
					{
						byte* src__=src_+start*bpp;
						byte* dst__=dst_+x*bpp+start*bpp;

						uint sw=source.width*bpp;
						uint dw=width*bpp;

						if(channelFormat==Format.BGRA||channelFormat==Format.RGBA)
						{
							for(uint j=jstart; j<jend; j++)
							{
								byte* src=src__+sw*j;
								byte* dst=dst__+dw*(y+j);

								for(uint i=start; i<end; i++)
								{
									byte sr=*src++; byte sg=*src++; byte sb=*src++; byte sa=*src++;

									if(sa!=0)
									{
										byte dr=*dst++; byte dg=*dst++; byte db=*dst++; byte da=*dst++;
										dst-=4;

										double a2=sa/255.0;
										double a1=1-a2;
										*dst++=(byte)(dr*a1+sr*a2);
										*dst++=(byte)(dg*a1+sg*a2);
										*dst++=(byte)(db*a1+sb*a2);
										*dst++=da;
									}
									else dst+=4;
								}
							}
						}
						else // GRAYALPHA
						{
							for(uint j=jstart; j<jend; j++)
							{
								byte* src=src__+sw*j;
								byte* dst=dst__+dw*(y+j);

								for(uint i=start; i<end; i++)
								{
									byte sg=*src++; byte sa=*src++;

									if(sa!=0)
									{
										byte dg=*dst++; byte da=*dst++;
										dst-=2;

										double a2=sa/255.0;
										double a1=1-a2;
										*dst++=(byte)(dg*a1+sg*a2);
										*dst++=da;
									}
									else dst+=2;
								}
							}
						} // end if RGBA || BGRA
					} // end if 2x Alpha-Bild
				} // fixed
			} // unsafe
		}
Пример #26
0
		public Graphic GetSubImage(uint x, uint y, uint w, uint h)
		{
			if(x>=width||y>=height) throw new ArgumentOutOfRangeException("x or y", "Out of image.");

			Graphic ret=new Graphic(w, h, channelFormat);

			ret.Draw(-(int)x, -(int)y, this);

			return ret;
		}
Пример #27
0
		Graphic ReduceByV(uint n)
		{
			if((width*height)==0) return new Graphic(0, 0, channelFormat);
			uint h=height/n;

			if(channelFormat==Format.GRAY)
			{
				Graphic ret=new Graphic(width, h, channelFormat);
				if(ret.imageData==null) return ret;

				for(uint x=0; x<width; x++)
				{
					byte[] dst=ret.imageData;
					uint ind=x;
					byte[] src=imageData;
					uint inds=x;
					for(uint y=0; y<h; y++)
					{
						uint sum=0;
						for(uint z=0; z<n; z++) { sum+=src[inds]; inds+=width; }

						dst[ind]=(byte)(sum/n);
						ind+=width;
					}
				}
				return ret;
			}

			if(channelFormat==Format.RGB||channelFormat==Format.BGR)
			{
				Graphic ret=new Graphic(width, h, channelFormat);
				if(ret.imageData==null) return ret;

				uint wb=3*width-2;
				for(uint x=0; x<width; x++)
				{
					byte[] dst=ret.imageData;
					uint ind=x*3;
					byte[] src=imageData;
					uint inds=x*3;
					for(uint y=0; y<h; y++)
					{
						uint sumr=0, sumg=0, sumb=0;
						for(uint z=0; z<n; z++)
						{
							sumr+=src[inds++];
							sumg+=src[inds++];
							sumb+=src[inds];
							inds+=wb;
						}

						dst[ind++]=(byte)(sumr/n);
						dst[ind++]=(byte)(sumg/n);
						dst[ind]=(byte)(sumb/n);
						ind+=wb;
					}
				}
				return ret;
			}

			if(channelFormat==Format.RGBA||channelFormat==Format.BGRA)
			{
				Graphic ret=new Graphic(width, h, channelFormat);
				if(ret.imageData==null) return ret;

				uint wb=4*width-3;
				for(uint x=0; x<width; x++)
				{
					byte[] dst=ret.imageData;
					uint ind=x*4;
					byte[] src=imageData;
					uint inds=x*4;
					for(uint y=0; y<h; y++)
					{
						uint sumr=0, sumg=0, sumb=0, suma=0;
						for(uint z=0; z<n; z++)
						{
							byte r=src[inds++];
							byte g=src[inds++];
							byte b=src[inds++];
							uint a=src[inds];
							inds+=wb;
							sumr+=r*a;
							sumg+=g*a;
							sumb+=b*a;
							suma+=a;
						}

						if(suma==0)
						{
							dst[ind++]=0;
							dst[ind++]=0;
							dst[ind++]=0;
							dst[ind]=0;
						}
						else
						{
							dst[ind++]=(byte)(sumr/suma);
							dst[ind++]=(byte)(sumg/suma);
							dst[ind++]=(byte)(sumb/suma);
							dst[ind]=(byte)(suma/n);
						}

						ind+=wb;
					}
				}
				return ret;
			}

			if(channelFormat==Format.GRAYAlpha)
			{
				Graphic ret=new Graphic(width, h, channelFormat);
				if(ret.imageData==null) return ret;

				uint wb=2*width-1;
				for(uint x=0; x<width; x++)
				{
					byte[] dst=ret.imageData;
					uint ind=x*2;
					byte[] src=imageData;
					uint inds=x*2;
					for(uint y=0; y<h; y++)
					{
						uint sumg=0, suma=0;
						for(uint z=0; z<n; z++)
						{
							byte g=src[inds++];
							uint a=src[inds];
							inds+=wb;
							sumg+=g*a;
							suma+=a;
						}

						if(suma==0)
						{
							dst[ind++]=0;
							dst[ind]=0;
						}
						else
						{
							dst[ind++]=(byte)(sumg/suma);
							dst[ind]=(byte)(suma/n);
						}

						ind+=wb;
					}
				}
				return ret;
			}

			return new Graphic(0, 0, channelFormat);
		}
Пример #28
0
		public static Graphic FromBMPFile(string filename)
		{
			#region Variablen
			// Header
			int bfSize;			// Größe der BMP-Datei in Byte. (unzuverlässig)
			int bfOffBits;		// Offset der Bilddaten in Byte vom Beginn der Datei an.

			// Infoblock
			uint biSize;			// Größe des Informationsblocks in Byte
			int biWidth;			// Breite der Bitmap in Pixel.
			int biHeight;			// Höhe der Bitmap in Pixel
			short biPlanes;			// Bei PCX die Anzahl der Farbebenen bei BMP nicht verwendet (immer 1)
			short biBitCount;		// Farbtiefe (1, 4, 8, 16, 24, 32 Bit)
			BMPBiCompression biCompression;		// Compressionsmethod
			uint biSizeImage;		// Größe der Bilddaten (oder 0)
			int biXPelsPerMeter;	// Horizontale Auflösung des Zielausgabegerätes in Pixel pro Meter 
			int biYPelsPerMeter;	// Vertikale Auflösung des Zielausgabegerätes in Pixel pro Meter 
			uint biClrUsed;			// Colors
			uint biClrImportant;	// Important Color

			// Weitere Dinge für den Infoblock
			uint bmRed=0;	// Farbmaske Rot
			uint bmGreen=0;	// Farbmaske Grün
			uint bmBlue=0;	// Farbmaske Blau
			uint bmAlpha=0;	// Farbmaske Alpha

			// Farbtabelle
			List<Color> ColorTable=new List<Color>();
			#endregion

			// Datei öffnen
			BinaryReader fileReader=new BinaryReader(File.OpenRead(filename));

			try
			{
				#region Header auslesen
				byte[] buffer=new byte[2];
				fileReader.Read(buffer, 0, 2);
				if(buffer[0]!='B'&&buffer[0]!='M') return new Graphic(); // Signatur überprüfen

				bfSize=fileReader.ReadInt32();						// (unzuverlässig)
				fileReader.BaseStream.Seek(10, SeekOrigin.Begin);	// bfReserved überspringen
				bfOffBits=fileReader.ReadInt32();
				#endregion

				#region Informationsblock
				biSize=fileReader.ReadUInt32();

				// 108: Typ Windows V4 wird nicht unterstützt
				// 124: Typ Windows V5 wird nicht unterstützt
				if(biSize==12)
				{ // OS/2 1.x
					biWidth=fileReader.ReadInt16();
					biHeight=fileReader.ReadInt16();
					biPlanes=fileReader.ReadInt16();
					biBitCount=fileReader.ReadInt16();

					// Fest definiert
					biCompression=BMPBiCompression.BI_RGB;
					biSizeImage=(uint)(bfSize-26);
					biXPelsPerMeter=2835; // 1000 DPI
					biYPelsPerMeter=2835; // 1000 DPI

					if(biBitCount==1||biBitCount==4||biBitCount==8)
					{
						int CountColors=1<<biBitCount; // 2^biBitCount

						for(int i=0; i<CountColors; i++)
						{
							byte blue=fileReader.ReadByte();
							byte green=fileReader.ReadByte();
							byte red=fileReader.ReadByte();
							ColorTable.Add(Color.FromArgb(red, green, blue));
						}
					}
					else if(biBitCount==16||biBitCount==24||biBitCount==32)
					{
						// nix
					}
					else return new Graphic();
				}
				else if(biSize==40||biSize==56||biSize==64)
				{
					// 40: Windows 3.1x, 95, NT
					// 56: Adobe Photoshop BMP mit Bitmaske (nicht Standardkonform?)
					// 64: OS/2 2.x (weitere Bytes werden einfach ignoriert)

					biWidth=fileReader.ReadInt32();
					biHeight=fileReader.ReadInt32();
					biPlanes=fileReader.ReadInt16();
					biBitCount=fileReader.ReadInt16();

					biCompression=(BMPBiCompression)fileReader.ReadUInt32();

					biSizeImage=fileReader.ReadUInt32();
					biXPelsPerMeter=fileReader.ReadInt32();
					biYPelsPerMeter=fileReader.ReadInt32();

					biClrUsed=fileReader.ReadUInt32();
					biClrImportant=fileReader.ReadUInt32();

					// 56 Byte Header ist ein 40 Byte Header + BitFields (16 byte): fehlerhaft geschrieben von Adobe PhotoShop
					if(biSize==64) fileReader.BaseStream.Seek(24, SeekOrigin.Current); // Rest des OS/2 2.x Headers

					if(biBitCount==16||biBitCount==24||biBitCount==32)
					{
						if(biCompression==BMPBiCompression.BI_BITFIELDS&&(biBitCount==16||biBitCount==32))
						{
							bmRed=fileReader.ReadUInt32();
							bmGreen=fileReader.ReadUInt32();
							bmBlue=fileReader.ReadUInt32();
						}
						if(biCompression==BMPBiCompression.BI_ALPHABITFIELDS&&(biBitCount==16||biBitCount==32))
						{
							bmRed=fileReader.ReadUInt32();
							bmGreen=fileReader.ReadUInt32();
							bmBlue=fileReader.ReadUInt32();
							bmAlpha=fileReader.ReadUInt32(); // ich hoffe mal, dass der Alpha am Anfang ist
						}
					}
					else if(biBitCount==1||biBitCount==4||biBitCount==8)
					{
						uint CountColors=biClrUsed;
						if(biClrUsed==0) CountColors=1u<<biBitCount; // 2^biBitCount

						for(uint i=0; i<CountColors; i++)
						{
							byte blue=fileReader.ReadByte();
							byte green=fileReader.ReadByte();
							byte red=fileReader.ReadByte();
							fileReader.BaseStream.Seek(1, SeekOrigin.Current);
							ColorTable.Add(Color.FromArgb(red, green, blue));
						}
					}
					else return new Graphic();
				}
				else return new Graphic();

				// Konsistenz Check
				if(biPlanes!=1||biWidth<=0||biHeight==0) return new Graphic();
				if(biBitCount!=16&&biBitCount!=32&&(biCompression==BMPBiCompression.BI_ALPHABITFIELDS||
					biCompression==BMPBiCompression.BI_BITFIELDS)) return new Graphic();

				// Fall auf Standardbehandlung zurück, wenn Bitfields dem Standardfällen entsprechen
				if(biCompression==BMPBiCompression.BI_BITFIELDS)
				{
					if(biBitCount==32&&bmRed==0xFF0000&&bmGreen==0xFF00&&bmBlue==0xFF) biCompression=BMPBiCompression.BI_RGB;
				}
				if(biCompression==BMPBiCompression.BI_ALPHABITFIELDS)
				{
					if(biBitCount==32&&bmRed==0xFF0000&&bmGreen==0xFF00&&bmBlue==0xFF&&bmAlpha==0xFF000000) biCompression=BMPBiCompression.BI_RGB;
				}

				int absHeight=System.Math.Abs(biHeight);
				#endregion

				#region pImage anlegen
				Graphic ret;

				if(biBitCount==32||(biBitCount==16&&(biCompression==BMPBiCompression.BI_ALPHABITFIELDS||
					biCompression==BMPBiCompression.BI_BITFIELDS)))
					ret=new Graphic((uint)biWidth, (uint)absHeight, Format.RGBA);
				else //Andere Bildern
					ret=new Graphic((uint)biWidth, (uint)absHeight, Format.RGB);
				#endregion

				#region Bilddaten in pImage einlesen
				fileReader.BaseStream.Seek(bfOffBits, SeekOrigin.Begin); // zu Bilddaten springen

				if(biCompression==BMPBiCompression.BI_RGB)
				{
					#region Unkomprimierte Bilddaten
					if(biBitCount==1) // 1 Bit
					{
						#region 1 Bit
						int BytesPerRow=(int)Align((uint)(biWidth+7)/8, 4);

						int ind=0;
						buffer=new byte[BytesPerRow];

						while(ColorTable.Count<2) ColorTable.Add(Color.Black);

						if(biHeight>0) // buttom-up Bild
						{
							for(int i=absHeight-1; i>=0; i--)
							{
								ind=i*biWidth*3;
								fileReader.Read(buffer, 0, buffer.Length);
								byte pixel=0;
								for(int a=0; a<biWidth; a++)
								{
									if(a%8==0) pixel=buffer[a/8];
									int bit=(pixel&0x80)==0x80?1:0;
									ret.imageData[ind++]=ColorTable[bit].B;
									ret.imageData[ind++]=ColorTable[bit].G;
									ret.imageData[ind++]=ColorTable[bit].R;
									pixel<<=1;
								}
							}
						}
						else if(biHeight<0) // top-down Bild
						{
							for(int i=0; i<absHeight; i++)
							{
								fileReader.Read(buffer, 0, buffer.Length);
								byte pixel=0;
								for(int a=0; a<biWidth; a++)
								{
									if(a%8==0) pixel=buffer[a/8];
									int bit=(pixel&0x80)==0x80?1:0;
									ret.imageData[ind++]=ColorTable[bit].B;
									ret.imageData[ind++]=ColorTable[bit].G;
									ret.imageData[ind++]=ColorTable[bit].R;
									pixel<<=1;
								}
							}
						}
						#endregion
					}
					else if(biBitCount==4) // 4 Bit
					{
						#region 4 Bit
						int BytesPerRow=(int)Align((uint)(biWidth*4+7)/8, 4);

						int ind=0;
						buffer=new byte[BytesPerRow];

						while(ColorTable.Count<16) ColorTable.Add(Color.Black);

						if(biHeight>0) // buttom-up Bild
						{
							for(int i=absHeight-1; i>=0; i--)
							{
								ind=i*biWidth*3;
								fileReader.Read(buffer, 0, buffer.Length);
								byte pixel=0;
								for(int a=0; a<biWidth; a++)
								{
									if(a%2==0) pixel=buffer[a/2];
									int bit=(pixel&0xF0)>>4;
									ret.imageData[ind++]=ColorTable[bit].B;
									ret.imageData[ind++]=ColorTable[bit].G;
									ret.imageData[ind++]=ColorTable[bit].R;
									pixel<<=4;
								}
							}
						}
						else if(biHeight<0) // top-down Bild
						{
							for(int i=0; i<absHeight; i++)
							{
								fileReader.Read(buffer, 0, buffer.Length);
								byte pixel=0;
								for(int a=0; a<biWidth; a++)
								{
									if(a%2==0) pixel=buffer[a/2];
									int bit=(pixel&0xF0)>>4;
									ret.imageData[ind++]=ColorTable[bit].B;
									ret.imageData[ind++]=ColorTable[bit].G;
									ret.imageData[ind++]=ColorTable[bit].R;
									pixel<<=4;
								}
							}
						}
						#endregion
					}
					else if(biBitCount==8) // 8 Bit
					{
						#region 8 Bit
						int BytesPerRow=(int)Align((uint)biWidth, 4);

						int ind=0;
						buffer=new byte[BytesPerRow];

						while(ColorTable.Count<256) ColorTable.Add(Color.Black);

						if(biHeight>0) // buttom-up Bild
						{
							for(int i=absHeight-1; i>=0; i--)
							{
								ind=i*biWidth*3;
								fileReader.Read(buffer, 0, buffer.Length);
								for(int a=0; a<biWidth; a++)
								{
									byte pixel=buffer[a];
									ret.imageData[ind++]=ColorTable[pixel].B;
									ret.imageData[ind++]=ColorTable[pixel].G;
									ret.imageData[ind++]=ColorTable[pixel].R;
								}
							}
						}
						else if(biHeight<0) // top-down Bild
						{
							for(int i=0; i<absHeight; i++)
							{
								fileReader.Read(buffer, 0, buffer.Length);
								for(int a=0; a<biWidth; a++)
								{
									byte pixel=buffer[a];
									ret.imageData[ind++]=ColorTable[pixel].B;
									ret.imageData[ind++]=ColorTable[pixel].G;
									ret.imageData[ind++]=ColorTable[pixel].R;
								}
							}
						}
						#endregion
					}
					else if(biBitCount==16) // 16 Bit
					{
						#region 16 Bit
						int BytesPerRow=(biWidth*2);
						int rest=(int)(Align((uint)BytesPerRow, 4)-BytesPerRow);

						int ind=0;
						buffer=new byte[BytesPerRow];

						if(biHeight>0) // buttom-up Bild
						{
							for(int i=absHeight-1; i>=0; i--)
							{
								ind=i*biWidth*3;
								fileReader.Read(buffer, 0, buffer.Length);
								for(int a=0; a<biWidth; a++)
								{
									byte pixelA=buffer[a*2];
									byte pixelB=buffer[a*2+1];

									int b=(pixelA&0x1F)<<3;
									int g=((pixelB&0x3)<<6)+((pixelA&0xE0)>>2);
									int r=(pixelB&0x7C)<<1;

									ret.imageData[ind++]=(byte)(b+b/32);
									ret.imageData[ind++]=(byte)(g+g/32);
									ret.imageData[ind++]=(byte)(r+r/32);
								}
							}
						}
						else if(biHeight<0) // top-down Bild
						{
							for(int i=absHeight-1; i>=0; i--)
							{
								fileReader.Read(buffer, 0, buffer.Length);
								for(int a=0; a<biWidth; a++)
								{
									byte pixelA=buffer[a*2];
									byte pixelB=buffer[a*2+1];

									int b=(pixelA&0x1F)<<3;
									int g=((pixelB&0x3)<<6)+((pixelA&0xE0)>>2);
									int r=(pixelB&0x7C)<<1;

									ret.imageData[ind++]=(byte)(b+b/32);
									ret.imageData[ind++]=(byte)(g+g/32);
									ret.imageData[ind++]=(byte)(r+r/32);
								}
							}
						}
						#endregion
					}
					else if(biBitCount==24) // 24 Bit
					{
						#region 24 Bit
						int BytesPerRow=(biWidth*3);
						int rest=(int)(Align((uint)BytesPerRow, 4)-BytesPerRow);

						if(biHeight>0) // buttom-up Bild
						{
							for(int i=0; i<absHeight; i++)
							{
								fileReader.Read(ret.imageData, ret.imageData.Length-(i+1)*BytesPerRow, BytesPerRow);
								if(rest!=0) fileReader.BaseStream.Seek(rest, SeekOrigin.Current);
							}
						}
						else if(biHeight<0) // top-down Bild
						{
							if(rest==0)
							{
								fileReader.Read(ret.imageData, 0, BytesPerRow*absHeight); // ganze bild auf einmal laden
							}
							else
							{
								for(int i=0; i<absHeight; i++)
								{
									fileReader.Read(ret.imageData, i*BytesPerRow, BytesPerRow);
									if(rest!=0) fileReader.BaseStream.Seek(rest, SeekOrigin.Current);
								}
							}
						}
						#endregion
					}
					else if(biBitCount==32) // 32 Bit
					{
						#region 32 Bit
						int BytesPerRow=(biWidth*4);
						buffer=new byte[BytesPerRow];

						if(biHeight>0) // buttom-up Bild
						{
							for(int i=0; i<absHeight; i++)
							{
								fileReader.Read(ret.imageData, ret.imageData.Length-(i+1)*BytesPerRow, BytesPerRow);
							}
						}
						else if(biHeight<0) // top-down Bild
						{
							fileReader.Read(ret.imageData, 0, BytesPerRow*absHeight); // ganze bild auf einmal laden
						}
						#endregion
					}
					#endregion Unkomprimierte Bilddaten
				}
				else if(biCompression==BMPBiCompression.BI_RLE8) // RLE 8 Kodierte Daten
				{
					#region RLE 8
					if(biBitCount!=8) return new Graphic();	// nur 8 Bit Bilder erlaubt

					int BytesPerRow=(int)Align((uint)biWidth, 4);
					int rest=BytesPerRow-biWidth;
					byte[] bufferRLE=new byte[absHeight*BytesPerRow];
					int index=0;
					int lineCount=0;

					while(ColorTable.Count<256) ColorTable.Add(Color.Black);

					#region Dekomprimiere RLE 8
					while(fileReader.BaseStream.Position<fileReader.BaseStream.Length&&index<(absHeight*BytesPerRow))
					{
						if(rest!=0&&(index/BytesPerRow)!=lineCount) throw new Exception("Bad RLE 8 coding.");
						if(rest==0&&(index/BytesPerRow)!=lineCount)
							if(index>BytesPerRow*(lineCount+1)) throw new Exception("Bad RLE 8 coding.");

						byte cByte=fileReader.ReadByte();

						if(cByte==0) // Kommando steht in Byte 2
						{
							byte scByte=fileReader.ReadByte();
							switch(scByte)
							{
								case 0: // Ende der Bildzeile
									{
										lineCount++;
										index=lineCount*BytesPerRow;
										break;
									}
								case 1: // Ende der Bitmap
									{
										index=absHeight*BytesPerRow;
										lineCount=absHeight;
										fileReader.BaseStream.Position=fileReader.BaseStream.Length;
										break;
									}
								case 2: // Verschiebung der aktuellen Pixelposition
									{
										byte vRight=fileReader.ReadByte();	// Verschiebung nach Rechts
										if(vRight>=biWidth) throw new Exception("Bad RLE 8 coding.");

										byte vDown=fileReader.ReadByte();	// Verschiebung nach Unten

										int currentRow=index-lineCount*BytesPerRow;
										if((currentRow+vRight)>=biWidth) throw new Exception("Bad RLE 8 coding.");
										if((lineCount+vDown)>=absHeight) throw new Exception("Bad RLE 8 coding.");

										lineCount+=vDown;
										index=lineCount*BytesPerRow+currentRow+vRight;
										break;
									}
								default: // 3-255 Byte unverändert übernehmen
									{
										// Die folgenden n Bytes werden direkt übernommen;
										// der nächste Datensatz findet sich am darauffolgenden
										// geraden Offset (vom Start der Bilddaten aus gezählt).

										fileReader.Read(bufferRLE, index, scByte);
										index+=scByte;

										// Wenn Offset nicht grade dann ein Byte nach vorne
										if(scByte%2!=0) fileReader.BaseStream.Seek(1, SeekOrigin.Current);

										break;
									}
							}
						}
						else // Daten so oft wie im cByte angegeben reinschreiben
						{
							byte dByte=fileReader.ReadByte();
							for(int i=0; i<cByte; i++) bufferRLE[index++]=dByte;
						}
					}
					#endregion

					#region pImage erstellen und füllen
					if(biHeight>0) // buttom-up Bild
					{
						int fIndex=0; // RLE Buffer Index
						index=0;
						for(int i=absHeight-1; i>=0; i--)
						{
							index=i*biWidth*3;
							for(int a=0; a<biWidth; a++)
							{
								byte pixel=bufferRLE[fIndex++];
								ret.imageData[index++]=ColorTable[pixel].B;
								ret.imageData[index++]=ColorTable[pixel].G;
								ret.imageData[index++]=ColorTable[pixel].R;
							}
							fIndex+=rest;
						}
					}
					else if(biHeight<0) // top-down Bild
					{
						int fIndex=0;	// RLE Buffer Index
						index=0;
						for(int i=0; i<absHeight; i++)
						{
							for(int a=0; a<biWidth; a++)
							{
								byte pixel=bufferRLE[fIndex++];
								ret.imageData[index++]=ColorTable[pixel].B;
								ret.imageData[index++]=ColorTable[pixel].G;
								ret.imageData[index++]=ColorTable[pixel].R;
							}
							fIndex+=rest;
						}
					}
					#endregion
					#endregion
				}
				else if(biCompression==BMPBiCompression.BI_RLE4) // RLE 4 Kodierte Daten
				{
					#region RLE 4
					if(biBitCount!=4) return new Graphic(); //Nur 4 Bit Bilder erlaubt

					int BytesPerRow=(int)Align((uint)biWidth, 4);
					int rest=BytesPerRow-biWidth;
					byte[] bufferRLE=new byte[absHeight*BytesPerRow];
					int index=0;
					int lineCount=0;

					while(ColorTable.Count<16) ColorTable.Add(Color.Black);

					#region Dekomprimiere RLE 4
					while(fileReader.BaseStream.Position<fileReader.BaseStream.Length&&index<(absHeight*BytesPerRow))
					{
						if(rest!=0&&(index/BytesPerRow)!=lineCount) throw new Exception("Bad RLE 4 coding.");
						if(rest==0&&(index/BytesPerRow)!=lineCount)
							if(index>BytesPerRow*(lineCount+1)) throw new Exception("Bad RLE 4 coding.");

						byte cByte=fileReader.ReadByte();

						if(cByte==0) // Kommando steht in Byte 2
						{
							byte scByte=fileReader.ReadByte();
							switch(scByte)
							{
								case 0: // Ende der Bildzeile
									{
										lineCount++;
										index=lineCount*BytesPerRow;
										break;
									}
								case 1: // Ende der Bitmap
									{
										index=absHeight*BytesPerRow;
										lineCount=absHeight;
										fileReader.BaseStream.Position=fileReader.BaseStream.Length;
										break;
									}
								case 2: // Verschiebung der aktuellen Pixelposition
									{
										byte vRight=fileReader.ReadByte();	// Verschiebung nach Rechts
										if(vRight>=biWidth) throw new Exception("Bad RLE 4 coding.");

										byte vDown=fileReader.ReadByte();	// Verschiebung nach Unten

										int currentRow=index-lineCount*BytesPerRow;
										if((currentRow+vRight)>=biWidth) throw new Exception("Bad RLE 4 coding.");
										if((lineCount+vDown)>=absHeight) throw new Exception("Bad RLE 4 coding.");

										lineCount+=vDown;
										index=lineCount*BytesPerRow+currentRow+vRight;
										break;
									}
								default: // 3-255 Nibbles unverändert übernehmen
									{
										// Die folgenden n Nibbles werden direkt übernommen;
										// der nächste Datensatz findet sich am darauffolgenden
										// geraden Offset (vom Start der Bilddaten aus gezählt).

										byte[] nibbles=new byte[(scByte+1)/2];
										fileReader.Read(nibbles, 0, nibbles.Length);

										for(int i=0; i<nibbles.Length-(cByte%2); i++)
										{
											bufferRLE[index++]=(byte)(nibbles[i]>>4);
											bufferRLE[index++]=(byte)(nibbles[i]&0xF);
										}
										if(cByte%2!=0) bufferRLE[index++]=(byte)(nibbles[nibbles.Length-1]>>4);

										// Wenn Offset nicht grade dann ein Byte nach vorne
										if(((scByte+1)/2)%2!=0) fileReader.BaseStream.Seek(1, SeekOrigin.Current);

										break;
									}
							}
						}
						else // Daten so oft wie im cByte angegeben reinschreiben
						{
							byte dByte=fileReader.ReadByte();
							byte aByte=(byte)(dByte>>4);
							byte bByte=(byte)(dByte&0xF);
							for(int i=0; i<cByte/2; i++)
							{
								bufferRLE[index++]=aByte;
								bufferRLE[index++]=bByte;
							}
							if(cByte%2!=0) bufferRLE[index++]=aByte;
						}
					}
					#endregion

					#region pImage erstellen und füllen
					if(biHeight>0) // buttom-up Bild
					{
						int fIndex=0; // RLE Buffer Index
						index=0;
						for(int i=absHeight-1; i>=0; i--)
						{
							index=i*biWidth*3;
							for(int a=0; a<biWidth; a++)
							{
								byte pixel=bufferRLE[fIndex++];
								ret.imageData[index++]=ColorTable[pixel].B;
								ret.imageData[index++]=ColorTable[pixel].G;
								ret.imageData[index++]=ColorTable[pixel].R;
							}
							fIndex+=rest;
						}
					}
					else if(biHeight<0) // top-down Bild
					{
						int fIndex=0;	// RLE Buffer Index
						index=0;
						for(int i=0; i<absHeight; i++)
						{
							for(int a=0; a<biWidth; a++)
							{
								byte pixel=bufferRLE[fIndex++];
								ret.imageData[index++]=ColorTable[pixel].B;
								ret.imageData[index++]=ColorTable[pixel].G;
								ret.imageData[index++]=ColorTable[pixel].R;
							}
							fIndex+=rest;
						}
					}
					#endregion
					#endregion
				}
				else if(biCompression==BMPBiCompression.BI_BITFIELDS||biCompression==BMPBiCompression.BI_ALPHABITFIELDS)
				{ // Bitmasken
					#region BI_BITFIELDS
					if(biBitCount==16)
					{
						#region Bitmasken checken
						bmRed&=0xffff; // nur 16 bittig
						bmGreen&=0xffff;
						bmBlue&=0xffff;
						bmAlpha&=0xffff;

						bool doRed=true;
						bool doGreen=true;
						bool doBlue=true;
						bool doAlpha=true;

						if((bmRed&bmGreen)>0) throw new Exception("Bad bit fields");
						if((bmRed&bmBlue)>0) throw new Exception("Bad bit fields");
						if((bmGreen&bmBlue)>0) throw new Exception("Bad bit fields");

						int rshifta=0;
						while(((bmRed>>rshifta)&0x1)==0) rshifta++;
						int rshiftb=rshifta;
						while(((bmRed>>rshiftb)&0x1)!=0) rshiftb++;
						for(int i=rshiftb; i<16; i++) if((bmRed&1u<<i)>0) throw new Exception("Bad bit fields");

						int gshifta=0;
						while(((bmGreen>>gshifta)&0x1)==0) gshifta++;
						int gshiftb=gshifta;
						while(((bmGreen>>gshiftb)&0x1)!=0) gshiftb++;
						for(int i=gshiftb; i<16; i++) if((bmGreen&1u<<i)>0) throw new Exception("Bad bit fields");

						int bshifta=0;
						while(((bmBlue>>bshifta)&0x1)==0) bshifta++;
						int bshiftb=bshifta;
						while(((bmBlue>>bshiftb)&0x1)!=0) bshiftb++;
						for(int i=bshiftb; i<16; i++) if((bmBlue&1u<<i)>0) throw new Exception("Bad bit fields");

						int ashifta=0;
						int ashiftb=0;
						if(biCompression==BMPBiCompression.BI_BITFIELDS)
						{
							bmAlpha=~(bmRed|bmGreen|bmBlue);
							if(bmAlpha!=0xffff0000)
							{
								bmAlpha&=0xffff;
								ashifta=0;
								while(((bmAlpha>>ashifta)&0x1)==0) ashifta++;

								ashiftb=ashifta;
								while(((bmAlpha>>ashiftb)&0x1)!=0) ashiftb++;

								bmAlpha=~bmAlpha;
								for(int i=ashiftb; i<16; i++) bmAlpha|=1u<<i;
								bmAlpha=~bmAlpha;
							}
							else bmAlpha=0;
						}
						else
						{
							if((bmAlpha&bmRed)>0) throw new Exception("Bad bit fields");
							if((bmAlpha&bmGreen)>0) throw new Exception("Bad bit fields");
							if((bmAlpha&bmBlue)>0) throw new Exception("Bad bit fields");

							ashifta=0;
							while(((bmAlpha>>ashifta)&0x1)==0) ashifta++;
							ashiftb=ashifta;
							while(((bmAlpha>>ashiftb)&0x1)!=0) ashiftb++;
							for(int i=ashiftb; i<16; i++) if((bmAlpha&1u<<i)>0) throw new Exception("Bad bit fields");
						}

						if(bmRed==0) doRed=false;
						if(bmGreen==0) doGreen=false;
						if(bmBlue==0) doBlue=false;
						if(bmAlpha==0) doAlpha=false;

						if(!doRed&&!doGreen&&!doBlue&&!doAlpha) throw new Exception("Bad bit fields");

						int redSize=rshiftb-rshifta;
						int greenSize=gshiftb-gshifta;
						int blueSize=bshiftb-bshifta;
						int alphaSize=ashiftb-ashifta;
						#endregion

						#region 16 Bit
						int BytesPerRow=(biWidth*2);
						buffer=new byte[BytesPerRow*absHeight];

						if(biHeight>0) // buttom-up Bild
						{
							for(int i=0; i<absHeight; i++)
							{
								fileReader.Read(buffer, buffer.Length-(i+1)*BytesPerRow, BytesPerRow);
							}
						}
						else if(biHeight<0) // top-down Bild
						{
							fileReader.Read(buffer, 0, BytesPerRow*absHeight); // ganze bild auf einmal laden
						}

						uint redDiv=0, greenDiv=0, blueDiv=0, alphaDiv=0;
						if(doRed&&redSize<8) redDiv=1u<<redSize;
						if(doGreen&&greenSize<8) greenDiv=1u<<greenSize;
						if(doBlue&&blueSize<8) blueDiv=1u<<blueSize;
						if(doAlpha&&alphaSize<8) alphaDiv=1u<<alphaSize;

						// Bitmaske anwenden
						for(int i=0; i<biWidth*absHeight; i++)
						{
							int start=i*4;
							uint color=((uint)buffer[i*2+1]<<8)+(uint)buffer[i*2];

							if(doRed)
							{
								uint red=(color&bmRed)>>rshifta;
								if(redSize>8) red>>=redSize-8;
								if(redSize<8)
								{
									red<<=8-redSize;
									red+=red/redDiv;
								}
								ret.imageData[start+2]=(byte)red;
							}
							else ret.imageData[start+2]=0;

							if(doGreen)
							{
								uint green=(color&bmGreen)>>gshifta;
								if(greenSize>8) green>>=greenSize-8;
								if(greenSize<8)
								{
									green<<=8-greenSize;
									green+=green/greenDiv;
								}
								ret.imageData[start+1]=(byte)green;
							}
							else ret.imageData[start+1]=0;

							if(doBlue)
							{
								uint blue=(color&bmBlue)>>bshifta;
								if(blueSize>8) blue>>=blueSize-8;
								if(blueSize<8)
								{
									blue<<=8-blueSize;
									blue+=blue/blueDiv;
								}
								ret.imageData[start]=(byte)blue;
							}
							else ret.imageData[start]=0;

							if(doAlpha)
							{
								uint alpha=(color&bmAlpha)>>ashifta;
								if(alphaSize>8) alpha>>=alphaSize-8;
								if(alphaSize<8)
								{
									alpha<<=8-alphaSize;
									alpha+=alpha/alphaDiv;
								}
								ret.imageData[start+3]=(byte)alpha;
							}
							else ret.imageData[start+3]=0;
						}
						#endregion
					}
					else if(biBitCount==32)
					{
						#region Bitmasken checken
						bool doRed=true;
						bool doGreen=true;
						bool doBlue=true;
						bool doAlpha=true;

						if((bmRed&bmGreen)>0) throw new Exception("Bad bit fields");
						if((bmRed&bmBlue)>0) throw new Exception("Bad bit fields");
						if((bmGreen&bmBlue)>0) throw new Exception("Bad bit fields");

						int rshifta=0;
						while(((bmRed>>rshifta)&0x1)==0) rshifta++;
						int rshiftb=rshifta;
						while(((bmRed>>rshiftb)&0x1)!=0) rshiftb++;
						for(int i=rshiftb; i<32; i++) if((bmRed&1u<<i)>0) throw new Exception("Bad bit fields");

						int gshifta=0;
						while(((bmGreen>>gshifta)&0x1)==0) gshifta++;
						int gshiftb=gshifta;
						while(((bmGreen>>gshiftb)&0x1)!=0) gshiftb++;
						for(int i=gshiftb; i<32; i++) if((bmGreen&1u<<i)>0) throw new Exception("Bad bit fields");

						int bshifta=0;
						while(((bmBlue>>bshifta)&0x1)==0) bshifta++;
						int bshiftb=bshifta;
						while(((bmBlue>>bshiftb)&0x1)!=0) bshiftb++;
						for(int i=bshiftb; i<32; i++) if((bmBlue&1u<<i)>0) throw new Exception("Bad bit fields");

						int ashifta=0;
						int ashiftb=0;
						if(biCompression==BMPBiCompression.BI_BITFIELDS)
						{
							bmAlpha=~(bmRed|bmGreen|bmBlue);
							if(bmAlpha!=0)
							{
								ashifta=0;
								while(((bmAlpha>>ashifta)&0x1)==0) ashifta++;

								ashiftb=ashifta;
								while(((bmAlpha>>ashiftb)&0x1)!=0) ashiftb++;

								bmAlpha=~bmAlpha;
								for(int i=ashiftb; i<32; i++) bmAlpha|=1u<<i;
								bmAlpha=~bmAlpha;
							}
						}
						else
						{
							if((bmAlpha&bmRed)>0) throw new Exception("Bad bit fields");
							if((bmAlpha&bmGreen)>0) throw new Exception("Bad bit fields");
							if((bmAlpha&bmBlue)>0) throw new Exception("Bad bit fields");

							ashifta=0;
							while(((bmAlpha>>ashifta)&0x1)==0) ashifta++;
							ashiftb=ashifta;
							while(((bmAlpha>>ashiftb)&0x1)!=0) ashiftb++;
							for(int i=ashiftb; i<32; i++) if((bmAlpha&1u<<i)>0) throw new Exception("Bad bit fields");
						}

						if(bmRed==0) doRed=false;
						if(bmGreen==0) doGreen=false;
						if(bmBlue==0) doBlue=false;
						if(bmAlpha==0) doAlpha=false;

						if(!doRed&&!doGreen&&!doBlue&&!doAlpha) throw new Exception("Bad bit fields");

						int redSize=rshiftb-rshifta;
						int greenSize=gshiftb-gshifta;
						int blueSize=bshiftb-bshifta;
						int alphaSize=ashiftb-ashifta;
						#endregion

						#region 32 Bit
						int BytesPerRow=(biWidth*4);

						if(biHeight>0) // buttom-up Bild
						{
							for(int i=0; i<absHeight; i++)
							{
								fileReader.Read(ret.imageData, ret.imageData.Length-(i+1)*BytesPerRow, BytesPerRow);
							}
						}
						else if(biHeight<0) // top-down Bild
						{
							fileReader.Read(ret.imageData, 0, BytesPerRow*absHeight); // ganze bild auf einmal laden
						}

						uint redDiv=0, greenDiv=0, blueDiv=0, alphaDiv=0;
						if(doRed&&redSize<8) redDiv=1u<<redSize;
						if(doGreen&&greenSize<8) greenDiv=1u<<greenSize;
						if(doBlue&&blueSize<8) blueDiv=1u<<blueSize;
						if(doAlpha&&alphaSize<8) alphaDiv=1u<<alphaSize;

						// Bitmaske anwenden
						for(int i=0; i<biWidth*absHeight; i++)
						{
							int start=i*4;
							uint color=((uint)ret.imageData[start+3]<<24)+((uint)ret.imageData[start+2]<<16)+((uint)ret.imageData[start+1]<<8)+(uint)ret.imageData[start];

							if(doRed)
							{
								uint red=(color&bmRed)>>rshifta;
								if(redSize>8) red>>=redSize-8;
								if(redSize<8)
								{
									red<<=8-redSize;
									red+=red/redDiv;
								}
								ret.imageData[start+2]=(byte)red;
							}
							else ret.imageData[start+2]=0;

							if(doGreen)
							{
								uint green=(color&bmGreen)>>gshifta;
								if(greenSize>8) green>>=greenSize-8;
								if(greenSize<8)
								{
									green<<=8-greenSize;
									green+=green/greenDiv;
								}
								ret.imageData[start+1]=(byte)green;
							}
							else ret.imageData[start+1]=0;

							if(doBlue)
							{
								uint blue=(color&bmBlue)>>bshifta;
								if(blueSize>8) blue>>=blueSize-8;
								if(blueSize<8)
								{
									blue<<=8-blueSize;
									blue+=blue/blueDiv;
								}
								ret.imageData[start]=(byte)blue;
							}
							else ret.imageData[start]=0;

							if(doAlpha)
							{
								uint alpha=(color&bmAlpha)>>ashifta;
								if(alphaSize>8) alpha>>=alphaSize-8;
								if(alphaSize<8)
								{
									alpha<<=8-alphaSize;
									alpha+=alpha/alphaDiv;
								}
								ret.imageData[start+3]=(byte)alpha;
							}
							else ret.imageData[start+3]=0;
						}
						#endregion
					}

					return ret;
					#endregion
				}
				#endregion

				return ret;
			}
			catch(Exception)
			{
				return new Graphic();
			}
			finally
			{
				fileReader.Close();
			}
		}
Пример #29
0
		public Graphic ToRot270()
		{
			Graphic ret=new Graphic(height, width, channelFormat);
			if(ret.imageData==null) return ret;

			uint bpp=BytePerPixel;
			uint bw=width*bpp;

			uint dst=0;
			uint src_=(height-1)*bw;

			for(uint y=0; y<width; y++)
			{
				uint src=src_;
				for(uint x=0; x<height; x++)
				{
					for(uint i=0; i<bpp; i++) ret.imageData[dst++]=imageData[src++];
					src-=bw+bpp;
				}
				src_+=bpp;
			}
			return ret;
		}
Пример #30
0
		unsafe Graphic DownsampleH(uint w)
		{
			if((width*height)==0) return new Graphic(0, 0, channelFormat);
			if(w==0) return new Graphic(0, 0, channelFormat);

			if(width>w&&width%w==0) return ReduceByH(width/w);

			double delta=((double)width)/w;

			if(channelFormat==Format.GRAY)
			{
				Graphic ret=new Graphic(w, height, channelFormat);
				if(ret.imageData==null) return ret;

				fixed(byte* _dst=ret.imageData, _src=imageData)
				{
					byte* dst=_dst;
					for(uint y=0; y<height; y++)
					{
						byte* src=_src+y*width;

						for(uint x=0; x<w; x++)
						{
							double deltax=x*delta;
							double dx=1-(deltax-((uint)deltax));
							byte* s=src+((uint)deltax);
							double deltasum=dx;

							double gsum=*(s++)*dx;

							while((delta-deltasum)>0.0001)
							{
								dx=delta-deltasum;
								if(dx>=1)
								{
									deltasum+=1;
									gsum+=*(s++);
								}
								else
								{
									gsum+=*s*dx;
									break;
								}
							}

							*(dst++)=(byte)(gsum/delta+0.5);
						}
					}
				}
				return ret;
			}

			if(channelFormat==Format.RGB||channelFormat==Format.BGR)
			{
				Graphic ret=new Graphic(w, height, channelFormat);
				if(ret.imageData==null) return ret;

				fixed(byte* _dst=ret.imageData, _src=imageData)
				{
					byte* dst=_dst;
					uint wb=width*3;
					for(uint y=0; y<height; y++)
					{
						byte* src=_src+y*wb;

						for(uint x=0; x<w; x++)
						{
							double deltax=x*delta;
							double dx=1-(deltax-((uint)deltax));
							byte* s=src+((uint)deltax)*3;
							double deltasum=dx;

							double rsum=*(s++)*dx;
							double gsum=*(s++)*dx;
							double bsum=*(s++)*dx;

							while((delta-deltasum)>0.0001)
							{
								dx=delta-deltasum;
								if(dx>=1)
								{
									deltasum+=1;
									rsum+=*(s++);
									gsum+=*(s++);
									bsum+=*(s++);
								}
								else
								{
									rsum+=*(s++)*dx;
									gsum+=*(s++)*dx;
									bsum+=*s*dx;
									break;
								}
							}

							*(dst++)=(byte)(rsum/delta+0.5);
							*(dst++)=(byte)(gsum/delta+0.5);
							*(dst++)=(byte)(bsum/delta+0.5);
						}
					}
				}
				return ret;
			}

			if(channelFormat==Format.RGBA||channelFormat==Format.BGRA)
			{
				Graphic ret=new Graphic(w, height, channelFormat);
				if(ret.imageData==null) return ret;

				fixed(byte* _dst=ret.imageData, _src=imageData)
				{
					byte* dst=_dst;
					uint wb=width*4;
					for(uint y=0; y<height; y++)
					{
						byte* src=_src+y*wb;

						for(uint x=0; x<w; x++)
						{
							double deltax=x*delta;
							double dx=1-(deltax-((uint)deltax));
							byte* s=src+((uint)deltax)*4;
							double deltasum=dx;

							byte r=*(s++), g=*(s++), b=*(s++);
							uint a=*(s++);

							double adx=a*dx;
							double rsum=r*adx;
							double gsum=g*adx;
							double bsum=b*adx;
							double asum=adx;

							while((delta-deltasum)>0.0001)
							{
								dx=delta-deltasum;
								r=*(s++); g=*(s++); b=*(s++); a=*(s++);
								if(dx>=1)
								{
									deltasum+=1;
									rsum+=r*a;
									gsum+=g*a;
									bsum+=b*a;
									asum+=a;
								}
								else
								{
									adx=a*dx;
									rsum+=r*adx;
									gsum+=g*adx;
									bsum+=b*adx;
									asum+=adx;
									break;
								}
							}

							*(dst++)=(byte)(rsum/asum+0.5);
							*(dst++)=(byte)(gsum/asum+0.5);
							*(dst++)=(byte)(bsum/asum+0.5);
							*(dst++)=(byte)(asum/delta+0.5);
						}
					}
				}
				return ret;
			}

			if(channelFormat==Format.GRAYAlpha)
			{
				Graphic ret=new Graphic(w, height, channelFormat);
				if(ret.imageData==null) return ret;

				fixed(byte* _dst=ret.imageData, _src=imageData)
				{
					byte* dst=_dst;
					uint wb=width*2;
					for(uint y=0; y<height; y++)
					{
						byte* src=_src+y*wb;

						for(uint x=0; x<w; x++)
						{
							double deltax=x*delta;
							double dx=1-(deltax-((uint)deltax));
							byte* s=src+((uint)deltax)*2;
							double deltasum=dx;

							byte g=*(s++);
							uint a=*(s++);

							double gsum=g*dx*a;
							double asum=a*dx;

							while((delta-deltasum)>0.0001)
							{
								dx=delta-deltasum;
								g=*(s++); a=*(s++);
								if(dx>=1)
								{
									deltasum+=1;
									gsum+=g*a;
									asum+=a;
								}
								else
								{
									double adx=a*dx;
									gsum+=g*adx;
									asum+=adx;
									break;
								}
							}

							*(dst++)=(byte)(gsum/asum+0.5);
							*(dst++)=(byte)(asum/delta+0.5);
						}
					}
				}
				return ret;
			}

			return new Graphic(0, 0, channelFormat);
		}