Example #1
0
		// ship the compressed text out via chunk writes
		void png_write_compressed_data_out(ref compression_state comp)
		{
			// handle the no-compression case
			if(comp.input!=null)
			{
				png_write_chunk_data(comp.input, (uint)comp.input.Length);
				return;
			}

			// write saved output buffers, if any
			for(int i=0; i<comp.output_ptr.Count; i++)
			{
				png_write_chunk_data(comp.output_ptr[i], zbuf_size);
			}
			if(comp.output_ptr!=null) comp.output_ptr.Clear();
			// write anything left in zbuf
			if(zstream.avail_out<zbuf_size) png_write_chunk_data(zbuf, zbuf_size-zstream.avail_out);

			// reset zlib for another zTXt/iTXt or image data
			zlib.deflateReset(zstream);
		}
Example #2
0
		// compress given text into storage in the png_ptr structure
		uint png_text_compress(byte[] text, PNG_TEXT_COMPRESSION compression, ref compression_state comp)
		{
			comp.input=null;
			comp.output_ptr=null;

			// we may just want to pass the text right through
			if(compression==PNG_TEXT_COMPRESSION.NONE)
			{
				comp.input=text;
				return (uint)text.Length;
			}

			if(compression>=PNG_TEXT_COMPRESSION.LAST) Debug.WriteLine("Unknown compression type "+(int)compression);

			// We can't write the chunk until we find out how much data we have,
			// which means we need to run the compressor first and save the
			// output. This shouldn't be a problem, as the vast majority of
			// comments should be reasonable, but we will set up an array of
			// malloc'd pointers to be sure.
			//
			// If we knew the application was well behaved, we could simplify this
			// greatly by assuming we can always malloc an output buffer large
			// enough to hold the compressed text ((1001*text_len/1000)+12)
			// and malloc this directly. The only time this would be a bad idea is
			// if we can't malloc more than 64K and we have 64K of random input
			// data, or if the input string is incredibly large (although this
			// wouldn't cause a failure, just a slowdown due to swapping).

			// set up the compression buffers
			zstream.avail_in=(uint)text.Length;
			zstream.next_in=0;
			zstream.in_buf=text;
			zstream.avail_out=zbuf_size;
			zstream.next_out=0;
			zstream.out_buf=zbuf;

			comp.output_ptr=new List<byte[]>();

			// this is the same compression loop as in png_write_row()
			int ret;
			do
			{
				// compress the data
				ret=zlib.deflate(zstream, zlib.Z_NO_FLUSH);
				if(ret!=zlib.Z_OK)
				{ // error
					if(zstream.msg!=null&&zstream.msg.Length>0) throw new PNG_Exception(zstream.msg);
					throw new PNG_Exception("zlib error");
				}
				// check to see if we need more room
				if(zstream.avail_out==0)
				{
					// save the data
					byte[] buf=new byte[zbuf_size];
					zbuf.CopyTo(buf, 0);
					comp.output_ptr.Add(buf);

					// and reset the buffer
					zstream.avail_out=zbuf_size;
					zstream.next_out=0;
					zstream.out_buf=zbuf;
				}
				// continue until we don't have any more to compress
			} while(zstream.avail_in!=0);

			// finish the compression
			do
			{
				// tell zlib we are finished
				ret=zlib.deflate(zstream, zlib.Z_FINISH);
				if(ret!=zlib.Z_STREAM_END)
				{ // we got an error
					if(zstream.msg!=null&&zstream.msg.Length>0) throw new PNG_Exception(zstream.msg);
					throw new PNG_Exception("zlib error");
				}

				if(ret==zlib.Z_OK)
				{
					// check to see if we need more room
					if(zstream.avail_out==0)
					{
						// save off the data
						byte[] buf=new byte[zbuf_size];
						zbuf.CopyTo(buf, 0);
						comp.output_ptr.Add(buf);

						// and reset the buffer pointers
						zstream.avail_out=zbuf_size;
						zstream.next_out=0;
						zstream.out_buf=zbuf;
					}
				}
			} while(ret!=zlib.Z_STREAM_END);

			// text length is number of buffers plus last buffer
			uint text_len=zbuf_size*(uint)comp.output_ptr.Count;
			if(zstream.avail_out<zbuf_size) text_len+=zbuf_size-zstream.avail_out;

			return text_len;
		}