diff --git a/Hjg.Pngcs.Portable/Hjg.Pngcs.Portable.csproj b/Hjg.Pngcs.Portable/Hjg.Pngcs.Portable.csproj
new file mode 100644
index 0000000..766a8a3
--- /dev/null
+++ b/Hjg.Pngcs.Portable/Hjg.Pngcs.Portable.csproj
@@ -0,0 +1,265 @@
+
+
+
+
+ 10.0
+ Debug
+ AnyCPU
+ {CCF5E155-ECF0-4DBC-BC7C-69FE1AAAF235}
+ Library
+ Properties
+ Ar.Com.Hjg.Pngcs
+ Pngcs.Portable
+ en-US
+ 512
+ {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Profile111
+ v4.5
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;NET45;PORTABLE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE;NET45;PORTABLE
+ prompt
+ 4
+
+
+
+
+
+
+ BufferedStreamReader.cs
+
+
+ ChunkReaderMode.cs
+
+
+ Chunks\ChunkCopyBehaviour.cs
+
+
+ Chunks\ChunkHelper.cs
+
+
+ Chunks\ChunkLoadBehaviour.cs
+
+
+ Chunks\ChunkPredicate.cs
+
+
+ Chunks\ChunkPredicateEquiv.cs
+
+
+ Chunks\ChunkPredicateId.cs
+
+
+ Chunks\ChunkPredicateId2.cs
+
+
+ Chunks\ChunkRaw.cs
+
+
+ Chunks\ChunksList.cs
+
+
+ Chunks\ChunksListForWrite.cs
+
+
+ Chunks\PngChunk.cs
+
+
+ Chunks\PngChunkBKGD.cs
+
+
+ Chunks\PngChunkCHRM.cs
+
+
+ Chunks\PngChunkGAMA.cs
+
+
+ Chunks\PngChunkHIST.cs
+
+
+ Chunks\PngChunkICCP.cs
+
+
+ Chunks\PngChunkIDAT.cs
+
+
+ Chunks\PngChunkIEND.cs
+
+
+ Chunks\PngChunkIHDR.cs
+
+
+ Chunks\PngChunkITXT.cs
+
+
+ Chunks\PngChunkMultiple.cs
+
+
+ Chunks\PngChunkOFFS.cs
+
+
+ Chunks\PngChunkPHYS.cs
+
+
+ Chunks\PngChunkPLTE.cs
+
+
+ Chunks\PngChunkSBIT.cs
+
+
+ Chunks\PngChunkSingle.cs
+
+
+ Chunks\PngChunkSkipped.cs
+
+
+ Chunks\PngChunkSPLT.cs
+
+
+ Chunks\PngChunkSRGB.cs
+
+
+ Chunks\PngChunkSTER.cs
+
+
+ Chunks\PngChunkTEXT.cs
+
+
+ Chunks\PngChunkTextVar.cs
+
+
+ Chunks\PngChunkTIME.cs
+
+
+ Chunks\PngChunkTRNS.cs
+
+
+ Chunks\PngChunkUNKNOWN.cs
+
+
+ Chunks\PngChunkZTXT.cs
+
+
+ Chunks\PngMetadata.cs
+
+
+ FilterType.cs
+
+
+ FilterWriteStrategy.cs
+
+
+ IBytesConsumer.cs
+
+
+ ImageInfo.cs
+
+
+ ImageLine.cs
+
+
+ ImageLineHelper.cs
+
+
+ ImageLines.cs
+
+
+ PngCsUtils.cs
+
+
+ PngDeinterlacer.cs
+
+
+ PngHelperInternal.cs
+
+
+ PngIDatChunkInputStream.cs
+
+
+ PngIDatChunkOutputStream.cs
+
+
+ PngjBadCrcException.cs
+
+
+ PngjException.cs
+
+
+ PngjExceptionInternal.cs
+
+
+ PngjInputException.cs
+
+
+ PngjOutputException.cs
+
+
+ PngjUnsupportedException.cs
+
+
+ PngReader.cs
+
+
+ PngWriter.cs
+
+
+ ProgressiveOutputStream.cs
+
+
+ Properties\AssemblyInfo.cs
+
+
+ Zlib\Adler32.cs
+
+
+ Zlib\AZlibInputStream.cs
+
+
+ Zlib\AZlibOutputStream.cs
+
+
+ Zlib\CRC32.cs
+
+
+ Zlib\DeflateCompressLevel.cs
+
+
+ Zlib\EDeflateCompressStrategy.cs
+
+
+ Zlib\ZlibInputStreamIs.cs
+
+
+ Zlib\ZlibInputStreamMs.cs
+
+
+ Zlib\ZlibOutputStreamIs.cs
+
+
+ Zlib\ZlibOutputStreamMs.cs
+
+
+ Zlib\ZlibStreamFactory.cs
+
+
+
+
+
\ No newline at end of file
diff --git a/Hjg.Pngcs/BufferedStreamReader.cs b/Hjg.Pngcs/BufferedStreamReader.cs
index 92726a6..7628648 100644
--- a/Hjg.Pngcs/BufferedStreamReader.cs
+++ b/Hjg.Pngcs/BufferedStreamReader.cs
@@ -15,7 +15,7 @@ class BufferedStreamFeeder
private bool eof = false;
private bool closeStream = true;
private bool failIfNoFeed = false;
- private static const int DEFAULTSIZE = 8192;
+ private const int DEFAULTSIZE = 8192;
public BufferedStreamFeeder(Stream ist) : this(ist,DEFAULTSIZE) {
}
@@ -126,7 +126,7 @@ public void close()
try
{
if (_stream != null && closeStream)
- _stream.Close();
+ _stream.Dispose();
}
catch (Exception e)
{
diff --git a/Hjg.Pngcs/Chunks/ChunkHelper.cs b/Hjg.Pngcs/Chunks/ChunkHelper.cs
index 4971bfe..7b5bb17 100644
--- a/Hjg.Pngcs/Chunks/ChunkHelper.cs
+++ b/Hjg.Pngcs/Chunks/ChunkHelper.cs
@@ -53,7 +53,7 @@ public static byte[] ToBytes(String x) {
///
///
public static String ToString(byte[] x) {
- return Hjg.Pngcs.PngHelperInternal.charsetLatin1.GetString(x);
+ return Hjg.Pngcs.PngHelperInternal.charsetLatin1.GetString(x, 0, x.Length);
}
///
/// Converts to String using Latin1 (ISO-8859-1)
@@ -81,7 +81,7 @@ public static byte[] ToBytesUTF8(String x) {
///
///
public static String ToStringUTF8(byte[] x) {
- return Hjg.Pngcs.PngHelperInternal.charsetUtf8.GetString(x);
+ return Hjg.Pngcs.PngHelperInternal.charsetUtf8.GetString(x, 0, x.Length);
}
///
/// Converts to string using UTF-8
@@ -187,8 +187,8 @@ internal static byte[] compressBytes(byte[] ori, int offset, int len, bool compr
Stream outx = outb;
if (compress) outx = ZlibStreamFactory.createZlibOutputStream(outb);
shovelInToOut(inx, outx);
- inx.Close();
- outx.Close();
+ inx.Dispose();
+ outx.Dispose();
byte[] res = outb.ToArray();
return res;
} catch (Exception e) {
diff --git a/Hjg.Pngcs/Chunks/ChunkRaw.cs b/Hjg.Pngcs/Chunks/ChunkRaw.cs
index bcfe0f0..83c7f77 100644
--- a/Hjg.Pngcs/Chunks/ChunkRaw.cs
+++ b/Hjg.Pngcs/Chunks/ChunkRaw.cs
@@ -101,7 +101,16 @@ internal MemoryStream GetAsByteStream() { // only the data
return new MemoryStream(Data);
}
- private void AllocData() {
+ /**
+ * offset in the full PNG stream, in bytes. only informational, for read chunks (0=NA)
+ */
+ public void setOffset(long offset)
+ {
+ this.offset = offset;
+ }
+
+ private void AllocData()
+ {
if (Data == null || Data.Length < Len)
Data = new byte[Len];
}
diff --git a/Hjg.Pngcs/Chunks/PngChunk.cs b/Hjg.Pngcs/Chunks/PngChunk.cs
index 0dc1d41..a0a76e6 100644
--- a/Hjg.Pngcs/Chunks/PngChunk.cs
+++ b/Hjg.Pngcs/Chunks/PngChunk.cs
@@ -1,13 +1,14 @@
-namespace Hjg.Pngcs.Chunks {
+namespace Hjg.Pngcs.Chunks
+{
using Hjg.Pngcs;
using System;
- using System.Collections;
using System.Collections.Generic;
- using System.ComponentModel;
using System.IO;
- using System.Runtime.CompilerServices;
-
+#if PORTABLE
+ using System.Linq;
+ using System.Reflection;
+#endif
///
/// Represents a instance of a PNG chunk
@@ -165,8 +166,17 @@ internal static PngChunk FactoryFromId(String cid, ImageInfo info) {
if (factoryMap == null) initFactory();
if (isKnown(cid)) {
Type t = factoryMap[cid];
- if (t == null) Console.Error.WriteLine("What?? " + cid);
+ if (t == null) System.Diagnostics.Debug.WriteLine("What?? " + cid);
+#if PORTABLE
+ System.Reflection.ConstructorInfo cons = t.GetTypeInfo().DeclaredConstructors.Single(
+ c =>
+ {
+ var p = c.GetParameters();
+ return p.Length == 1 && p[0].ParameterType == typeof(ImageInfo);
+ });
+#else
System.Reflection.ConstructorInfo cons = t.GetConstructor(new Type[] { typeof(ImageInfo) });
+#endif
object o = cons.Invoke(new object[] { info });
chunk = (PngChunk)o;
}
diff --git a/Hjg.Pngcs/Hjg.Pngcs.csproj b/Hjg.Pngcs/Hjg.Pngcs.csproj
index eff3e36..fc7d5b6 100644
--- a/Hjg.Pngcs/Hjg.Pngcs.csproj
+++ b/Hjg.Pngcs/Hjg.Pngcs.csproj
@@ -64,7 +64,7 @@
- ..\..\..\..\..\..\..\temp\ICSharpCode.SharpZipLib.dll
+ ..\ICSharpCode.SharpZipLib.dll
diff --git a/Hjg.Pngcs/IBytesConsumer.cs b/Hjg.Pngcs/IBytesConsumer.cs
index d53a4a4..ee9b51e 100644
--- a/Hjg.Pngcs/IBytesConsumer.cs
+++ b/Hjg.Pngcs/IBytesConsumer.cs
@@ -6,5 +6,6 @@ namespace Ar.Com.Hjg.Pngcs
{
interface IBytesConsumer
{
+ int consume(byte[] buf, int offset, int len);
}
}
diff --git a/Hjg.Pngcs/ImageInfo.cs b/Hjg.Pngcs/ImageInfo.cs
index 0482edb..3f95029 100644
--- a/Hjg.Pngcs/ImageInfo.cs
+++ b/Hjg.Pngcs/ImageInfo.cs
@@ -16,7 +16,7 @@ namespace Hjg.Pngcs {
/// http://www.w3.org/TR/PNG/#11IHDR
///
public class ImageInfo {
- private const int MAX_COLS_ROWS_VAL = 400000; // very big value, but no so ridiculous as 2^32
+ private const int MAX_COLS_ROWS_VAL = 0X7FEFFFFF; // very big value, but no so ridiculous as 2^32
///
/// Image width, in pixels
diff --git a/Hjg.Pngcs/PngHelperInternal.cs b/Hjg.Pngcs/PngHelperInternal.cs
index 69b6c7e..7d2b938 100644
--- a/Hjg.Pngcs/PngHelperInternal.cs
+++ b/Hjg.Pngcs/PngHelperInternal.cs
@@ -203,7 +203,7 @@ public static int FilterPaethPredictor(int a, int b, int c) {
public static void Logdebug(String msg) {
if (DEBUG)
- System.Console.Out.WriteLine(msg);
+ System.Diagnostics.Debug.WriteLine(msg);
}
@@ -218,7 +218,7 @@ public static long GetCrctestVal(PngReader pngr) {
internal static void Log(string p, Exception e)
{
- Console.Error.WriteLine(p);
+ System.Diagnostics.Debug.WriteLine(p);
}
}
}
diff --git a/Hjg.Pngcs/PngIDatChunkInputStream.cs b/Hjg.Pngcs/PngIDatChunkInputStream.cs
index 53de140..b2046d7 100644
--- a/Hjg.Pngcs/PngIDatChunkInputStream.cs
+++ b/Hjg.Pngcs/PngIDatChunkInputStream.cs
@@ -70,8 +70,12 @@ public PngIDatChunkInputStream(Stream iStream, int lenFirstChunk, long offset_0)
/// does NOT close the associated stream!
///
///
+#if PORTABLE
+ public virtual void Close() {
+#else
public override void Close() {
- base.Close(); // nothing
+#endif
+ base.Dispose(); // nothing
}
private void EndChunkGoForNext() {
diff --git a/Hjg.Pngcs/PngReader.cs b/Hjg.Pngcs/PngReader.cs
index 76666cb..1611dca 100644
--- a/Hjg.Pngcs/PngReader.cs
+++ b/Hjg.Pngcs/PngReader.cs
@@ -225,7 +225,7 @@ private bool FirstChunksNotYetRead() {
private void ReadLastAndClose() {
if (CurrentChunkGroup < ChunksList.CHUNK_GROUP_5_AFTERIDAT) {
try {
- idatIstream.Close();
+ idatIstream.Dispose();
} catch (Exception ) { }
ReadLastChunks();
}
@@ -235,13 +235,13 @@ private void ReadLastAndClose() {
private void Close() {
if (CurrentChunkGroup < ChunksList.CHUNK_GROUP_6_END) { // this could only happen if forced close
try {
- idatIstream.Close();
+ idatIstream.Dispose();
} catch (Exception ) {
}
CurrentChunkGroup = ChunksList.CHUNK_GROUP_6_END;
}
if (ShouldCloseStream)
- inputStream.Close();
+ inputStream.Dispose();
}
@@ -451,7 +451,7 @@ private PngChunk ReadChunk(byte[] chunkid, int clen, bool skipforced) {
///
///
internal void logWarn(String warn) {
- Console.Error.WriteLine(warn);
+ System.Diagnostics.Debug.WriteLine(warn);
}
///
diff --git a/Hjg.Pngcs/PngWriter.cs b/Hjg.Pngcs/PngWriter.cs
index 584e8d4..6d187f4 100644
--- a/Hjg.Pngcs/PngWriter.cs
+++ b/Hjg.Pngcs/PngWriter.cs
@@ -474,12 +474,12 @@ public void End() {
if (rowNum != ImgInfo.Rows - 1)
throw new PngjOutputException("all rows have not been written");
try {
- datStreamDeflated.Close();
- datStream.Close();
+ datStreamDeflated.Dispose();
+ datStream.Dispose();
WriteLastChunks();
WriteEndChunk();
if (this.ShouldCloseStream)
- outputStream.Close();
+ outputStream.Dispose();
} catch (IOException e) {
throw new PngjOutputException(e);
}
diff --git a/Hjg.Pngcs/Pngcs.xml b/Hjg.Pngcs/Pngcs.xml
index 422c584..7179d43 100644
--- a/Hjg.Pngcs/Pngcs.xml
+++ b/Hjg.Pngcs/Pngcs.xml
@@ -4,6 +4,20 @@
Pngcs
+
+
+ Stream from which bytes are read
+
+
+
+
+ Feeds bytes to the consumer
+ Returns bytes actually consumed
+ This should return 0 only if the stream is EOF or the consumer is done
+
+
+
+
Static utility methods for CHunks
@@ -277,7 +291,7 @@
See http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
-
+
The length counts only the data field, not itself, the chunk type code, or the CRC. Zero is a valid length.
Although encoders and decoders should treat the length as unsigned, its value must not exceed 2^31-1 bytes.
@@ -293,13 +307,10 @@
Raw data, crc not included
-
+
Creates an empty raw chunk
-
-
- pre allocate the data buffer?
@@ -313,6 +324,9 @@
+
+ offset in the full PNG stream, in bytes. only informational, for read chunks (0=NA)
+
Just id and length
@@ -497,144 +511,6 @@
A Chunk type that allows duplicate in an image
-
-
- Represents a instance of a PNG chunk
-
-
- Concrete classes should extend PngChunkSingle or PngChunkMultiple
-
- Note that some methods/fields are type-specific (GetOrderingConstraint(), AllowsMultiple())
- some are 'almost' type-specific (Id,Crit,Pub,Safe; the exception is PngUKNOWN),
- and some are instance-specific
-
- Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
-
-
-
-
- 4 letters. The Id almost determines the concrete type (except for PngUKNOWN)
-
-
-
-
- Standard basic properties, implicit in the Id
-
-
-
-
- Standard basic properties, implicit in the Id
-
-
-
-
- Standard basic properties, implicit in the Id
-
-
-
-
- Image basic info, mostly for some checks
-
-
-
-
- Constructs an empty chunk
-
-
-
-
-
-
- Registers a Chunk ID in the factory, to instantiate a given type
-
-
- This can be called by client code to register additional chunk types
-
-
- should extend PngChunkSingle or PngChunkMultiple
-
-
-
- Creates one new blank chunk of the corresponding type, according to factoryMap (PngChunkUNKNOWN if not known)
-
- Chunk Id
-
-
-
-
-
- Basic info: Id, length, Type name
-
-
-
-
-
- Serialization. Creates a Raw chunk, ready for write, from this chunk content
-
-
-
-
- Deserialization. Given a Raw chunk, just rad, fills this chunk content
-
-
-
-
- Override to make a copy (normally deep) from other chunk
-
-
-
-
-
- This is implemented in PngChunkMultiple/PngChunSingle
-
- Allows more than one chunk of this type in a image
-
-
-
- Get ordering constrain
-
-
-
-
-
- For writing. Queued chunks with high priority will be written as soon as possible
-
-
-
-
- Chunk group where it was read or writen
-
-
-
-
- Restrictions for chunk ordering, for ancillary chunks
-
-
-
-
- No constraint, the chunk can go anywhere
-
-
-
-
- Before PLTE (palette) - and hence, also before IDAT
-
-
-
-
- After PLTE (palette), but before IDAT
-
-
-
-
- Before IDAT (before or after PLTE)
-
-
-
-
- Does not apply
-
-
A Chunk type that does not allow duplicate in an image
@@ -837,101 +713,467 @@
sRGB chunk: http://www.w3.org/TR/PNG/#11sRGB
-
+
- Wraps a set of rows from a image, read in a single operation, stored in a int[][] or byte[][] matrix
+ Represents a instance of a PNG chunk
+
+
+ Concrete classes should extend PngChunkSingle or PngChunkMultiple
- They can be a subset of the total rows, but in this case they are equispaced.
+ Note that some methods/fields are type-specific (GetOrderingConstraint(), AllowsMultiple())
+ some are 'almost' type-specific (Id,Crit,Pub,Safe; the exception is PngUKNOWN),
+ and some are instance-specific
- See also ImageLine
-
+ Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html
+
-
+
- Translates from image row number to matrix row.
- If you are not sure if this image row in included, use better ImageRowToMatrixRowStrict
-
+ 4 letters. The Id almost determines the concrete type (except for PngUKNOWN)
- Row number in the original image (from 0)
- Row number in the wrapped matrix. Undefined result if invalid
-
+
- translates from image row number to matrix row
+ Standard basic properties, implicit in the Id
- Row number in the original image (from 0)
- Row number in the wrapped matrix. Returns -1 if invalid
-
+
- Translates from matrix row number to real image row number
+ Standard basic properties, implicit in the Id
-
-
-
+
- Constructs and returns an ImageLine object backed by a matrix row.
- This is quite efficient, no deep copy.
+ Standard basic properties, implicit in the Id
- Row number inside the matrix
-
-
-
- this refers to the row currRowSubimg
-
-
- Is current row the last row for the lass pass??
-
-
- current row number inside the "sub image"
-
- current row number inside the "real image"
+
+
+ Image basic info, mostly for some checks
+
-
- current pass number (1-7)
+
+
+ For writing. Queued chunks with high priority will be written as soon as possible
+
-
- How many rows has the current pass?
-
+
+
+ Chunk group where it was read or writen
+
-
- How many columns (pixels) are there in the current row
+
+
+ Restrictions for chunk ordering, for ancillary chunks
+
-
+
- Exception for internal problems
+ No constraint, the chunk can go anywhere
-
+
- Manages the writer strategy for selecting the internal png predictor filter
+ Before PLTE (palette) - and hence, also before IDAT
-
-
- A few utility static methods to read and write files
-
-
+
+
+ After PLTE (palette), but before IDAT
+
-
+
- Given a filename and a ImageInfo, produces a PngWriter object, ready for writing.
- Path of file
- ImageInfo object
- Flag: if false and file exists, a PngjOutputException is thrown
- A PngWriter object, ready for writing
+ Before IDAT (before or after PLTE)
+
-
+
- Given a filename, produces a PngReader object, ready for reading.
+ Does not apply
- Path of file
- PngReader, ready for reading
-
-
+
+
+ Constructs an empty chunk
+
+
+
+
+
+
+ Registers a Chunk ID in the factory, to instantiate a given type
+
+
+ This can be called by client code to register additional chunk types
+
+
+ should extend PngChunkSingle or PngChunkMultiple
+
+
+
+ Creates one new blank chunk of the corresponding type, according to factoryMap (PngChunkUNKNOWN if not known)
+
+ Chunk Id
+
+
+
+
+
+ Basic info: Id, length, Type name
+
+
+
+
+
+ Serialization. Creates a Raw chunk, ready for write, from this chunk content
+
+
+
+
+ Deserialization. Given a Raw chunk, just rad, fills this chunk content
+
+
+
+
+ Override to make a copy (normally deep) from other chunk
+
+
+
+
+
+ This is implemented in PngChunkMultiple/PngChunSingle
+
+ Allows more than one chunk of this type in a image
+
+
+
+ Get ordering constrain
+
+
+
+
+
+ bKGD chunk, see http://www.w3.org/TR/PNG/#11bKGD
+
+
+
+
+ Set gray value (0-255 if bitdept=8)
+
+
+
+
+
+ Gets gray value
+
+ gray value (0-255 if bitdept=8)
+
+
+
+ Set pallette index - only for indexed
+
+
+
+
+
+ Get pallette index - only for indexed
+
+
+
+
+
+ Sets rgb value, only for rgb images
+
+
+
+
+
+
+
+ Gets rgb value, only for rgb images
+
+ [r , g, b] array
+
+
+
+ gAMA chunk, see http://www.w3.org/TR/PNG/#11gAMA
+
+
+
+
+ iCCP Chunk: see http://www.w3.org/TR/PNG/#11iCCP
+
+
+
+
+ Sets profile name and profile
+
+ profile name
+ profile (latin1 string)
+
+
+
+ Sets profile name and profile
+
+ profile name
+ profile (uncompressed)
+
+
+
+ This uncompresses the string!
+
+
+
+
+
+ IDAT chunk http://www.w3.org/TR/PNG/#11IDAT
+
+ This object is dummy placeholder - We treat this chunk in a very different way than ancillary chnks
+
+
+
+
+ IEND chunk http://www.w3.org/TR/PNG/#11IEND
+
+
+
+
+ IHDR chunk: http://www.w3.org/TR/PNG/#11IHDR
+
+
+
+
+ iTXt chunk: http://www.w3.org/TR/PNG/#11iTXt
+ One of the three text chunks
+
+
+
+
+ Unknown (for our chunk factory) chunk type.
+
+
+
+
+ pHYs chunk: http://www.w3.org/TR/PNG/#11pHYs
+
+
+
+
+ 0: unknown 1:metre
+
+
+
+
+ returns -1 if not in meters, or not equal
+
+
+
+
+
+ returns -1 if the physicial unit is unknown
+
+
+
+
+
+ same in both directions
+
+
+
+
+
+ PLTE Palette chunk: this is the only optional critical chunk
+
+ http://www.w3.org/TR/PNG/#11PLTE
+
+
+
+
+
+
+
+
+
+ Also allocates array
+
+ 1-256
+
+
+
+ as packed RGB8
+
+
+
+
+
+
+ Gets n'th entry, filling 3 positions of given array, at given offset
+
+
+
+
+
+
+
+ shortcut: GetEntryRgb(index, int[] rgb, 0)
+
+
+
+
+
+
+ minimum allowed bit depth, given palette size
+
+ 1-2-4-8
+
+
+
+ tEXt chunk: latin1 uncompressed text
+
+
+
+
+ general class for textual chunks
+
+
+
+
+
+
+
+
+
+
+ tIME chunk: http://www.w3.org/TR/PNG/#11tIME
+
+
+
+ format YYYY/MM/DD HH:mm:SS
+
+
+
+ tRNS chunk: http://www.w3.org/TR/PNG/#11tRNS
+
+
+
+
+ WARNING: non deep copy
+
+
+
+
+
+ utiliy method : to use when only one pallete index is set as totally transparent
+
+
+
+
+
+ WARNING: non deep copy
+
+
+
+
+
+ zTXt chunk: http://www.w3.org/TR/PNG/#11zTXt
+
+
+
+
+
+ Wraps a set of rows from a image, read in a single operation, stored in a int[][] or byte[][] matrix
+
+ They can be a subset of the total rows, but in this case they are equispaced.
+
+ See also ImageLine
+
+
+
+
+ Translates from image row number to matrix row.
+ If you are not sure if this image row in included, use better ImageRowToMatrixRowStrict
+
+
+ Row number in the original image (from 0)
+ Row number in the wrapped matrix. Undefined result if invalid
+
+
+
+ translates from image row number to matrix row
+
+ Row number in the original image (from 0)
+ Row number in the wrapped matrix. Returns -1 if invalid
+
+
+
+ Translates from matrix row number to real image row number
+
+
+
+
+
+
+ Constructs and returns an ImageLine object backed by a matrix row.
+ This is quite efficient, no deep copy.
+
+ Row number inside the matrix
+
+
+
+ this refers to the row currRowSubimg
+
+
+ Is current row the last row for the lass pass??
+
+
+ current row number inside the "sub image"
+
+
+ current row number inside the "real image"
+
+
+ current pass number (1-7)
+
+
+ How many rows has the current pass?
+
+
+
+ How many columns (pixels) are there in the current row
+
+
+
+ Exception for internal problems
+
+
+
+
+ Manages the writer strategy for selecting the internal png predictor filter
+
+
+
+
+ A few utility static methods to read and write files
+
+
+
+
+
+ Given a filename and a ImageInfo, produces a PngWriter object, ready for writing.
+ Path of file
+ ImageInfo object
+ Flag: if false and file exists, a PngjOutputException is thrown
+ A PngWriter object, ready for writing
+
+
+
+ Given a filename, produces a PngReader object, ready for reading.
+
+ Path of file
+ PngReader, ready for reading
+
+
+
Utility functions for C# porting
@@ -1060,31 +1302,6 @@
See scanline field doc, to understand the format.
-
-
- Constructs an ImageLine
-
- Inmutable copy of PNG ImageInfo
- Storage for samples:INT (default) or BYTE
- If true and bitdepth less than 8, samples are unpacked. This has no effect if biddepth 8 or 16
-
-
- size original: samplesPerRow sizeFinal: samplesPerRowPacked (trailing elements are trash!) *
-
-
-
- Makes a deep copy
-
- You should rarely use this
-
-
-
-
- Makes a deep copy
-
- You should rarely use this
-
-
ImageInfo (readonly inmutable)
@@ -1123,281 +1340,78 @@
Hown many elements has the scanline array
- =imgInfo.samplePerRowPacked, if packed, imgInfo.samplePerRow elsewhere
-
-
-
-
- Maximum sample value that this line admits: typically 255; less if bitdepth less than 8, 65535 if 16bits
-
-
-
-
- Determines if samples are stored in integers or in bytes
-
-
-
-
- True: each scanline element is a sample.
- False: each scanline element has severals samples packed in a byte
-
-
-
-
- informational only ; filled by the reader
-
-
-
-
- Bunch of utility static methods to process/analyze an image line.
-
- Not essential at all, some methods are probably to be removed if future releases.
-
- TODO: document this better
-
-
-
-
-
-
- Given an indexed line with a palette, unpacks as a RGB array
-
- ImageLine as returned from PngReader
- Palette chunk
- TRNS chunk (optional)
- Preallocated array, optional
- R G B (one byte per sample)
-
-
- [0,1)
-
-
-
- bKGD chunk, see http://www.w3.org/TR/PNG/#11bKGD
-
-
-
-
- Set gray value (0-255 if bitdept=8)
-
-
-
-
-
- Gets gray value
-
- gray value (0-255 if bitdept=8)
-
-
-
- Set pallette index - only for indexed
-
-
-
-
-
- Get pallette index - only for indexed
-
-
-
-
-
- Sets rgb value, only for rgb images
-
-
-
-
-
-
-
- Gets rgb value, only for rgb images
-
- [r , g, b] array
-
-
-
- gAMA chunk, see http://www.w3.org/TR/PNG/#11gAMA
-
-
-
-
- iCCP Chunk: see http://www.w3.org/TR/PNG/#11iCCP
-
-
-
-
- Sets profile name and profile
-
- profile name
- profile (latin1 string)
-
-
-
- Sets profile name and profile
-
- profile name
- profile (uncompressed)
-
-
-
- This uncompresses the string!
-
-
-
-
-
- IDAT chunk http://www.w3.org/TR/PNG/#11IDAT
-
- This object is dummy placeholder - We treat this chunk in a very different way than ancillary chnks
-
-
-
-
- IEND chunk http://www.w3.org/TR/PNG/#11IEND
-
-
-
-
- IHDR chunk: http://www.w3.org/TR/PNG/#11IHDR
-
-
-
-
- iTXt chunk: http://www.w3.org/TR/PNG/#11iTXt
- One of the three text chunks
-
-
-
-
- general class for textual chunks
-
-
-
-
-
-
-
-
-
-
- Unknown (for our chunk factory) chunk type.
-
-
-
-
- pHYs chunk: http://www.w3.org/TR/PNG/#11pHYs
-
-
-
-
- returns -1 if not in meters, or not equal
-
-
-
-
-
- returns -1 if the physicial unit is unknown
-
-
-
-
-
- same in both directions
-
-
-
-
-
- 0: unknown 1:metre
-
-
-
-
- PLTE Palette chunk: this is the only optional critical chunk
-
- http://www.w3.org/TR/PNG/#11PLTE
-
-
-
-
-
-
-
-
-
- Also allocates array
-
- 1-256
-
-
-
- as packed RGB8
-
-
-
-
-
-
- Gets n'th entry, filling 3 positions of given array, at given offset
-
-
-
-
-
-
-
- shortcut: GetEntryRgb(index, int[] rgb, 0)
+ =imgInfo.samplePerRowPacked, if packed, imgInfo.samplePerRow elsewhere
-
-
-
+
- minimum allowed bit depth, given palette size
+ Maximum sample value that this line admits: typically 255; less if bitdepth less than 8, 65535 if 16bits
- 1-2-4-8
-
+
- tEXt chunk: latin1 uncompressed text
+ Determines if samples are stored in integers or in bytes
-
+
- tIME chunk: http://www.w3.org/TR/PNG/#11tIME
+ True: each scanline element is a sample.
+ False: each scanline element has severals samples packed in a byte
-
- format YYYY/MM/DD HH:mm:SS
-
-
+
- tRNS chunk: http://www.w3.org/TR/PNG/#11tRNS
+ informational only ; filled by the reader
-
+
- WARNING: non deep copy
+ Constructs an ImageLine
-
+ Inmutable copy of PNG ImageInfo
+ Storage for samples:INT (default) or BYTE
+ If true and bitdepth less than 8, samples are unpacked. This has no effect if biddepth 8 or 16
-
+
+ size original: samplesPerRow sizeFinal: samplesPerRowPacked (trailing elements are trash!) *
+
+
- utiliy method : to use when only one pallete index is set as totally transparent
+ Makes a deep copy
-
+ You should rarely use this
+
-
+
- WARNING: non deep copy
+ Makes a deep copy
-
+ You should rarely use this
+
-
-
- zTXt chunk: http://www.w3.org/TR/PNG/#11zTXt
+
+
+ Bunch of utility static methods to process/analyze an image line.
+
+ Not essential at all, some methods are probably to be removed if future releases.
+
+ TODO: document this better
+
+
+
+
+
+ Given an indexed line with a palette, unpacks as a RGB array
+ ImageLine as returned from PngReader
+ Palette chunk
+ TRNS chunk (optional)
+ Preallocated array, optional
+ R G B (one byte per sample)
+
+
+ [0,1)
@@ -1525,20 +1539,6 @@
outputs the stream for IDAT chunk , fragmented at fixed size (32k default).
-
-
-
- stream that outputs to memory and allows to flush fragments every 'size'
- bytes to some other destination
-
-
-
-
-
- if it's time to flush data (or if forced==true) calls abstract method
- flushBuffer() and cleans those bytes from own buffer
-
-
@@ -1590,11 +1590,58 @@
+
+
+ Basic image info, inmutable
+
+
filename, or description - merely informative, can be empty
+
+
+ Strategy for chunk loading. Default: LOAD_CHUNK_ALWAYS
+
+
+
+
+ Should close the underlying Input Stream when ends?
+
+
+
+
+ Maximum amount of bytes from ancillary chunks to load in memory
+
+
+ Default: 5MB. 0: unlimited. If exceeded, chunks will be skipped
+
+
+
+
+ Maximum total bytes to read from stream
+
+
+ Default: 200MB. 0: Unlimited. If exceeded, an exception will be thrown
+
+
+
+
+ Maximum ancillary chunk size
+
+
+ Default: 2MB, 0: unlimited. Chunks exceeding this size will be skipped (nor even CRC checked)
+
+
+
+
+ Ancillary chunks to skip
+
+
+ Default: { "fdAT" }. chunks with these ids will be skipped (nor even CRC checked)
+
+
A high level wrapper of a ChunksList : list of read chunks
@@ -1625,6 +1672,12 @@
raw current row, after unfiltered
+
+
+ number of chunk group (0-6) last read, or currently reading
+
+ see ChunksList.CHUNK_GROUP_NNN
+
last read row number
@@ -1725,74 +1778,47 @@
@see PngReader#setUnpackedMode(boolean)
-
+
- Basic image info, inmutable
+ Writes a PNG image, line by line.
-
+
- Strategy for chunk loading. Default: LOAD_CHUNK_ALWAYS
+ Basic image info, inmutable
-
+
- Should close the underlying Input Stream when ends?
+ filename, or description - merely informative, can be empty
-
-
- Maximum amount of bytes from ancillary chunks to load in memory
-
-
- Default: 5MB. 0: unlimited. If exceeded, chunks will be skipped
-
+
+ Deflate algortithm compression strategy
-
+
- Maximum total bytes to read from stream
+ zip compression level (0 - 9)
- Default: 200MB. 0: Unlimited. If exceeded, an exception will be thrown
+ default:6
+
+ 9 is the maximum compression
-
+
- Maximum ancillary chunk size
+ true: closes stream after ending write
-
- Default: 2MB, 0: unlimited. Chunks exceeding this size will be skipped (nor even CRC checked)
-
-
+
- Ancillary chunks to skip
+ Maximum size of IDAT chunks
- Default: { "fdAT" }. chunks with these ids will be skipped (nor even CRC checked)
+ 0=use default (PngIDatChunkOutputStream 32768)
-
-
- number of chunk group (0-6) last read, or currently reading
-
- see ChunksList.CHUNK_GROUP_NNN
-
-
-
- Writes a PNG image, line by line.
-
-
-
-
- Basic image info, inmutable
-
-
-
-
- filename, or description - merely informative, can be empty
-
-
A high level wrapper of a ChunksList : list of written/queued chunks
@@ -1818,6 +1844,12 @@
raw current row, after filtered
+
+
+ number of chunk group (0-6) last writen, or currently writing
+
+ see ChunksList.CHUNK_GROUP_NNN
+
Constructs a PngWriter from a outputStream, with no filename information
@@ -1917,55 +1949,32 @@
One of the five prediction types or strategy to choose it
-
- Deflate algortithm compression strategy
-
-
-
- zip compression level (0 - 9)
-
-
- default:6
+
+
+ stream that outputs to memory and allows to flush fragments every 'size'
+ bytes to some other destination
+
- 9 is the maximum compression
-
-
-
-
- true: closes stream after ending write
-
-
-
-
- Maximum size of IDAT chunks
-
-
- 0=use default (PngIDatChunkOutputStream 32768)
-
-
-
- number of chunk group (0-6) last writen, or currently writing
-
- see ChunksList.CHUNK_GROUP_NNN
+
+
+ if it's time to flush data (or if forced==true) calls abstract method
+ flushBuffer() and cleans those bytes from own buffer
+
+
-
+
- Zlib output (deflater) based on ShaprZipLib
+ Zip input (deflater) based on Ms DeflateStream (.net 4.5)
-
+
mainly for debugging
-
-
- Zip input (inflater) based on ShaprZipLib
-
-
-
+
mainly for debugging
diff --git a/Hjg.Pngcs/PngjBadCrcException.cs b/Hjg.Pngcs/PngjBadCrcException.cs
index 0de3733..fd70f6c 100644
--- a/Hjg.Pngcs/PngjBadCrcException.cs
+++ b/Hjg.Pngcs/PngjBadCrcException.cs
@@ -10,7 +10,9 @@ namespace Hjg.Pngcs {
///
/// Exception for CRC check
///
+#if !PORTABLE
[Serializable]
+#endif
public class PngjBadCrcException : PngjException {
private const long serialVersionUID = 1L;
diff --git a/Hjg.Pngcs/PngjException.cs b/Hjg.Pngcs/PngjException.cs
index 3304300..a5f0b9d 100644
--- a/Hjg.Pngcs/PngjException.cs
+++ b/Hjg.Pngcs/PngjException.cs
@@ -10,7 +10,9 @@ namespace Hjg.Pngcs {
///
/// Gral exception class for PNGCS library
///
+#if !PORTABLE
[Serializable]
+#endif
public class PngjException : Exception {
private const long serialVersionUID = 1L;
diff --git a/Hjg.Pngcs/PngjExceptionInternal.cs b/Hjg.Pngcs/PngjExceptionInternal.cs
index 91af2c2..2bcd6d4 100644
--- a/Hjg.Pngcs/PngjExceptionInternal.cs
+++ b/Hjg.Pngcs/PngjExceptionInternal.cs
@@ -10,7 +10,9 @@ namespace Hjg.Pngcs {
///
/// Exception for internal problems
///
+#if !PORTABLE
[Serializable]
+#endif
public class PngjExceptionInternal : Exception {
private const long serialVersionUID = 1L;
diff --git a/Hjg.Pngcs/PngjInputException.cs b/Hjg.Pngcs/PngjInputException.cs
index 40a9939..6b8bc05 100644
--- a/Hjg.Pngcs/PngjInputException.cs
+++ b/Hjg.Pngcs/PngjInputException.cs
@@ -10,7 +10,9 @@ namespace Hjg.Pngcs {
///
/// Exception associated with input (reading) operations
///
+#if !PORTABLE
[Serializable]
+#endif
public class PngjInputException : PngjException {
private const long serialVersionUID = 1L;
diff --git a/Hjg.Pngcs/PngjOutputException.cs b/Hjg.Pngcs/PngjOutputException.cs
index fa7d9ae..78b14cb 100644
--- a/Hjg.Pngcs/PngjOutputException.cs
+++ b/Hjg.Pngcs/PngjOutputException.cs
@@ -10,7 +10,9 @@ namespace Hjg.Pngcs {
///
/// Exception associated with input (reading) operations
///
+#if !PORTABLE
[Serializable]
+#endif
public class PngjOutputException : PngjException {
private const long serialVersionUID = 1L;
diff --git a/Hjg.Pngcs/PngjUnsupportedException.cs b/Hjg.Pngcs/PngjUnsupportedException.cs
index e2c9345..824307d 100644
--- a/Hjg.Pngcs/PngjUnsupportedException.cs
+++ b/Hjg.Pngcs/PngjUnsupportedException.cs
@@ -10,7 +10,9 @@ namespace Hjg.Pngcs {
///
/// Exception for unsupported operation or feature
///
+#if !PORTABLE
[Serializable]
+#endif
public class PngjUnsupportedException : Exception {
private const long serialVersionUID = 1L;
diff --git a/Hjg.Pngcs/ProgressiveOutputStream.cs b/Hjg.Pngcs/ProgressiveOutputStream.cs
index 1234bbc..be7e59b 100644
--- a/Hjg.Pngcs/ProgressiveOutputStream.cs
+++ b/Hjg.Pngcs/ProgressiveOutputStream.cs
@@ -1,4 +1,5 @@
-namespace Hjg.Pngcs {
+namespace Hjg.Pngcs
+{
using System;
using System.Collections;
@@ -12,31 +13,42 @@ namespace Hjg.Pngcs {
/// bytes to some other destination
///
///
- abstract internal class ProgressiveOutputStream : MemoryStream {
+ abstract internal class ProgressiveOutputStream : MemoryStream
+ {
private readonly int size;
private long countFlushed = 0;
- public ProgressiveOutputStream(int size_0) {
+ public ProgressiveOutputStream(int size_0)
+ {
this.size = size_0;
if (size < 8) throw new PngjException("bad size for ProgressiveOutputStream: " + size);
}
- public override void Close() {
+#if PORTABLE
+ public virtual void Close()
+ {
+#else
+ public override void Close()
+ {
+#endif
Flush();
- base.Close();
+ base.Dispose();
}
- public override void Flush() {
+ public override void Flush()
+ {
base.Flush();
CheckFlushBuffer(true);
}
- public override void Write(byte[] b, int off, int len) {
+ public override void Write(byte[] b, int off, int len)
+ {
base.Write(b, off, len);
CheckFlushBuffer(false);
}
- public void Write(byte[] b) {
+ public void Write(byte[] b)
+ {
Write(b, 0, b.Length);
CheckFlushBuffer(false);
}
@@ -47,29 +59,52 @@ public void Write(byte[] b) {
/// flushBuffer() and cleans those bytes from own buffer
///
///
- private void CheckFlushBuffer(bool forced) {
+ private void CheckFlushBuffer(bool forced)
+ {
int count = (int)Position;
- byte[] buf = GetBuffer();
- while (forced || count >= size) {
+
+ while (forced || count >= size)
+ {
int nb = size;
if (nb > count)
nb = count;
if (nb == 0)
return;
+
+ byte[] buf = ToArray();
+
FlushBuffer(buf, nb);
countFlushed += nb;
int bytesleft = count - nb;
count = bytesleft;
- Position = count;
+
+ Position = 0;
if (bytesleft > 0)
- System.Array.Copy((Array)(buf), nb, (Array)(buf), 0, bytesleft);
+ base.Write(buf, nb, bytesleft);
}
}
protected abstract void FlushBuffer(byte[] b, int n);
- public long GetCountFlushed() {
+ public long GetCountFlushed()
+ {
return countFlushed;
}
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ this.Close();
+ // Free any other managed objects here.
+ //
+ }
+
+ // Free any unmanaged objects here.
+ //
+
+ // Call base class implementation.
+ base.Dispose(disposing);
+ }
}
}
diff --git a/Hjg.Pngcs/Zlib/ZlibInputStreamMs.cs b/Hjg.Pngcs/Zlib/ZlibInputStreamMs.cs
index 9aa05a5..26fe03d 100644
--- a/Hjg.Pngcs/Zlib/ZlibInputStreamMs.cs
+++ b/Hjg.Pngcs/Zlib/ZlibInputStreamMs.cs
@@ -40,20 +40,21 @@ public override int Read(byte[] array, int offset, int count) {
}
return r;
}
+
+ public virtual void Close() {
- public override void Close() {
if (!initdone) doInit(); // can happen if never called write
if (closed) return;
closed = true;
if (deflateStream != null) {
- deflateStream.Close();
+ deflateStream.Dispose();
}
if (crcread == null) { // eat trailing 4 bytes
crcread = new byte[4];
for (int i = 0; i < 4; i++) crcread[i] = (byte)rawStream.ReadByte();
}
if (!leaveOpen)
- rawStream.Close();
+ rawStream.Dispose();
}
private void initStream() {
@@ -86,6 +87,23 @@ public override void Flush() {
public override String getImplementationId() {
return "Zlib inflater: .Net CLR 4.5";
}
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ this.Close();
+ // Free any other managed objects here.
+ //
+ }
+
+ // Free any unmanaged objects here.
+ //
+
+ // Call base class implementation.
+ base.Dispose(disposing);
+ }
+ }
#endif
diff --git a/Hjg.Pngcs/Zlib/ZlibOutputStreamMs.cs b/Hjg.Pngcs/Zlib/ZlibOutputStreamMs.cs
index ce1fbf4..0c4a6ea 100644
--- a/Hjg.Pngcs/Zlib/ZlibOutputStreamMs.cs
+++ b/Hjg.Pngcs/Zlib/ZlibOutputStreamMs.cs
@@ -32,15 +32,16 @@ public override void Write(byte[] array, int offset, int count) {
deflateStream.Write(array, offset, count);
adler32.Update(array, offset, count);
}
+
+ public virtual void Close() {
- public override void Close() {
if (!initdone) doInit(); // can happen if never called write
if (closed) return;
closed = true;
// sigh ... no only must I close the parent stream to force a flush, but I must save a reference
// raw stream because (apparently) Close() sets it to null (shame on you, MS developers)
if (deflateStream != null) {
- deflateStream.Close();
+ deflateStream.Dispose();
} else { // second hack: empty input?
rawStream.WriteByte(3);
rawStream.WriteByte(0);
@@ -52,7 +53,7 @@ public override void Close() {
rawStream.WriteByte((byte)((crcv >> 8) & 0xFF));
rawStream.WriteByte((byte)((crcv) & 0xFF));
if (!leaveOpen)
- rawStream.Close();
+ rawStream.Dispose();
}
@@ -91,6 +92,22 @@ public override String getImplementationId() {
return "Zlib deflater: .Net CLR 4.5";
}
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ this.Close();
+ // Free any other managed objects here.
+ //
+ }
+
+ // Free any unmanaged objects here.
+ //
+
+ // Call base class implementation.
+ base.Dispose(disposing);
+ }
+
}
#endif
}
diff --git a/SamplesTests.Portable/App.config b/SamplesTests.Portable/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/SamplesTests.Portable/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SamplesTests.Portable/SamplesTests.Portable.csproj b/SamplesTests.Portable/SamplesTests.Portable.csproj
new file mode 100644
index 0000000..9b72baf
--- /dev/null
+++ b/SamplesTests.Portable/SamplesTests.Portable.csproj
@@ -0,0 +1,103 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {FC944235-D299-4EEF-BE46-D5A83C591048}
+ Exe
+ Properties
+ SamplesTests
+ SamplesTests
+ v4.5
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG;NET45
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE;NET45
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+ {ccf5e155-ecf0-4dbc-bc7c-69fe1aaaf235}
+ Hjg.Pngcs.Portable
+
+
+
+
+ FileHelper.cs
+
+
+ MainProgram.cs
+
+
+ NullOutputStream.cs
+
+
+ Properties\AssemblyInfo.cs
+
+
+ SampleConvertToTrueCol.cs
+
+
+ SampleCreateOrange.cs
+
+
+ SampleCustomChunk.cs
+
+
+ SampleDecreaseRed.cs
+
+
+ SampleMirrorImage.cs
+
+
+ SampleShowChunks.cs
+
+
+ SampleTileImage.cs
+
+
+ TestPngSuite.cs
+
+
+ TestsHelper.cs
+
+
+ TestTextChunks.cs
+
+
+ TestZlib.cs
+
+
+
+
+
\ No newline at end of file
diff --git a/SamplesTests/SampleTileImage.cs b/SamplesTests/SampleTileImage.cs
index 35d7b41..626f181 100644
--- a/SamplesTests/SampleTileImage.cs
+++ b/SamplesTests/SampleTileImage.cs
@@ -17,7 +17,6 @@ public static void tile(String orig, String dest,int factor) {
if (factor<2 || factor>100) throw new PngjException("bad factor ");
PngReader pngr = FileHelper.CreatePngReader(orig);
var x = pngr.ImgInfo;
- x.
PngWriter pngw = FileHelper.CreatePngWriter(dest, pngr.ImgInfo, true);
pngr.SetUnpackedMode(true); // we dont want to do the unpacking ourselves, we want a sample per array element
pngw.SetUseUnPackedMode(true); // not really necesary here, as we pass the ImageLine, but anyway...
diff --git a/pngcs.portable.sln b/pngcs.portable.sln
new file mode 100644
index 0000000..4bd271f
--- /dev/null
+++ b/pngcs.portable.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hjg.Pngcs.Portable", "Hjg.Pngcs.Portable\Hjg.Pngcs.Portable.csproj", "{CCF5E155-ECF0-4DBC-BC7C-69FE1AAAF235}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SamplesTests.Portable", "SamplesTests.Portable\SamplesTests.Portable.csproj", "{FC944235-D299-4EEF-BE46-D5A83C591048}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CCF5E155-ECF0-4DBC-BC7C-69FE1AAAF235}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CCF5E155-ECF0-4DBC-BC7C-69FE1AAAF235}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CCF5E155-ECF0-4DBC-BC7C-69FE1AAAF235}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CCF5E155-ECF0-4DBC-BC7C-69FE1AAAF235}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FC944235-D299-4EEF-BE46-D5A83C591048}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FC944235-D299-4EEF-BE46-D5A83C591048}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FC944235-D299-4EEF-BE46-D5A83C591048}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FC944235-D299-4EEF-BE46-D5A83C591048}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal