Draw a GraphicsPath in a PDF - itext

I am trying to create a PDF based on some vector art I have in my C# application. I have two major problems when I try to map the points and types from a GraphicsPath.
Some paths are just plain missing.
When a sub path is an internal boundary I need to indicate that somehow. ie, the circle in the letter d is filled in.
I'm referencing iTextSharp 5.5.2 on NuGet. I'm only using AddString here because I want an easy way to demonstrate creating a complex path in this example. For my need I won't be using a path to place text in the PDF.
using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PdfGen
{
class StackQuestion
{
public static void Main()
{
string filename = #"d:\itext.pdf";
using (var doc = new Document())
using (var fs = new FileStream(filename, FileMode.Create))
{
var writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
writer.DirectContent.SetColorFill(BaseColor.BLACK);
var path = new GraphicsPath(FillMode.Winding);
path.AddString("Hello World", FontFamily.GenericSerif,
(int)FontStyle.Regular, 25f, RectangleF.Empty,
StringFormat.GenericDefault);
AddPath(path, writer.DirectContent);
doc.Close();
}
System.Diagnostics.Process.Start(filename);
}
static void AddPath(GraphicsPath path, PdfContentByte to)
{
var view = to.PdfDocument.PageSize;
path.FillMode = System.Drawing.Drawing2D.FillMode.Winding;
var d = path.PathData;
for (int i = 0; i < d.Points.Length && i < d.Types.Length; i++)
{
var t = (PathPointType)d.Types[i];
var p = Fix(d.Points[i], view);
if (Match(t, PathPointType.Bezier))
{
var p2 = Fix(d.Points[++i], view);
if (d.Types.Length > i + 1 &&
Match((PathPointType)d.Types[i + 1],
PathPointType.Bezier3))
{
var p3 = Fix(d.Points[++i], view);
to.CurveTo(p.X, p.Y, p2.X, p2.Y, p3.X, p3.Y);
}
else
{
to.CurveTo(p.X, p.Y, p2.X, p2.Y);
}
}
if (Match(t, PathPointType.Line))
{
to.LineTo(p.X, p.Y);
}
if (Match(t, PathPointType.CloseSubpath))
{
to.ClosePath();
to.EoFill();
}
if (t == PathPointType.Start)
{
to.NewPath();
to.MoveTo(p.X, p.Y);
}
}
}
static bool Match(PathPointType type, PathPointType match)
{
return (type & match) == match;
}
static System.Drawing.PointF Fix(System.Drawing.PointF pt,
iTextSharp.text.Rectangle view)
{
return new System.Drawing.PointF(pt.X, view.Height - pt.Y);
}
}
}

I'm posting an answer to myself in case anyone else is in need of a simple function to plot out a GraphicsPath in iTextSharp. I had two problems with my sample code in the question:
as mkl pointed out I was trying to fill too often
I failed to notice that PathPointType.Line is a valid mask in PathPointType.Bezier so the code placing a line back to the origin after a curve.
Updatd Code:
using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
namespace PdfGen
{
class StackQuestion
{
public static void Main()
{
string filename = #"d:\itext.pdf";
using (var doc = new Document())
using (var fs = new FileStream(filename, FileMode.Create))
{
var writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
writer.DirectContent.SetColorFill(BaseColor.BLACK);
var path = new GraphicsPath(FillMode.Winding);
path.AddString("Hello World", FontFamily.GenericSansSerif,
(int)FontStyle.Regular, 90f, PointF.Empty,
StringFormat.GenericDefault);
AddPath(path, writer.DirectContent);
writer.DirectContent.EoFill();
doc.Close();
}
System.Diagnostics.Process.Start(filename);
}
static void AddPath(GraphicsPath path, PdfContentByte to)
{
var view = to.PdfDocument.PageSize;
var d = path.PathData;
to.NewPath();
PointF? start = null;
for (int i = 0; i < d.Points.Length && i < d.Types.Length; i++)
{
var t = (PathPointType)d.Types[i];
var p = Fix(d.Points[i], view);
if (Match(t, PathPointType.Bezier))
{
var p2 = Fix(d.Points[++i], view);
if (d.Types.Length > i + 1 &&
Match((PathPointType)d.Types[i + 1],
PathPointType.Bezier))
{
var p3 = Fix(d.Points[++i], view);
to.CurveTo(p.X, p.Y, p2.X, p2.Y, p3.X, p3.Y);
}
else
{
to.CurveTo(p.X, p.Y, p2.X, p2.Y);
}
}
else if (Match(t, PathPointType.Line))
{
to.LineTo(p.X, p.Y);
}
if (Match(t, PathPointType.CloseSubpath))
{
if (start != null)
to.LineTo(start.Value.X, start.Value.Y);
start = null;
to.ClosePath();
}
if (t == PathPointType.Start)
{
if (start != null)
to.LineTo(start.Value.X, start.Value.Y);
start = p;
to.MoveTo(p.X, p.Y);
}
}
}
static bool Match(PathPointType type, PathPointType match)
{
return (type & match) == match;
}
static System.Drawing.PointF Fix(System.Drawing.PointF pt,
iTextSharp.text.Rectangle view)
{
return new System.Drawing.PointF(pt.X, view.Height - pt.Y);
}
}
}

