Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by POiD · Dec 13, 2013 at 02:55 AM · textures

Split BMP into smaller Textures using Unity

I am currently trying to split a larger BMP (304x160) into smaller Bmp files (16x16) using C# script in unity. Unfortunately I cannot add the larger BMP file to the Project but must load it using System.IO as eventually this BMP file will be sent from a game server.

I've tried splitting the larger BMP into smaller BMPs using two methods:

  1. using System.Drawing.Graphics.DrawImage()

  2. using System.Drawing.Bitmap.Clone()

Unfortunately option #1 throws an Invalid Win32 GDI exception while Option #2 is throwing an "OutOfMemoryException".

The end goal is: I need to split this larger BMP (which holds 2d textures), store these Texture2Ds in an array, so that I can apply each texture to a cube (instantiated prefab). Which texture to use is specified by the game server depending on the location of the cube.

I'm currently at a loss as how to get around these issues while working within the Unity Framework. (Yes I know using System.Drawing isn't exactly in the framework but supoorted when I drag/dropped it into my Project).

Any suggestions are welcome!


Current Code attempts:

                 public static bool BitmapToArray(out System.Drawing.Bitmap[,] tiles, System.Drawing.Bitmap bmpfile, int dimX, int dimY, int padX, int padY)
                 {
                     int itemsInX = (bmpfile.Width - padX) / (dimX + padX);
                     int itemsInY = (bmpfile.Height - padY) / (dimY + padY);
                     tiles = new Bitmap[itemsInX, itemsInY];
                     
                     for (int i = 0; i < itemsInY; i++)
                     {
                         for (int j = 0; j < itemsInX; j++)
                         {
                             //below caused errors
                             //System.Drawing.Bitmap smallBMP = new System.Drawing.Bitmap(dimX, dimY);
                             //Graphics g = Graphics.FromImage(smallBMP);
                             //g.DrawImage (bmpfile, 0, 0, new Rectangle((j*dimX)+ padX,(i*dimY)+padY, dimX, dimY), GraphicsUnit.Pixel);
                             //g.Dispose();
                             //tiles[j,i] = smallBMP;
                                                                                             
                             tiles[j,i] = bmpfile.Clone(new Rectangle((j*dimX)+ padX,(i*dimY)+padY, dimX, dimY),System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                         }
                     }
                     return true;
                 }
 
Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image POiD · Dec 24, 2013 at 11:20 PM 0
Share

Update:

I'm still stuck on this issue. It turns out that my code works fine for Bitmaps in a non-indexed format. However, unfortunately, it does not work for Indexed formats, such as the Format8bppIndexed Pixelformat that I have receiving from the game server.

I've even tried using System.Drawing.Bitmap.LockBits and accessing the pixel data directly. Unfortunately with Unity this does not work and throws errors.

I'm still stuck trying to access the pixel information from the Format8bppIndexed bitmap, so that I can split it and convert it into a Texture2d for use in Unity.

Any suggestions at all on how to proceed???

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by iwaldrop · Dec 24, 2013 at 11:09 PM

You don't need to break them up at all. Just adjust the UV coordinates of the cube's material instance to the location on the texture. This has the added benefit of allowing all of your blocks to be dynamically batched for fewer drawcalls, which in-turn allows higher frame rates.

Checkout the material page in the Unity Docs for info about texture offsets. To discover the offsets you can manually set play with them in the inspector and evaluate which offsets each type of block should have.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image POiD · Dec 25, 2013 at 12:14 AM 0
Share

Unfortunately when i attempt to do this I run into an issue trying to just apply the format8bppIndexed bmp to a Texture. This process works with 32 bit formats of Bmps but not the 8 bit Indexed. I assume this is because internally it is trying to use getPixel / setPixel.

For example the following code that I tried to do fails on the .save(). Note that tileset is my format8bppIndexed bitmap.

         Texture2D tileTexture = new Texture2D(tileSet.Width,tileSet.Height);
         using ($$anonymous$$emoryStream ms = new $$anonymous$$emoryStream())
         {
             tileSet.Save (ms, System.Drawing.Imaging.ImageFormat.Png);
             //tileSet.Save (ms, System.Drawing.Imaging.ImageFormat.Bmp);
             tileTexture.LoadImage (ms.ToArray());
         }



$$anonymous$$gestion on how to proceed in this route? I'm all for trying anything that works!

avatar image iwaldrop · Dec 25, 2013 at 12:38 AM 0
Share

Like so:

 using UnityEngine;
 using System.Collections;
 
 public class TextureOffsetter : $$anonymous$$onoBehaviour
 {
     public Texture2D texture;
     public Vector2 offset;
     public Vector2 scale;
 
     void Awake()
     {
         renderer.material.mainTexture = texture;
         renderer.material.mainTextureScale = scale;
         renderer.material.mainTextureOffset = offset;
     }
 }
 

Again, focus your attention on the $$anonymous$$aterial's mainTextureOffset and mainTextureScale properties.

For a single texture that has 4 sub-images, set your scale to 0.5 for both x and y, and to change them alternate combinations of 0 and 0.5 for offset x and y. Obviously you can fit many images into the same texture, just to the math:

1 / {number of textures} = scale

avatar image POiD · Dec 30, 2013 at 03:48 PM 0
Share

Thanks for the information iwaldrop. I've started using the texture offset ins$$anonymous$$d of splitting the bmps. Has made my life a little easier.

It wasn't my main issue in the end, the problem was the way I was loading the B$$anonymous$$P from the file, creating a $$anonymous$$emoryStream to save it but then disposing of the $$anonymous$$emoryStream. Later on in the code when i tried to access the B$$anonymous$$P all GDI+ activities (.save, .lockbits, etc) all failed. From my tinkering around for ages and a chance 'mistake' (forgetting to dispose of the memorystream for a test load that ended up in everything working), I was pointed to the .dispose actually being the problem. It had nothing to do with the bitmap pixelformat (regardless of if the B$$anonymous$$P in the file was format8bppIndexed or format16Rgb or even format32rgb). Turns out that the memorystream becomes attached to the created Bit$$anonymous$$ap when creating it from that memorystream. As such, you shouldn't dispose it, as disposing of the Bit$$anonymous$$ap later will take care of that.

$$anonymous$$ore information on that is here (for any others that come across this post): http://stackoverflow.com/questions/336387/image-save-throws-a-gdi-exception-because-the-memory-stream-is-closed

Your answer pointed me in the right direction so I've accepted it! Thanks for the help.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

17 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

How to import the object from server to unity 2 Answers

How to Best Implement a Tileset 1 Answer

Help?! Changing Textures via mouse click 1 Answer

Select an object, then change the texture 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges