/// <summary> /// copies this bitmap and trims out transparent pixels, returning the offset to the topleft pixel /// </summary> public BitmapBuffer Trim(out int xofs, out int yofs) { int minx = int.MaxValue; int maxx = int.MinValue; int miny = int.MaxValue; int maxy = int.MinValue; for (int y = 0; y < Height; y++) { for (int x = 0; x < Width; x++) { int pixel = GetPixel(x, y); int a = (pixel >> 24) & 0xFF; if (a != 0) { minx = Math.Min(minx, x); maxx = Math.Max(maxx, x); miny = Math.Min(miny, y); maxy = Math.Max(maxy, y); } } } if (minx == int.MaxValue || maxx == int.MinValue || miny == int.MaxValue || minx == int.MinValue) { xofs = yofs = 0; return(new BitmapBuffer(0, 0)); } int w = maxx - minx + 1; int h = maxy - miny + 1; BitmapBuffer bbRet = new BitmapBuffer(w, h); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { bbRet.SetPixel(x, y, GetPixel(x + minx, y + miny)); } } xofs = minx; yofs = miny; return(bbRet); }
/// <summary> /// copies this bitmap and trims out transparent pixels, returning the offset to the topleft pixel /// </summary> public BitmapBuffer Trim(out int xofs, out int yofs) { int minx = int.MaxValue; int maxx = int.MinValue; int miny = int.MaxValue; int maxy = int.MinValue; for (int y = 0; y < Height; y++) for (int x = 0; x < Width; x++) { int pixel = GetPixel(x, y); int a = (pixel >> 24) & 0xFF; if (a != 0) { minx = Math.Min(minx, x); maxx = Math.Max(maxx, x); miny = Math.Min(miny, y); maxy = Math.Max(maxy, y); } } if (minx == int.MaxValue || maxx == int.MinValue || miny == int.MaxValue || minx == int.MinValue) { xofs = yofs = 0; return new BitmapBuffer(0, 0); } int w = maxx - minx + 1; int h = maxy - miny + 1; BitmapBuffer bbRet = new BitmapBuffer(w, h); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { bbRet.SetPixel(x, y, GetPixel(x + minx, y + miny)); } xofs = minx; yofs = miny; return bbRet; }
/// <summary> /// Closes this instance for for further resource loading. Will result in a texture atlasing operation. /// If the close operation is forever, then internal backup copies of resources will be freed, but it can never be reopened. /// This function may take some time to run, as it is /// </summary> public unsafe void Close(bool forever = true) { AssertIsOpen(true); IsOpened = false; IsClosedForever = forever; // first, cleanup old stuff foreach (var tex in ManagedTextures) { tex.Dispose(); } ManagedTextures.Clear(); // prepare input for atlas process and perform atlas // add 2 extra pixels for padding on all sides var atlasItems = new List <TexAtlas.RectItem>(); foreach (var kvp in ArtLooseTextureAssociation) { atlasItems.Add(new TexAtlas.RectItem(kvp.Value.Width + 2, kvp.Value.Height + 2, kvp)); } var results = TexAtlas.PackAtlas(atlasItems); // this isn't supported yet: if (results.Atlases.Count > 1) { throw new InvalidOperationException("Art files too big for atlas"); } // prepare the output buffer BitmapBuffer bmpResult = new BitmapBuffer(results.Atlases[0].Size); //for each item, copy it into the output buffer and set the tex parameters on them for (int i = 0; i < atlasItems.Count; i++) { var item = results.Atlases[0].Items[i]; var artAndBitmap = (KeyValuePair <Art, BitmapBuffer>)item.Item; var art = artAndBitmap.Key; var bitmap = artAndBitmap.Value; int w = bitmap.Width; int h = bitmap.Height; int dx = item.X + 1; int dy = item.Y + 1; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int pixel = bitmap.GetPixel(x, y); bmpResult.SetPixel(x + dx, y + dy, pixel); } } var myDestBitmap = bmpResult; float myDestWidth = (float)myDestBitmap.Width; float myDestHeight = (float)myDestBitmap.Height; art.u0 = dx / myDestWidth; art.v0 = dy / myDestHeight; art.u1 = (dx + w) / myDestWidth; art.v1 = (dy + h) / myDestHeight; art.Width = w; art.Height = h; } //if we're closed forever, then forget all the original bitmaps if (forever) { foreach (var kvp in ArtLooseTextureAssociation) { kvp.Value.Dispose(); } ArtLooseTextureAssociation.Clear(); } //create a physical texture var texture = Owner.LoadTexture(bmpResult); ManagedTextures.Add(texture); //oops, we couldn't do this earlier. foreach (var art in ManagedArts) { art.BaseTexture = texture; } }
/// <summary> /// Closes this instance for for further resource loading. Will result in a texture atlasing operation. /// If the close operation is forever, then internal backup copies of resources will be freed, but it can never be reopened. /// This function may take some time to run, as it is /// </summary> public unsafe void Close(bool forever = true) { AssertIsOpen(true); IsOpened = false; IsClosedForever = forever; //first, cleanup old stuff foreach (var tex in ManagedTextures) tex.Dispose(); ManagedTextures.Clear(); //prepare input for atlas process and perform atlas //add 2 extra pixels for padding on all sides List<TexAtlas.RectItem> atlasItems = new List<TexAtlas.RectItem>(); foreach (var kvp in ArtLooseTextureAssociation) atlasItems.Add(new TexAtlas.RectItem(kvp.Value.Width+2, kvp.Value.Height+2, kvp)); var results = TexAtlas.PackAtlas(atlasItems); //this isnt supported yet: if (results.Atlases.Count > 1) throw new InvalidOperationException("Art files too big for atlas"); //prepare the output buffer BitmapBuffer bmpResult = new BitmapBuffer(results.Atlases[0].Size); //for each item, copy it into the output buffer and set the tex parameters on them for (int i = 0; i < atlasItems.Count; i++) { var item = results.Atlases[0].Items[i]; var artAndBitmap = (KeyValuePair<Art, BitmapBuffer>)item.Item; var art = artAndBitmap.Key; var bitmap = artAndBitmap.Value; int w = bitmap.Width; int h = bitmap.Height; int dx = item.X + 1; int dy = item.Y + 1; for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { int pixel = bitmap.GetPixel(x, y); bmpResult.SetPixel(x+dx,y+dy,pixel); } var myDestBitmap = bmpResult; float myDestWidth = (float)myDestBitmap.Width; float myDestHeight = (float)myDestBitmap.Height; art.u0 = dx / myDestWidth; art.v0 = dy / myDestHeight; art.u1 = (dx + w) / myDestWidth; art.v1 = (dy + h) / myDestHeight; art.Width = w; art.Height = h; } //if we're closed forever, then forget all the original bitmaps if (forever) { foreach (var kvp in ArtLooseTextureAssociation) kvp.Value.Dispose(); ArtLooseTextureAssociation.Clear(); } //create a physical texture var texture = Owner.LoadTexture(bmpResult); ManagedTextures.Add(texture); //oops, we couldn't do this earlier. foreach (var art in ManagedArts) art.BaseTexture = texture; }