Related

Unity Object Detection: Barracuda, MobileNET and Webcam

I am trying to run the following ONNX model in Unity, using Barracuda and the following pre-trained model:
https://github.com/onnx/models/tree/master/vision/classification/mobilenet
with my webcam as the camera, and using the following script to test the system:
using UnityEngine;
using UnityEngine.UI;
using Unity.Barracuda;
using System.IO;
using System.Linq;
public class Webcam : MonoBehaviour
{
public NNModel mob_net;
public Model model;
private IWorker worker;
int current_cam_index = 0;
WebCamTexture tex;
public RawImage display;
private bool brain_on = false;
private const int SIZE = 224;
public void start_cam()
{
model = ModelLoader.Load(mob_net);
worker = WorkerFactory.CreateWorker(WorkerFactory.Type.ComputePrecompiled, model);
if (tex != null)
{
stop_cam();
}
else
{
WebCamDevice device = WebCamTexture.devices[current_cam_index];
tex = new WebCamTexture(device.name);
display.texture = tex;
tex.Play();
}
}
public void stop_cam()
{
display.texture = null;
tex.Stop();
tex = null;
}
void crop__normalize_inference(WebCamTexture src)
{
int x = Mathf.FloorToInt(display.transform.position.x);
int y = Mathf.FloorToInt(display.transform.position.y);
Color[] pix = src.GetPixels(x, y, SIZE, SIZE);
Texture2D dest = new Texture2D(SIZE, SIZE);
dest.SetPixels(pix);
dest.Apply();
float[] floats = new float[224 * 224 * 3];
for (int i = 0; i < pix.Length; ++i)
{
var color = pix[i];
floats[i * 3 + 0] = (color.r - 127) / 127.5f;
floats[i * 3 + 1] = (color.g - 127) / 127.5f;
floats[i * 3 + 2] = (color.b - 127) / 127.5f;
}
Tensor in_tensor = new Tensor(1, 224, 224, 3, floats);
worker.Execute(in_tensor);
Tensor out_tensor = worker.PeekOutput("MobilenetV2/Predictions/Reshape_1");
var max = Mathf.Max(out_tensor.ToReadOnlyArray());
var arr = out_tensor.ToReadOnlyArray();
var index = System.Array.IndexOf(arr, max);
string line = File.ReadLines(#"D:\Unity\WebCam\Cam\Assets\Scenes\mobile_net.txt").Skip(index).Take(1).First();
Debug.Log(line);
in_tensor.Dispose();
out_tensor.Dispose();
worker.Dispose();
}
public void brain()
{
brain_on = !brain_on;
}
private void Update()
{
if (brain_on)
{
crop_and_normalize(tex);
brain_on = false;
}
}
}
But when I run it I get an error which says:
ArgumentException: Can only specify one unknown dimension
My guess is that either Unity doesn't support the model, or that for some reason my input tensor form is incorrect . . .
Any help would be massively appreciated,
K
Solution: Set to barracuda V1.3.0

Why Can't I instatiate my object in the position that want at unity?

I'm trying instantiate a sphere to use like a bullet. I want that the bullet be align like the image bellow:
the desirable situation
but when I instantiate through interactive way a have a problem, The sphere stay in diferente coordinate completely different of that I instantiated previouslly. look at the image:
the real situation
why does it happen? how can I solve it?
follow the code from Player.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Player
{
public string name;
int currentLife;
int maxLife;
int mentalPower;
public GameObject obj3d; // variável de referência ao modelo 3d do player
// métodos
public Player(string nome, int vidaTotal, int forcaMental)
{
name = nome;
maxLife = vidaTotal;
currentLife = maxLife;
mentalPower = forcaMental;
}
public int Atack(ref bool critico)
{
int aux = mentalPower / 2;
int damage = mentalPower + Random.Range(-aux, aux);
int critical = Random.Range(0, 100);
if(critical < 5) // ataque critico
{
critico = true;
damage *= 2;
}
else
{
critico = false;
}
return (damage);
}
public bool UpdateLife(int dano)
{
currentLife -= dano;
if (currentLife < 0)
{
//comando para destruir o objeto
Object.Destroy(obj3d);
return false;
}
else
return true;
}
public int getLife(int tipo)
{
if (tipo == 0)
return currentLife;
else
return maxLife;
}
public string getName(Player player)
{
return player.name;
}
}
from the Battle.cs:
`using System.Collections;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Battle : MonoBehaviour
{
Player[] players;
int status; // -1= game não começou,0 =game rolando, 1= player 1 vencedor , 2 = player 2 venceu.
Vector3[] spawnPoints;
Quaternion[] rotSpawnPoints;
Color[] playerColors;
public GameObject myPrefab;
Text titulo, info, lifePlayer1, lifePlayer2;
// Bullet
public GameObject objBullet;
Vector3 spawBullet;
// Start is called before the first frame update
void Start()
{
players = new Player[2];
status = -1;
spawnPoints = new Vector3[2];
spawnPoints[0] = new Vector3(2.24f, 0.97f, -4.46f);
spawnPoints[1] = new Vector3(-6.13f, 0.8f, 3.79f);
rotSpawnPoints = new Quaternion[2];
rotSpawnPoints[0] = Quaternion.Euler(0.0f, -250.0f, 0.0f);
rotSpawnPoints[1] = Quaternion.Euler(0.0f, -75.0f, 0.0f);
playerColors = new Color[2];
playerColors[0] = Color.blue;
playerColors[1] = Color.red;
titulo = GameObject.Find("Title").GetComponent<Text>();
info = GameObject.Find("Info").GetComponent<Text>();
lifePlayer1 = GameObject.Find("LifePlayer1").GetComponent<Text>();
lifePlayer2 = GameObject.Find("LifePlayer2").GetComponent<Text>();
spawBullet = new Vector3(1.268f, 1.45f, -3.763f);
}
void CreatePlayer(int nPlayer)
{
print("Entrou na Create Player() com arg = " + nPlayer);
players[nPlayer - 1].obj3d = (GameObject)Instantiate(myPrefab, spawnPoints[nPlayer - 1], rotSpawnPoints[nPlayer - 1]);
players[nPlayer - 1].obj3d.name = "Player" + nPlayer;
players[nPlayer - 1].obj3d.GetComponent<MeshRenderer>().material.color = playerColors[nPlayer - 1];
ControlaInterface();
}
void ControlaCritico(bool status)
{
if (status == true)
{
GameObject.Find("Title").GetComponent<Text>().enabled = true;
GameObject.Find("Title").GetComponent<Text>().color = new Color(GameObject.Find("Title").GetComponent<Text>().color.r, GameObject.Find("Title").GetComponent<Text>().color.g,
GameObject.Find("Title").GetComponent<Text>().color.b, 255f);
GameObject.Find("Title").GetComponent<Text>().text = "CRITOU URRUUU!!!!";
}
else
GameObject.Find("Title").GetComponent<Text>().enabled = false;
}
void ControlaInterface()
{
print("entrei na controla inter");
if(players[0] == null)// entra aqui quando aperta F2
{
print("entrou primeiro if");
GameObject.Find("Title").GetComponent<Text>().text = " Aguardando\nPlayer 1 Azul";
lifePlayer2.enabled = true;
lifePlayer2.text = players[1].getLife(0).ToString() + "/" + players[1].getLife(1).ToString();
}
else if(players[1] == null)// entra aqui quando aperta F1
{
print("entrou segundo if");
GameObject.Find("Title").GetComponent<Text>().text = " Aguardando\nPlayer 2 Vemelho";
lifePlayer1.enabled = true;
lifePlayer1.text = players[0].getLife(0).ToString() + "/" + players[0].getLife(1).ToString();
}
else // player 0 e 1 são diferentes de null
{
print("entrou no else");
lifePlayer2.enabled = true;
lifePlayer1.enabled = true;
lifePlayer2.text = players[1].getLife(0).ToString() + "/" + players[0].getLife(1).ToString();
lifePlayer1.text = players[0].getLife(0).ToString() + "/" + players[1].getLife(1).ToString();
GameObject.Find("Title").GetComponent<Text>().enabled = false;
if (status == -1)
status = 0;
}
GameObject objTmp = null;
}
// Update is called once per frame
void Update()
{
if (status == -1)
titulo.color = new Color(titulo.color.r, titulo.color.g, titulo.color.b,Mathf.Sin(Time.time*2.0f +1.0f)/2.0f) ;
if (Input.GetKeyDown(KeyCode.F1)) //criar player 1(Azul)
{
if (players[0] == null)
{
players[0] = new Player("Player 1 Azul", 100, 14);
CreatePlayer(1);
//GameObject.Find("Title").GetComponent<Text>().enabled = false;
}
}
//-4.87f, 0.8f, -4.83f
if(Input.GetKeyDown(KeyCode.F10))// reseta o game
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
if (Input.GetKeyDown(KeyCode.F2)) //criar player 2(vermelho)
{
if (players[1] == null)
{
players[1] = new Player("Player 2 Vermelho", 100, 14);
CreatePlayer(2);
// GameObject.Find("Title").GetComponent<Text>().enabled = false;
}
}
if (Input.GetKeyDown(KeyCode.Alpha1)) // ataque do player 1
{
//if (objTmp == null)
GameObject objTmp = (GameObject)Instantiate(objBullet, new Vector3(-0.52f, 0.4f, 0.57f), Quaternion.Euler(0f, -45f, 0f));
objTmp.transform.parent = players[0].obj3d.transform;
objTmp.transform.localPosition = spawBullet;
}
}
//-4.87f, 0.8f, -4.83f
if (Input.GetKeyDown(KeyCode.Alpha2)) //ataque player 2(vermelho)
{
// if(objTmp == null)
GameObject objTmp = (GameObject)Instantiate(objBullet, new Vector3(-4.5f, 0.3f, 5.514f), Quaternion.Euler(0f, -45f, 0f));
objTmp.transform.parent = players[1].obj3d.transform;
objTmp.transform.localPosition = spawBullet;
}
}
}
`

Unity GUI combo box with search

I need a list which is a lot of list (enum list). And right now the list is using the pop up (combo box), but the normal combo box is not really help because too many item inside it. It kind of frustrating when try to select item that is far away at bottom. The list are full on the screen when openned.
When openning a combo box and type a letter it will jump only the first letter, when I press second letter the list will be jump to another first letter start. So example, I want to select DIAMOND -> I press D and it will go to the list with D start. And when I press I, it will jump to item that start with I instead of DI.
Is there any component of GUI to have the search?
Unity haven't components for search like your.
But you can try something like this (SearchEnumLabel function):
using System;
using System.Globalization;
using System.Linq;
using UnityEditor;
public enum States
{
ABCDEF,
ACBDEF,
AdEXG,
bErDSa
}
[CustomEditor(typeof(ObjectControllerTester))]
[CanEditMultipleObjects]
public class ObjectControllerTesterEditor : Editor
{
States _selected;
public override void OnInspectorGUI ()
{
_selected = SearchEnumLabel("My search enum", _selected);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("[Debug]Current selected: "+_selected);
}
private String _searchEnumText = "";
private bool _isSearchEnumLabelInSearch = false;
private T SearchEnumLabel<T>(String label, T state) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
EditorGUILayout.LabelField("T must be an enumerated type");
return state;
}
var states = Enum.GetValues(typeof (T)).Cast<object>().Select(o => o.ToString()).ToArray();
if (string.IsNullOrEmpty(_searchEnumText) && states.Length > 0) _searchEnumText = state.ToString(CultureInfo.InvariantCulture);
var text = EditorGUILayout.TextField(label, _searchEnumText);
if (text != _searchEnumText || _isSearchEnumLabelInSearch)
{
_searchEnumText = text;
var mach = states.Select((v,i)=>new {value = v, index = i}).FirstOrDefault(a => a.value.ToLower().StartsWith(text.ToLower()));
var targetState = state;
if (mach != null) targetState = (T) Enum.GetValues(typeof (T)).GetValue(mach.index);
EditorGUILayout.LabelField("Select closest: "+targetState);
Repaint();
state = targetState;
_isSearchEnumLabelInSearch = !string.Equals(_searchEnumText, targetState.ToString(CultureInfo.InvariantCulture), StringComparison.CurrentCultureIgnoreCase);
}
return state;
}
}
This script will show something like this:
Default view
After input some data
=== UPDATE ===
More complex variant with fast select buttons
using System;
using System.Globalization;
using System.Linq;
using UnityEditor;
using UnityEngine;
public enum States
{
ABCDEF,
ACBDEF,
AdEXG,
bErDSa,
sEOjsfl,
SdDiaso,
POsdjaow,
PSADJsd,
Oasdo,
IOQWEnds
}
[CustomEditor(typeof(ObjectControllerTester))]
[CanEditMultipleObjects]
public class ObjectControllerTesterEditor : Editor
{
States _selected;
public override void OnInspectorGUI()
{
_selected = SearchEnumLabel("My search enum", _selected);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField("[Debug]Current selected: " + _selected);
}
private String _searchEnumText = "";
private bool _isSearchEnumLabelInSearch = false;
private T SearchEnumLabel<T>(String label, T state) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
EditorGUILayout.LabelField("T must be an enumerated type");
return state;
}
var states = Enum.GetValues(typeof(T)).Cast<object>().Select(o => o.ToString()).ToArray();
if (string.IsNullOrEmpty(_searchEnumText) && states.Length > 0) _searchEnumText = state.ToString(CultureInfo.InvariantCulture);
var text = EditorGUILayout.TextField(label, _searchEnumText);
if (text != _searchEnumText || _isSearchEnumLabelInSearch)
{
_searchEnumText = text;
var mach = states.Select((v, i) => new { value = v, index = i }).Where(a => a.value.ToLower().StartsWith(text.ToLower())).ToList();
var targetState = state;
if (mach.Any())
{
// many of results
targetState = (T)Enum.GetValues(typeof(T)).GetValue(mach[0].index);
EditorGUILayout.LabelField("Select closested: " + targetState);
Repaint();
var selected = GUILayout.SelectionGrid(-1, mach.Select(v => v.value).ToArray(), 4);
if (selected != -1)
{
targetState = (T)Enum.GetValues(typeof(T)).GetValue(mach[selected].index);
_searchEnumText = targetState.ToString(CultureInfo.InvariantCulture);
_isSearchEnumLabelInSearch = false;
GUI.FocusControl("FocusAway");
Repaint();
}
}
state = targetState;
_isSearchEnumLabelInSearch = !string.Equals(_searchEnumText, targetState.ToString(CultureInfo.InvariantCulture), StringComparison.CurrentCultureIgnoreCase);
}
return state;
}
}
Tap button to select target enum
Here is my solution, you can replace 'EnumNBEvent' as you like.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using Newborn.Pb.Event;
using System;
using System.Reflection;
using Google.Protobuf.Reflection;
using System.Text.RegularExpressions;
[CustomPropertyDrawer(typeof(EnumNBEvent), false)]
public class FSMEventDrawer : PropertyDrawer {
struct EnumStringValuePair : IComparable<EnumStringValuePair>
{
public string strValue;
public int intValue;
public int CompareTo(EnumStringValuePair another)
{
if (intValue < another.intValue)
return -1;
else if (intValue > another.intValue)
return 1;
return 0;
}
}
Dictionary<int, string> filters = new Dictionary<int, string>();
//string filter = string.Empty;
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
int y = (int)position.position.y;
if (!filters.ContainsKey(y))
filters[y] = string.Empty;
EditorGUI.BeginProperty(position, label, property);
EditorGUI.LabelField(new Rect(position.x, position.y, 100, 20), property.name);
filters[y] = EditorGUI.TextField(new Rect(position.x + 100, position.y, 60, 15), filters[y]);
List<EnumStringValuePair> enumList = GetEnumList(filters[y]);
List<string> enumStrList = new List<string>(enumList.Count);
for (int i = 0; i < enumList.Count; ++i)
{
enumStrList.Add(enumList[i].strValue);
}
int selectedIndex = 0;
for (int i = 0; i < enumList.Count; ++i)
{
if (enumList[i].intValue == property.enumValueIndex)
{
selectedIndex = i;
break;
}
}
selectedIndex = EditorGUI.Popup(new Rect(position.x + 170, position.y, 200, 20), selectedIndex, enumStrList.ToArray());
if (enumList.Count > selectedIndex)
{
property.enumValueIndex = enumList[selectedIndex].intValue;
}
EditorGUI.EndProperty();
}
private List<EnumStringValuePair> GetEnumList(string filter)
{
List<EnumStringValuePair> allList = new List<EnumStringValuePair>();
Array enumValues = Enum.GetValues(typeof(EnumNBEvent));
for (int i = 0; i < enumValues.Length; ++i)
{
EnumStringValuePair pair = new EnumStringValuePair();
pair.strValue = enumValues.GetValue(i).ToString();
pair.intValue = (int)enumValues.GetValue(i);
allList.Add(pair);
}
List<EnumStringValuePair> ret = new List<EnumStringValuePair>();
Regex regex = new Regex(filter.ToLower());
for (int i = 0; i < allList.Count; ++i)
{
if (regex.IsMatch(allList[i].strValue.ToLower()))
{
ret.Add(allList[i]);
}
}
return ret;
}
}

