/// <summary> /// Release resources for garbage collection /// </summary> public void CloseEncoder() { _YEncoder = null; _CbEncoder = null; _CrEncoder = null; Close(); }
/// <summary> /// Encodes one data chunk into output stream. Settings parameter controls /// how much data is generated.The chunk data is written to Stream /// with no IFF header. Successive calls to EncodeChunk encode /// successive chunks.You must call CloseCodec after encoding the last /// chunk of a file. /// </summary> /// <param name="stream"></param> /// <param name="settings"></param> /// <returns></returns> public int EncodeChunk(Stream stream, InterWaveEncoderSettings settings) { // Check if (settings.Slices == 0 && settings.Bytes == 0 && settings.Decibels == 0) { throw new DjvuArgumentException("Encoder needs stop condition", nameof(settings)); } if (_YMap == null) { throw new DjvuInvalidOperationException($"Cannot encode! Target encoder map is null {nameof(_YMap)}"); } // Open if (_YEncoder == null) { _CSlices = _CSerial = _CBytes = 0; _YEncoder = new InterWaveEncoder(_YMap); if (_CrMap != null && _CbMap != null) { _CbEncoder = new InterWaveEncoder(_CbMap); _CrEncoder = new InterWaveEncoder(_CrMap); } } // Prepare zcodec slices int flag = 1; int nslices = 0; using (MemoryStream coderStream = new MemoryStream()) { float estdb = -1.0f; ZPCodec zp = new ZPCodec(coderStream, true, true); while (flag != 0) { if (settings.Decibels > 0 && estdb >= settings.Decibels) { break; } if (settings.Bytes > 0 && coderStream.Position + _CBytes >= settings.Bytes) { break; } if (settings.Slices > 0 && nslices + _CSlices >= settings.Slices) { break; } flag = _YEncoder.CodeSlice(zp); if (flag != 0 && settings.Decibels > 0) { if (_YEncoder._CurrentBand == 0 || estdb >= settings.Decibels - DecibelPrune) { estdb = _YEncoder.EstimateDecibel(_dBFrac); } } if (_CrEncoder != null && _CbEncoder != null && _CSlices + nslices >= _CrCbDelay) { flag |= _CbEncoder.CodeSlice(zp); flag |= _CrEncoder.CodeSlice(zp); } nslices++; } zp.Flush(); // Write primary header stream.WriteByte((byte)_CSerial); stream.WriteByte((byte)(nslices)); // Write extended header if (_CSerial == 0) { byte major = InterWaveCodec.MajorVersion; if (!(_CrMap != null && _CbMap != null)) { major |= 0x80; } stream.WriteByte(major); stream.WriteByte(InterWaveCodec.MinorVersion); byte xhi = (byte)((_YMap.Width >> 8) & 0xff); byte xlo = (byte)(_YMap.Width & 0xff); byte yhi = (byte)((_YMap.Height >> 8) & 0xff); byte ylo = (byte)(_YMap.Height & 0xff); byte crCbDelay = (byte)(_CrCbHalf ? 0x00 : 0x80); crCbDelay |= (byte)(_CrCbDelay >= 0 ? _CrCbDelay : 0x00); stream.WriteByte(xhi); stream.WriteByte(xlo); stream.WriteByte(yhi); stream.WriteByte(ylo); stream.WriteByte(crCbDelay); } byte[] buffer = coderStream.GetBuffer(); stream.Write(buffer, 0, (int)coderStream.Position); _CBytes += (int)coderStream.Position; } _CSlices += nslices; _CSerial += 1; return(flag); }