/// <summary> /// Writes the image data. /// </summary> /// <param name="writer">The writer.</param> /// <param name="count">The count of bits (pels) to encode.</param> /// <param name="white">The color of the pels.</param> private static void WriteSample(BitWriter writer, uint count, bool white) { uint[] terminatingCodes = white ? WhiteTerminatingCodes : BlackTerminatingCodes; uint[] makeUpCodes = white ? WhiteMakeUpCodes : BlackMakeUpCodes; // The make-up code for 2560 will be written as often as required: while (count >= 2624) { writer.WriteTableLine(makeUpCodes, 39); // Magic: 2560 count -= 2560; } // A make-up code for a multiple of 64 will be written if required: if (count > 63) { uint line = count / 64 - 1; writer.WriteTableLine(makeUpCodes, line); count -= (line + 1) * 64; } // And finally the terminating code for the remaining value (0 through 63): writer.WriteTableLine(terminatingCodes, count); }
/// <summary> /// Encodes a bitonal bitmap using 2D group 4 CCITT fax encoding. /// </summary> /// <param name="imageData">Space reserved for the fax encoded bitmap. An exception will be thrown if this buffer is too small.</param> /// <param name="imageBits">The bitmap to be encoded.</param> /// <param name="bytesFileOffset">Offset of image data in bitmap file.</param> /// <param name="width">The width of the image.</param> /// <param name="height">The height of the image.</param> /// <returns>The size of the fax encoded image (0 on failure).</returns> internal static int DoFaxEncodingGroup4(ref byte[] imageData, byte[] imageBits, uint bytesFileOffset, uint width, uint height) { try { uint bytesPerLineBmp = ((width + 31) / 32) * 4; BitWriter writer = new BitWriter(ref imageData); for (uint y = 0; y < height; ++y) { FaxEncode2DRow(writer, bytesFileOffset, imageBits, y, (y != 0) ? y - 1 : 0xffffffff, width, height, bytesPerLineBmp); } writer.FlushBuffer(); return writer.BytesWritten(); } catch (Exception ex) { ex.GetType(); return 0; } }
/// <summary> /// 2d-encode a row of pixels. Consult the CCITT documentation for the algorithm. /// </summary> /// <param name="writer">The writer.</param> /// <param name="bytesFileOffset">Offset of image data in bitmap file.</param> /// <param name="imageBits">The bitmap file.</param> /// <param name="currentRow">Index of the current row.</param> /// <param name="referenceRow">Index of the reference row (0xffffffff if there is none).</param> /// <param name="width">The width of the image.</param> /// <param name="height">The height of the image.</param> /// <param name="bytesPerLineBmp">The bytes per line in the bitmap file.</param> static void FaxEncode2DRow(BitWriter writer, uint bytesFileOffset, byte[] imageBits, uint currentRow, uint referenceRow, uint width, uint height, uint bytesPerLineBmp) { // Translated from LibTiff uint bytesOffsetRead = bytesFileOffset + (height - 1 - currentRow) * bytesPerLineBmp; BitReader reader = new BitReader(imageBits, bytesOffsetRead, width); BitReader readerReference; if (referenceRow != 0xffffffff) { uint bytesOffsetReadReference = bytesFileOffset + (height - 1 - referenceRow) * bytesPerLineBmp; readerReference = new BitReader(imageBits, bytesOffsetReadReference, width); } else { byte[] tmpImageBits = new byte[bytesPerLineBmp]; for (int i = 0; i < bytesPerLineBmp; ++i) tmpImageBits[i] = 255; readerReference = new BitReader(tmpImageBits, 0, width); } uint a0 = 0; uint a1 = !reader.GetBit(0) ? 0 : FindDifference(reader, 0, width, true); uint b1 = !readerReference.GetBit(0) ? 0 : FindDifference(readerReference, 0, width, true); // ReSharper disable TooWideLocalVariableScope uint a2, b2; // ReSharper restore TooWideLocalVariableScope for (;;) { b2 = FindDifferenceWithCheck(readerReference, b1, width, readerReference.GetBit(b1)); if (b2 >= a1) { int d = (int)b1 - (int)a1; if (!(-3 <= d && d <= 3)) { /* horizontal mode */ a2 = FindDifferenceWithCheck(reader, a1, width, reader.GetBit(a1)); writer.WriteTableLine(HorizontalCodes, 0); if (a0 + a1 == 0 || reader.GetBit(a0)) { WriteSample(writer, a1 - a0, true); WriteSample(writer, a2 - a1, false); } else { WriteSample(writer, a1 - a0, false); WriteSample(writer, a2 - a1, true); } a0 = a2; } else { /* vertical mode */ writer.WriteTableLine(VerticalCodes, (uint)(d + 3)); a0 = a1; } } else { /* pass mode */ writer.WriteTableLine(PassCodes, 0); a0 = b2; } if (a0 >= width) break; bool bitA0 = reader.GetBit(a0); a1 = FindDifference(reader, a0, width, bitA0/*reader.GetBit(a0)*/); b1 = FindDifference(readerReference, a0, width, !bitA0/*reader.GetBit(a0)*/); b1 = FindDifferenceWithCheck(readerReference, b1, width, bitA0/*reader.GetBit(a0)*/); } }
/// <summary> /// Encodes a bitonal bitmap using 1D CCITT fax encoding. /// </summary> /// <param name="imageData">Space reserved for the fax encoded bitmap. An exception will be thrown if this buffer is too small.</param> /// <param name="imageBits">The bitmap to be encoded.</param> /// <param name="bytesFileOffset">Offset of image data in bitmap file.</param> /// <param name="width">The width of the image.</param> /// <param name="height">The height of the image.</param> /// <returns>The size of the fax encoded image (0 on failure).</returns> private static int DoFaxEncoding(ref byte[] imageData, byte[] imageBits, uint bytesFileOffset, uint width, uint height) { try { uint bytesPerLineBmp = ((width + 31) / 32) * 4; BitWriter writer = new BitWriter(ref imageData); for (uint y = 0; y < height; ++y) { uint bytesOffsetRead = bytesFileOffset + (height - 1 - y) * bytesPerLineBmp; BitReader reader = new BitReader(imageBits, bytesOffsetRead, width); for (uint bitsRead = 0; bitsRead < width;) { uint white = CountOneBits(reader, width - bitsRead); WriteSample(writer, white, true); bitsRead += white; if (bitsRead < width) { uint black = CountZeroBits(reader, width - bitsRead); WriteSample(writer, black, false); bitsRead += black; } } } writer.FlushBuffer(); return writer.BytesWritten(); } catch (Exception /*ex*/) { //ex.GetType(); return 0; } }
/// <summary> /// 2d-encode a row of pixels. Consult the CCITT documentation for the algorithm. /// </summary> /// <param name="writer">The writer.</param> /// <param name="bytesFileOffset">Offset of image data in bitmap file.</param> /// <param name="imageBits">The bitmap file.</param> /// <param name="currentRow">Index of the current row.</param> /// <param name="referenceRow">Index of the reference row (0xffffffff if there is none).</param> /// <param name="width">The width of the image.</param> /// <param name="height">The height of the image.</param> /// <param name="bytesPerLineBmp">The bytes per line in the bitmap file.</param> static void FaxEncode2DRow(BitWriter writer, uint bytesFileOffset, byte[] imageBits, uint currentRow, uint referenceRow, uint width, uint height, uint bytesPerLineBmp) { // Translated from LibTiff uint bytesOffsetRead = bytesFileOffset + (height - 1 - currentRow) * bytesPerLineBmp; BitReader reader = new BitReader(imageBits, bytesOffsetRead, width); BitReader readerReference; if (referenceRow != 0xffffffff) { uint bytesOffsetReadReference = bytesFileOffset + (height - 1 - referenceRow) * bytesPerLineBmp; readerReference = new BitReader(imageBits, bytesOffsetReadReference, width); } else { byte[] tmpImageBits = new byte[bytesPerLineBmp]; for (int i = 0; i < bytesPerLineBmp; ++i) { tmpImageBits[i] = 255; } readerReference = new BitReader(tmpImageBits, 0, width); } uint a0 = 0; uint a1 = !reader.GetBit(0) ? 0 : FindDifference(reader, 0, width, true); uint b1 = !readerReference.GetBit(0) ? 0 : FindDifference(readerReference, 0, width, true); // ReSharper disable TooWideLocalVariableScope uint a2, b2; // ReSharper restore TooWideLocalVariableScope for (; ;) { b2 = FindDifferenceWithCheck(readerReference, b1, width, readerReference.GetBit(b1)); if (b2 >= a1) { int d = (int)b1 - (int)a1; if (!(-3 <= d && d <= 3)) { /* horizontal mode */ a2 = FindDifferenceWithCheck(reader, a1, width, reader.GetBit(a1)); writer.WriteTableLine(HorizontalCodes, 0); if (a0 + a1 == 0 || reader.GetBit(a0)) { WriteSample(writer, a1 - a0, true); WriteSample(writer, a2 - a1, false); } else { WriteSample(writer, a1 - a0, false); WriteSample(writer, a2 - a1, true); } a0 = a2; } else { /* vertical mode */ writer.WriteTableLine(VerticalCodes, (uint)(d + 3)); a0 = a1; } } else { /* pass mode */ writer.WriteTableLine(PassCodes, 0); a0 = b2; } if (a0 >= width) { break; } bool bitA0 = reader.GetBit(a0); a1 = FindDifference(reader, a0, width, bitA0 /*reader.GetBit(a0)*/); b1 = FindDifference(readerReference, a0, width, !bitA0 /*reader.GetBit(a0)*/); b1 = FindDifferenceWithCheck(readerReference, b1, width, bitA0 /*reader.GetBit(a0)*/); } }