Merge textures at Runtime

Is there any way to "bake" one texture to another, except for using SetPixels()?
Now i'm trying to use something like that, but it too slow:
public static Texture2D CombineTextures(Texture2D aBaseTexture, Texture2D aToCopyTexture, int x, int y)
{
int aWidth = aBaseTexture.width;
int aHeight = aBaseTexture.height;
int bWidth = aToCopyTexture.width;
int bHeight = aToCopyTexture.height;
Texture2D aReturnTexture = new Texture2D(aWidth, aHeight, TextureFormat.RGBA32, false);
Color[] aBaseTexturePixels = aBaseTexture.GetPixels();
Color[] aCopyTexturePixels = aToCopyTexture.GetPixels();
int aPixelLength = aBaseTexturePixels.Length;
for(int y1 = y, y2 = 0; y1 < aHeight && y2 < bHeight ; y1++, y2++)
{
for(int x1 = x, x2 = 0 ; x1 < aWidth && x2 < bWidth; x1++, x2++)
{
aBaseTexturePixels[x1 + y1*aWidth] = Color.Lerp(aBaseTexturePixels[x1 + y1*aWidth], aCopyTexturePixels[x2 + y2*bWidth], aCopyTexturePixels[x2 + y2*bWidth].a);
}
}
aReturnTexture.SetPixels(aBaseTexturePixels);
aReturnTexture.Apply(false);
return aReturnTexture;
}
The problem is, that i need to display a lot of sprites on 2d surface (blood, enemy corpses, etc.), and just instantiating every sprite will greatly reduce fps.
If you are concerned about fps drop when instantiating prefabs you should definitely build a Object pooling system. So you will have a system that:
Instantiating all objects in the pool and keep it far away from the main camera
Once you need the object you will "borrow" it from the pool
Once object is not needed anymore you will return it back to the object pool (for example when sprite is out the camera view
Baking it all to one texture isn't the best practice. You will need huge amounts of RAM for this. Consider steps above, its very common practice
Good example here:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
public class BackgroundPool : MonoBehaviour
{
public static BackgroundPool instance;
public List<BackgroundSection> sectionsLibrary = new List<BackgroundSection>();
public int poolSize = 4;
public List<BackgroundSection> pool = new List<BackgroundSection>();
void Awake()
{
instance = this;
DateTime startGenTime = DateTime.Now;
//generateSectionsPool
for (int i=0; i<sectionsLibrary.Count; i++)
{
for (int j=0; j<poolSize; j++)
{
if (j == 0)
{
sectionsLibrary[i].positionInPool = sectionsLibrary[i].transform.position;
pool.Add(sectionsLibrary[i]);
}
else
{
BackgroundSection section = (BackgroundSection)Instantiate(sectionsLibrary[i]);
section.transform.parent = this.transform;
section.transform.position = new Vector3((-(ExtensionMethods.GetBounds(sectionsLibrary[i].gameObject).extents.x * 2) * j) + sectionsLibrary[i].transform.position.x,
sectionsLibrary[i].transform.position.y);
section.transform.localEulerAngles = Vector3.zero;
section.gameObject.name = sectionsLibrary[i].gameObject.name + ":" + j.ToString();
section.positionInPool = section.transform.position;
pool.Add(section);
}
}
}
Debug.Log("Background Pool generated in: " + (DateTime.Now - startGenTime).TotalSeconds.ToString() + " s");
}
public BackgroundSection GetPiece(Scenery scenery, SceneryLayer _layer)
{
List<BackgroundSection> allScenery = new List<BackgroundSection>();
foreach (BackgroundSection section in pool) { if (section.scenery == scenery) allScenery.Add(section); }
List<BackgroundSection> matchingPieces = new List<BackgroundSection>();
foreach (BackgroundSection section in allScenery) { if (section.sceneryLayer == _layer) matchingPieces.Add(section); }
if (matchingPieces.Count > 0)
{
BackgroundSection pickedSection = matchingPieces[UnityEngine.Random.Range(0,matchingPieces.Count-1)];
pool.Remove(pickedSection);
return pickedSection;
}
else
{
Debug.LogError("Cann't get background piece matching criteria, scenery: " + scenery + ", layer" + _layer);
return null;
}
}
public void ReturnPiece(BackgroundSection section)
{
pool.Add(section);
section.transform.parent = this.transform;
section.transform.position = section.positionInPool;
}
}

iTextSharp different results on Windows 7 vs Windows 8.1

When I run the following code on Windows 7 and 8.1 I get different results. On Windows 7 if I re-run the code on the newly created file it throws exceptions while the Windows 8.1 code works fine.
Any Clues?????
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string a = #"C:\temp\Materials\20130911134612877_3.pdf";
string b = #"C:\temp\Materials\20130911134612877_4.pdf";
Program p = new Program();
p.Open(a);
p.SaveSource(b);
}
public List<Bitmap> Bitmaps { get; private set; }
private string sourceFileName { get; set; }
private string destPath { get; set; }
public List<int> Source { get; set; }
public List<int> Destination { get; set; }
public void Open(string fileName)
{
this.sourceFileName = fileName;
this.destPath = Path.Combine(Path.GetDirectoryName(fileName), "Processed");
if (!Directory.Exists(destPath))
{
Directory.CreateDirectory(this.destPath);
}
string original = Path.Combine(Path.GetDirectoryName(fileName), "Orginal", Path.GetFileName(fileName));
if (!File.Exists(original))
{
string originalPath = Path.GetDirectoryName(original);
if (!Directory.Exists(originalPath))
{
Directory.CreateDirectory(originalPath);
}
File.Copy(fileName, original);
}
if (this.Bitmaps != null)
{
for (int _i = 0; _i < this.Bitmaps.Count; _i++)
{
this.Bitmaps[_i].Dispose();
}
}
PDFDocument doc = GetDocument(fileName);
this.Bitmaps = new List<Bitmap>();
this.Source = new List<int>();
this.Destination = new List<int>();
for (int i = 0; i < doc.Count; i++)
{
this.Source.Add(i);
this.Bitmaps.Add(doc.GetImage(i));
}
doc.Close();
}
public void SaveSource(string file)
{
if (this.Source.Count != 0)
{
PDFDocument pdf = new PDFDocument();
pdf.FileName = file;
foreach (int i in this.Source)
{
pdf.Add(this.Bitmaps[i]);
}
pdf.Close();
}
else
{
if (File.Exists(this.sourceFileName))
{
File.Delete(this.sourceFileName);
}
}
}
private PDFDocument GetDocument(string file)
{
PDFDocument doc = null;
doc = new PDFDocument();
doc.Open(file);
return doc;
}
public static void MergePdfFiles(IEnumerable<string> files, string output)
{
iTextSharp.text.Document doc;
iTextSharp.text.pdf.PdfCopy pdfCpy;
doc = new iTextSharp.text.Document();
pdfCpy = new iTextSharp.text.pdf.PdfCopy(doc, new System.IO.FileStream(output, System.IO.FileMode.Create));
doc.Open();
foreach (string file in files)
{
// initialize a reader
iTextSharp.text.pdf.PdfReader reader = new iTextSharp.text.pdf.PdfReader(file);
int pageCount = reader.NumberOfPages;
// set page size for the documents
doc.SetPageSize(reader.GetPageSizeWithRotation(1));
for (int pageNum = 1; pageNum <= pageCount; pageNum++)
{
iTextSharp.text.pdf.PdfImportedPage page = pdfCpy.GetImportedPage(reader, pageNum);
pdfCpy.AddPage(page);
}
reader.Close();
}
doc.Close();
}
}
public class MyImageRenderListener : IRenderListener
{
public void RenderText(TextRenderInfo renderInfo) { }
public void BeginTextBlock() { }
public void EndTextBlock() { }
public Bitmap Image = null;
public void RenderImage(ImageRenderInfo renderInfo)
{
try
{
PdfImageObject image = renderInfo.GetImage();
if (image == null) return;
using (MemoryStream ms = new MemoryStream(image.GetImageAsBytes()))
{
Bitmap i = (System.Drawing.Bitmap)Bitmap.FromStream(ms);
Image = (System.Drawing.Bitmap)i.Clone();
i.Dispose();
// int dpi = i.Height / 11;
int yDPI = Image.Height / 11;
int xDPI = (Image.Width * 2) / 17;
xDPI = Math.Abs(xDPI - 300) < 10 ? 300 : xDPI;
yDPI = Math.Abs(yDPI - 300) < 10 ? 300 : yDPI;
xDPI = Math.Abs(xDPI - 600) < 10 ? 600 : xDPI;
yDPI = Math.Abs(yDPI - 600) < 10 ? 600 : yDPI;
if (xDPI == yDPI)
{
Image.SetResolution(xDPI, yDPI);
}
else
{
}
}
}
catch (IOException)
{
/*
* pass-through; image type not supported by iText[Sharp]; e.g. jbig2
*/
}
}
}
public class PDFDocument
{
public string FileName { get; set; }
~PDFDocument()
{
this.Close();
}
public static void AddImage(Stream inputPdfStream, Stream outputPdfStream, Stream inputImageStream)
{
PdfReader reader = new PdfReader(inputPdfStream);
iTextSharp.text.Rectangle size = reader.GetPageSize(1);
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(inputImageStream);
image.SetAbsolutePosition(size.Width - 98, size.Height - 98);
PdfStamper stamper = new PdfStamper(reader, outputPdfStream);
int page = 1;
// for (int page = 1; page <= reader.NumberOfPages; page++)
{
PdfContentByte pdfContentByte = stamper.GetOverContent(page);
pdfContentByte.AddImage(image);
}
stamper.Close();
}
public void Open(string fileName)
{
this.reader = new PdfReader(fileName);
this.parser = new PdfReaderContentParser(reader);
this.listener = new MyImageRenderListener();
}
public int Count { get { return reader.NumberOfPages; } }
public Bitmap GetImage(int index)
{
parser.ProcessContent(index + 1, listener);
return listener.Image;
}
public Bitmap GetImage2(int index)
{
PdfDictionary page = reader.GetPageN(index + 1);
return GetImagesFromPdfDict(page);
}
private PdfReaderContentParser parser = null;
private MyImageRenderListener listener = null;
private PdfReader reader = null;
private Bitmap GetImagesFromPdfDict(PdfDictionary dict)
{
PdfDictionary res = (PdfDictionary)(PdfReader.GetPdfObject(dict.Get(PdfName.RESOURCES)));
PdfDictionary xobj = (PdfDictionary)(PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT)));
Bitmap bm = null;
if (xobj != null)
{
foreach (PdfName name in xobj.Keys)
{
PdfObject obj = xobj.Get(name);
if (obj.IsIndirect())
{
PdfDictionary tg = (PdfDictionary)(PdfReader.GetPdfObject(obj));
PdfName subtype = (PdfName)(PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE)));
if (PdfName.IMAGE.Equals(subtype))
{
int xrefIdx = ((PRIndirectReference)obj).Number;
PdfObject pdfObj = this.reader.GetPdfObject(xrefIdx);
PRStream str = (PRStream)(pdfObj);
iTextSharp.text.pdf.parser.PdfImageObject pdfImage = new iTextSharp.text.pdf.parser.PdfImageObject(str);
bm = (System.Drawing.Bitmap)pdfImage.GetDrawingImage();
bm.SetResolution(300.0f, 300.0f);
break;
}
else if (PdfName.FORM.Equals(subtype) || PdfName.GROUP.Equals(subtype))
{
GetImagesFromPdfDict(tg);
}
}
}
}
return bm;
}
public void Split(string fileName)
{
throw new NotImplementedException();
}
public void Save(System.Drawing.Bitmap bm, string filename)
{
Save(bm, filename, RotateFlipType.RotateNoneFlipNone);
}
const float PAGE_LEFT_MARGIN = 0;
const float PAGE_RIGHT_MARGIN = 0;
const float PAGE_TOP_MARGIN = 0;
const float PAGE_BOTTOM_MARGIN = 0;
public void Save(System.Drawing.Bitmap bm, string filename, System.Drawing.RotateFlipType rotate)
{
Bitmap image = bm;
if (rotate != RotateFlipType.RotateNoneFlipNone)
{
image.RotateFlip(rotate);
}
using (FileStream stream = new FileStream(filename, FileMode.Create))
{
using (iTextSharp.text.Document pdfDocument = new iTextSharp.text.Document(PageSize.LETTER, PAGE_LEFT_MARGIN, PAGE_RIGHT_MARGIN, PAGE_TOP_MARGIN, PAGE_BOTTOM_MARGIN))
{
iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(pdfDocument, stream);
pdfDocument.Open();
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff);
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(ms);
img.ScaleToFit(PageSize.LETTER.Width - (PAGE_LEFT_MARGIN + PAGE_RIGHT_MARGIN), PageSize.LETTER.Height - (PAGE_TOP_MARGIN + PAGE_BOTTOM_MARGIN));
pdfDocument.Add(img);
pdfDocument.Close();
writer.Close();
}
}
}
public void Add(System.Drawing.Bitmap bm)
{
this.Add(bm, RotateFlipType.RotateNoneFlipNone);
}
FileStream stream;
iTextSharp.text.Document pdfDocument;
iTextSharp.text.pdf.PdfWriter writer;
public void Add(System.Drawing.Bitmap bm, System.Drawing.RotateFlipType rotate)
{
if (this.stream == null)
{
this.stream = new FileStream(this.FileName, FileMode.Create);
this.pdfDocument = new iTextSharp.text.Document(PageSize.LETTER, PAGE_LEFT_MARGIN, PAGE_RIGHT_MARGIN, PAGE_TOP_MARGIN, PAGE_BOTTOM_MARGIN);
this.writer = iTextSharp.text.pdf.PdfWriter.GetInstance(pdfDocument, stream);
this.pdfDocument.Open();
}
Bitmap image = bm;
if (rotate != RotateFlipType.RotateNoneFlipNone)
{
image.RotateFlip(rotate);
}
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, System.Drawing.Imaging.ImageFormat.Tiff);
ms.Seek(0, SeekOrigin.Begin);
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(ms);
img.ScaleToFit(PageSize.LETTER.Width - (PAGE_LEFT_MARGIN + PAGE_RIGHT_MARGIN), PageSize.LETTER.Height - (PAGE_TOP_MARGIN + PAGE_BOTTOM_MARGIN));
pdfDocument.Add(img);
}
}
public void Close()
{
if (this.pdfDocument != null)
{
this.pdfDocument.Close();
this.pdfDocument.Dispose();
this.writer.Close();
this.writer.Dispose();
this.stream.Close();
this.stream.Dispose();
this.pdfDocument = null;
this.writer = null;
this.pdfDocument = null;
}
if (this.reader != null)
{
this.reader.Close();
}
}
public void Tag(string oldFile, Stream fs, string text)
{
float x;
float y;
// open the reader
PdfReader reader = new PdfReader(oldFile);
iTextSharp.text.Rectangle size = reader.GetPageSizeWithRotation(1);
float height = 60;
float width = 150;
x = size.Width - 40 - width;
y = size.Height - height;
Document document = new Document(size);
// open the writer
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
// the pdf content
PdfContentByte cb = writer.DirectContent;
// create the new page and add it to the pdf
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
cb.Rectangle(x, y, width, height);
cb.SetColorFill(BaseColor.WHITE);
cb.Fill();
// close the streams and voilá the file should be changed :)
// write the text in the pdf content
cb.BeginText();
// select the font properties
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SetColorFill(BaseColor.BLACK);
cb.SetFontAndSize(bf, 20);
// put the alignment and coordinates here
cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT, text, x + 5, y + 10, 0);
cb.EndText();
writer.Flush();
document.Close();
reader.Close();
// fs.Seek(0, SeekOrigin.Begin);
}
}
}