1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// found in the LICENSE file.
4ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
74d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <algorithm>
84d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <memory>
94d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <vector>
104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
11d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcodec/codec/ccodec_faxmodule.h"
12d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcodec/codec/ccodec_scanlinedecoder.h"
134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcodec/codec/codec_int.h"
14d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fxcrt/cfx_binarybuf.h"
154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcrt/fx_memory.h"
164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "third_party/base/ptr_util.h"
17d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "third_party/base/stl_util.h"
18ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
19ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannnamespace {
20ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
21ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannconst uint8_t OneLeadPos[256] = {
22ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
23ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
24ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
25ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
26ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
27ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
28ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
30ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
34ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannconst uint8_t ZeroLeadPos[256] = {
35ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
38ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
41ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
42ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
43ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
44ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
45e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8,
46e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
47e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Limit of image dimension, an arbitrary large number.
494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannconst int kMaxImageDimension = 0x01FFFF;
504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
51ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannint FindBit(const uint8_t* data_buf, int max_pos, int start_pos, int bit) {
524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  ASSERT(start_pos >= 0);
534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (start_pos >= max_pos)
54ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return max_pos;
554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
56ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const uint8_t* leading_pos = bit ? OneLeadPos : ZeroLeadPos;
57ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (start_pos % 8) {
58ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    uint8_t data = data_buf[start_pos / 8];
594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (bit)
60ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      data &= 0xff >> (start_pos % 8);
614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    else
62ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      data |= 0xff << (8 - start_pos % 8);
634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (leading_pos[data] < 8)
65ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return start_pos / 8 * 8 + leading_pos[data];
664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
67ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    start_pos += 7;
68ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
69ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t skip = bit ? 0x00 : 0xff;
70ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int byte_pos = start_pos / 8;
71ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int max_byte = (max_pos + 7) / 8;
72ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (byte_pos < max_byte) {
734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (data_buf[byte_pos] != skip)
74ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    ++byte_pos;
77ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (byte_pos == max_byte)
79ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return max_pos;
804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return std::min(leading_pos[data_buf[byte_pos]] + byte_pos * 8, max_pos);
82ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
83ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid FaxG4FindB1B2(const std::vector<uint8_t>& ref_buf,
85ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                   int columns,
86ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                   int a0,
87ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                   bool a0color,
884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   int* b1,
894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                   int* b2) {
90ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t first_bit =
91ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      (a0 < 0) ? 1 : ((ref_buf[a0 / 8] & (1 << (7 - a0 % 8))) != 0);
924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *b1 = FindBit(ref_buf.data(), columns, a0 + 1, !first_bit);
934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (*b1 >= columns) {
944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *b1 = *b2 = columns;
95ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
96ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
97ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (first_bit == !a0color) {
984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *b1 = FindBit(ref_buf.data(), columns, *b1 + 1, first_bit);
99ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    first_bit = !first_bit;
100ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (*b1 >= columns) {
1024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *b1 = *b2 = columns;
103ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
104ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *b2 = FindBit(ref_buf.data(), columns, *b1 + 1, first_bit);
106ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
107ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
108ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid FaxFillBits(uint8_t* dest_buf, int columns, int startpos, int endpos) {
1094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  startpos = std::max(startpos, 0);
110d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  endpos = pdfium::clamp(endpos, 0, columns);
1114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (startpos >= endpos)
112ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
1134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
114ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int first_byte = startpos / 8;
115ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int last_byte = (endpos - 1) / 8;
116ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (first_byte == last_byte) {
1174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    for (int i = startpos % 8; i <= (endpos - 1) % 8; ++i)
118ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      dest_buf[first_byte] -= 1 << (7 - i);
119ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    return;
120ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
1214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  for (int i = startpos % 8; i < 8; ++i)
123ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    dest_buf[first_byte] -= 1 << (7 - i);
1244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  for (int i = 0; i <= (endpos - 1) % 8; ++i)
125ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    dest_buf[last_byte] -= 1 << (7 - i);
1264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (last_byte > first_byte + 1)
128d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memset(dest_buf + first_byte + 1, 0, last_byte - first_byte - 1);
129e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
130ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
1314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmanninline bool NextBit(const uint8_t* src_buf, int* bitpos) {
1324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int pos = (*bitpos)++;
1334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return !!(src_buf[pos / 8] & (1 << (7 - pos % 8)));
1344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
135ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
136ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannconst uint8_t FaxBlackRunIns[] = {
137ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          2,          0x02,       3,          0,          0x03,
138ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    2,          0,          2,          0x02,       1,          0,
139ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x03,       4,          0,          2,          0x02,       6,
140ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x03,       5,          0,          1,          0x03,
141ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    7,          0,          2,          0x04,       9,          0,
142ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x05,       8,          0,          3,          0x04,       10,
143ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x05,       11,         0,          0x07,       12,
144ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          2,          0x04,       13,         0,          0x07,
145ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    14,         0,          1,          0x18,       15,         0,
146ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    5,          0x08,       18,         0,          0x0f,       64,
147ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x17,       16,         0,          0x18,       17,
148ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x37,       0,          0,          10,         0x08,
149ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x00,       0x07,       0x0c,       0x40,       0x07,       0x0d,
150ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x80,       0x07,       0x17,       24,         0,          0x18,
151ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    25,         0,          0x28,       23,         0,          0x37,
152ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    22,         0,          0x67,       19,         0,          0x68,
153ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    20,         0,          0x6c,       21,         0,          54,
154ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x12,       1984 % 256, 1984 / 256, 0x13,       2048 % 256, 2048 / 256,
155ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x14,       2112 % 256, 2112 / 256, 0x15,       2176 % 256, 2176 / 256,
156ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x16,       2240 % 256, 2240 / 256, 0x17,       2304 % 256, 2304 / 256,
157ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x1c,       2368 % 256, 2368 / 256, 0x1d,       2432 % 256, 2432 / 256,
158ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x1e,       2496 % 256, 2496 / 256, 0x1f,       2560 % 256, 2560 / 256,
159ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x24,       52,         0,          0x27,       55,         0,
160ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x28,       56,         0,          0x2b,       59,         0,
161ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x2c,       60,         0,          0x33,       320 % 256,  320 / 256,
162ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x34,       384 % 256,  384 / 256,  0x35,       448 % 256,  448 / 256,
163ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x37,       53,         0,          0x38,       54,         0,
164ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x52,       50,         0,          0x53,       51,         0,
165ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x54,       44,         0,          0x55,       45,         0,
166ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x56,       46,         0,          0x57,       47,         0,
167ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x58,       57,         0,          0x59,       58,         0,
168ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x5a,       61,         0,          0x5b,       256 % 256,  256 / 256,
169ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x64,       48,         0,          0x65,       49,         0,
170ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x66,       62,         0,          0x67,       63,         0,
171ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x68,       30,         0,          0x69,       31,         0,
172ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x6a,       32,         0,          0x6b,       33,         0,
173ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x6c,       40,         0,          0x6d,       41,         0,
174ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xc8,       128,        0,          0xc9,       192,        0,
175ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xca,       26,         0,          0xcb,       27,         0,
176ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xcc,       28,         0,          0xcd,       29,         0,
177ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xd2,       34,         0,          0xd3,       35,         0,
178ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xd4,       36,         0,          0xd5,       37,         0,
179ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xd6,       38,         0,          0xd7,       39,         0,
180ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xda,       42,         0,          0xdb,       43,         0,
181ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    20,         0x4a,       640 % 256,  640 / 256,  0x4b,       704 % 256,
182ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    704 / 256,  0x4c,       768 % 256,  768 / 256,  0x4d,       832 % 256,
183ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    832 / 256,  0x52,       1280 % 256, 1280 / 256, 0x53,       1344 % 256,
184ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1344 / 256, 0x54,       1408 % 256, 1408 / 256, 0x55,       1472 % 256,
185ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1472 / 256, 0x5a,       1536 % 256, 1536 / 256, 0x5b,       1600 % 256,
186ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1600 / 256, 0x64,       1664 % 256, 1664 / 256, 0x65,       1728 % 256,
187ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1728 / 256, 0x6c,       512 % 256,  512 / 256,  0x6d,       576 % 256,
188ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    576 / 256,  0x72,       896 % 256,  896 / 256,  0x73,       960 % 256,
189ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    960 / 256,  0x74,       1024 % 256, 1024 / 256, 0x75,       1088 % 256,
190ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1088 / 256, 0x76,       1152 % 256, 1152 / 256, 0x77,       1216 % 256,
191ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1216 / 256, 0xff};
192ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
193ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannconst uint8_t FaxWhiteRunIns[] = {
194ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0,          0,          6,          0x07,       2,
195ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x08,       3,          0,          0x0B,       4,
196ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x0C,       5,          0,          0x0E,       6,
197ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x0F,       7,          0,          6,          0x07,
198ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    10,         0,          0x08,       11,         0,          0x12,
199ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    128,        0,          0x13,       8,          0,          0x14,
200ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    9,          0,          0x1b,       64,         0,          9,
201ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x03,       13,         0,          0x07,       1,          0,
202ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x08,       12,         0,          0x17,       192,        0,
203ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x18,       1664 % 256, 1664 / 256, 0x2a,       16,         0,
204ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x2B,       17,         0,          0x34,       14,         0,
205ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x35,       15,         0,          12,         0x03,       22,
206ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x04,       23,         0,          0x08,       20,
207ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x0c,       19,         0,          0x13,       26,
208ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x17,       21,         0,          0x18,       28,
209ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x24,       27,         0,          0x27,       18,
210ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x28,       24,         0,          0x2B,       25,
211ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          0x37,       256 % 256,  256 / 256,  42,         0x02,
212ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    29,         0,          0x03,       30,         0,          0x04,
213ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    45,         0,          0x05,       46,         0,          0x0a,
214ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    47,         0,          0x0b,       48,         0,          0x12,
215ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    33,         0,          0x13,       34,         0,          0x14,
216ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    35,         0,          0x15,       36,         0,          0x16,
217ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    37,         0,          0x17,       38,         0,          0x1a,
218ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    31,         0,          0x1b,       32,         0,          0x24,
219ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    53,         0,          0x25,       54,         0,          0x28,
220ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    39,         0,          0x29,       40,         0,          0x2a,
221ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    41,         0,          0x2b,       42,         0,          0x2c,
222ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    43,         0,          0x2d,       44,         0,          0x32,
223ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    61,         0,          0x33,       62,         0,          0x34,
224ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    63,         0,          0x35,       0,          0,          0x36,
225ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    320 % 256,  320 / 256,  0x37,       384 % 256,  384 / 256,  0x4a,
226ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    59,         0,          0x4b,       60,         0,          0x52,
227ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    49,         0,          0x53,       50,         0,          0x54,
228ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    51,         0,          0x55,       52,         0,          0x58,
229ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    55,         0,          0x59,       56,         0,          0x5a,
230ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    57,         0,          0x5b,       58,         0,          0x64,
231ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    448 % 256,  448 / 256,  0x65,       512 % 256,  512 / 256,  0x67,
232ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    640 % 256,  640 / 256,  0x68,       576 % 256,  576 / 256,  16,
233ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x98,       1472 % 256, 1472 / 256, 0x99,       1536 % 256, 1536 / 256,
234ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x9a,       1600 % 256, 1600 / 256, 0x9b,       1728 % 256, 1728 / 256,
235ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xcc,       704 % 256,  704 / 256,  0xcd,       768 % 256,  768 / 256,
236ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xd2,       832 % 256,  832 / 256,  0xd3,       896 % 256,  896 / 256,
237ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xd4,       960 % 256,  960 / 256,  0xd5,       1024 % 256, 1024 / 256,
238ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xd6,       1088 % 256, 1088 / 256, 0xd7,       1152 % 256, 1152 / 256,
239ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xd8,       1216 % 256, 1216 / 256, 0xd9,       1280 % 256, 1280 / 256,
240ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xda,       1344 % 256, 1344 / 256, 0xdb,       1408 % 256, 1408 / 256,
241ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0,          3,          0x08,       1792 % 256, 1792 / 256, 0x0c,
242ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    1856 % 256, 1856 / 256, 0x0d,       1920 % 256, 1920 / 256, 10,
243ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x12,       1984 % 256, 1984 / 256, 0x13,       2048 % 256, 2048 / 256,
244ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x14,       2112 % 256, 2112 / 256, 0x15,       2176 % 256, 2176 / 256,
245ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x16,       2240 % 256, 2240 / 256, 0x17,       2304 % 256, 2304 / 256,
246ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x1c,       2368 % 256, 2368 / 256, 0x1d,       2432 % 256, 2432 / 256,
247ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x1e,       2496 % 256, 2496 / 256, 0x1f,       2560 % 256, 2560 / 256,
248ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xff,
249ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann};
250ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
251ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannint FaxGetRun(const uint8_t* ins_array,
252ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              const uint8_t* src_buf,
2534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann              int* bitpos,
254ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann              int bitsize) {
2554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t code = 0;
256ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int ins_off = 0;
257ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (1) {
258ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    uint8_t ins = ins_array[ins_off++];
2594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (ins == 0xff)
260ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return -1;
2614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (*bitpos >= bitsize)
263ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return -1;
2644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
265ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    code <<= 1;
2664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (src_buf[*bitpos / 8] & (1 << (7 - *bitpos % 8)))
2674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      ++code;
2684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    ++(*bitpos);
270ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int next_off = ins_off + ins * 3;
271ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    for (; ins_off < next_off; ins_off += 3) {
272d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (ins_array[ins_off] == code)
273ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        return ins_array[ins_off + 1] + ins_array[ins_off + 2] * 256;
274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
275ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
277ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
278d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid FaxG4GetRow(const uint8_t* src_buf,
2794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 int bitsize,
2804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 int* bitpos,
2814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 uint8_t* dest_buf,
2824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 const std::vector<uint8_t>& ref_buf,
2834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 int columns) {
284ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int a0 = -1;
285ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  bool a0color = true;
286ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (1) {
2874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (*bitpos >= bitsize)
288d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return;
2894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int a1;
2914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int a2;
2924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int b1;
2934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int b2;
2944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    FaxG4FindB1B2(ref_buf, columns, a0, a0color, &b1, &b2);
2954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
296ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int v_delta = 0;
2974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (!NextBit(src_buf, bitpos)) {
2984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (*bitpos >= bitsize)
299d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        return;
3004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      bool bit1 = NextBit(src_buf, bitpos);
3024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (*bitpos >= bitsize)
303d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        return;
3044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      bool bit2 = NextBit(src_buf, bitpos);
3064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (bit1) {
3074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        v_delta = bit2 ? 1 : -1;
308ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else if (bit2) {
309ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        int run_len1 = 0;
310ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        while (1) {
311ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          int run = FaxGetRun(a0color ? FaxWhiteRunIns : FaxBlackRunIns,
312ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              src_buf, bitpos, bitsize);
313ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          run_len1 += run;
314d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          if (run < 64)
315ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            break;
316e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
3174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (a0 < 0)
3184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          ++run_len1;
319d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        if (run_len1 < 0)
320d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          return;
3214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
322ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        a1 = a0 + run_len1;
3234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (!a0color)
324ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          FaxFillBits(dest_buf, columns, a0, a1);
3254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
326ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        int run_len2 = 0;
327ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        while (1) {
328ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          int run = FaxGetRun(a0color ? FaxBlackRunIns : FaxWhiteRunIns,
329ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                              src_buf, bitpos, bitsize);
330ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          run_len2 += run;
331d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          if (run < 64)
332ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            break;
333e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
334d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        if (run_len2 < 0)
335d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          return;
336ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        a2 = a1 + run_len2;
3374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (a0color)
338ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          FaxFillBits(dest_buf, columns, a1, a2);
3394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
340ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        a0 = a2;
3414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (a0 < columns)
342ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          continue;
3434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
344d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        return;
345ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      } else {
3464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (*bitpos >= bitsize)
347d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          return;
3484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (NextBit(src_buf, bitpos)) {
3504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          if (!a0color)
351ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann            FaxFillBits(dest_buf, columns, a0, b2);
3524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          if (b2 >= columns)
354d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            return;
3554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
356ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          a0 = b2;
357ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          continue;
3584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        }
3594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (*bitpos >= bitsize)
361d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          return;
3624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        bool next_bit1 = NextBit(src_buf, bitpos);
3644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (*bitpos >= bitsize)
365d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          return;
3664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        bool next_bit2 = NextBit(src_buf, bitpos);
3684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        if (next_bit1) {
3694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          v_delta = next_bit2 ? 2 : -2;
3704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        } else if (next_bit2) {
3714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          if (*bitpos >= bitsize)
372d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            return;
3734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          v_delta = NextBit(src_buf, bitpos) ? 3 : -3;
375e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
3764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          if (*bitpos >= bitsize)
377d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            return;
3784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          if (NextBit(src_buf, bitpos)) {
3804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            *bitpos += 3;
3814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann            continue;
382ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          }
3834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          *bitpos += 5;
384d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann          return;
385e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
386ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
388ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    a1 = b1 + v_delta;
3894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (!a0color)
390ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FaxFillBits(dest_buf, columns, a0, a1);
3914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (a1 >= columns)
393d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return;
3944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    // The position of picture element must be monotonic increasing.
3964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (a0 >= a1)
397d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return;
3984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
399ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    a0 = a1;
400ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    a0color = !a0color;
401ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
402e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
403ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
404d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid FaxSkipEOL(const uint8_t* src_buf, int bitsize, int* bitpos) {
4054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int startbit = *bitpos;
4064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  while (*bitpos < bitsize) {
4074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (!NextBit(src_buf, bitpos))
4084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      continue;
4094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (*bitpos - startbit <= 11)
4104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      *bitpos = startbit;
411d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    return;
4124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
413e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
414ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
415d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid FaxGet1DLine(const uint8_t* src_buf,
4164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  int bitsize,
4174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  int* bitpos,
4184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  std::vector<uint8_t>* dest_buf,
4194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  int columns) {
420ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  bool color = true;
421ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int startpos = 0;
422ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (1) {
4234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (*bitpos >= bitsize)
424d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      return;
4254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
426ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int run_len = 0;
427ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    while (1) {
428ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int run = FaxGetRun(color ? FaxWhiteRunIns : FaxBlackRunIns, src_buf,
429ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                          bitpos, bitsize);
430ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      if (run < 0) {
4314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        while (*bitpos < bitsize) {
4324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          if (NextBit(src_buf, bitpos))
433d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann            return;
434e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
435d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann        return;
436ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
437ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      run_len += run;
438d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (run < 64)
439ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        break;
440ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
4414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (!color)
4424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      FaxFillBits(dest_buf->data(), columns, startpos, startpos + run_len);
4434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
444ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    startpos += run_len;
4454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (startpos >= columns)
446ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      break;
4474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
448ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    color = !color;
449ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
450e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
451ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
4524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}  // namespace
4534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannclass CCodec_FaxDecoder : public CCodec_ScanlineDecoder {
4554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann public:
4564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CCodec_FaxDecoder(const uint8_t* src_buf,
4574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    uint32_t src_size,
4584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    int width,
4594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    int height,
4604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    uint32_t pitch,
4614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    int K,
4624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    bool EndOfLine,
4634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    bool EncodedByteAlign,
4644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                    bool BlackIs1);
4654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  ~CCodec_FaxDecoder() override;
4664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  // CCodec_ScanlineDecoder
4684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool v_Rewind() override;
4694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint8_t* v_GetNextLine() override;
4704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t GetSrcOffset() override;
4714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann private:
4734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const int m_Encoding;
4744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int m_bitpos;
4754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool m_bByteAlign;
4764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const bool m_bEndOfLine;
4774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const bool m_bBlack;
4784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const uint32_t m_SrcSize;
4794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const uint8_t* const m_pSrcBuf;
4804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  std::vector<uint8_t> m_ScanlineBuf;
4814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  std::vector<uint8_t> m_RefBuf;
4824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann};
4834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannCCodec_FaxDecoder::CCodec_FaxDecoder(const uint8_t* src_buf,
4854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     uint32_t src_size,
4864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     int width,
4874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     int height,
4884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     uint32_t pitch,
4894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     int K,
4904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     bool EndOfLine,
4914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     bool EncodedByteAlign,
4924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     bool BlackIs1)
4934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    : CCodec_ScanlineDecoder(width, height, width, height, 1, 1, pitch),
4944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_Encoding(K),
4954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_bitpos(0),
4964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_bByteAlign(EncodedByteAlign),
4974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_bEndOfLine(EndOfLine),
4984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_bBlack(BlackIs1),
4994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_SrcSize(src_size),
5004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_pSrcBuf(src_buf),
5014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_ScanlineBuf(pitch),
5024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_RefBuf(pitch) {}
5034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannCCodec_FaxDecoder::~CCodec_FaxDecoder() {}
5054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_FaxDecoder::v_Rewind() {
507d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  memset(m_RefBuf.data(), 0xff, m_RefBuf.size());
5084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_bitpos = 0;
5094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
5104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
5114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannuint8_t* CCodec_FaxDecoder::v_GetNextLine() {
5134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int bitsize = m_SrcSize * 8;
5144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
5154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (m_bitpos >= bitsize)
5164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
5174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
518d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  memset(m_ScanlineBuf.data(), 0xff, m_ScanlineBuf.size());
5194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (m_Encoding < 0) {
5204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
5214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                m_OrigWidth);
5224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    m_RefBuf = m_ScanlineBuf;
5234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  } else if (m_Encoding == 0) {
5244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
5254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  } else {
5264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (NextBit(m_pSrcBuf, &m_bitpos)) {
5274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      FaxGet1DLine(m_pSrcBuf, bitsize, &m_bitpos, &m_ScanlineBuf, m_OrigWidth);
5284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    } else {
5294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      FaxG4GetRow(m_pSrcBuf, bitsize, &m_bitpos, m_ScanlineBuf.data(), m_RefBuf,
5304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                  m_OrigWidth);
5314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
5324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    m_RefBuf = m_ScanlineBuf;
5334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
5344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (m_bEndOfLine)
5354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    FaxSkipEOL(m_pSrcBuf, bitsize, &m_bitpos);
5364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (m_bByteAlign && m_bitpos < bitsize) {
5384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int bitpos0 = m_bitpos;
5394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int bitpos1 = (m_bitpos + 7) / 8 * 8;
5404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    while (m_bByteAlign && bitpos0 < bitpos1) {
5414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      int bit = m_pSrcBuf[bitpos0 / 8] & (1 << (7 - bitpos0 % 8));
542d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (bit != 0)
5434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        m_bByteAlign = false;
544d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      else
5454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        ++bitpos0;
5464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
5474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (m_bByteAlign)
5484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_bitpos = bitpos1;
5494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
5504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (m_bBlack) {
551d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    for (uint32_t i = 0; i < m_Pitch; ++i)
5524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      m_ScanlineBuf[i] = ~m_ScanlineBuf[i];
5534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
5544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return m_ScanlineBuf.data();
5554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
5564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannuint32_t CCodec_FaxDecoder::GetSrcOffset() {
5584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return std::min(static_cast<uint32_t>((m_bitpos + 7) / 8), m_SrcSize);
5594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
5604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid FaxG4Decode(const uint8_t* src_buf,
5624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 uint32_t src_size,
5634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 int* pbitpos,
5644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 uint8_t* dest_buf,
5654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 int width,
5664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 int height,
5674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                 int pitch) {
5684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (pitch == 0)
5694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    pitch = (width + 7) / 8;
5704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  std::vector<uint8_t> ref_buf(pitch, 0xff);
5724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int bitpos = *pbitpos;
5734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  for (int iRow = 0; iRow < height; iRow++) {
5744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    uint8_t* line_buf = dest_buf + iRow * pitch;
575d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memset(line_buf, 0xff, pitch);
5764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    FaxG4GetRow(src_buf, src_size << 3, &bitpos, line_buf, ref_buf, width);
577d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memcpy(ref_buf.data(), line_buf, pitch);
5784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
5794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *pbitpos = bitpos;
5804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
5814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstd::unique_ptr<CCodec_ScanlineDecoder> CCodec_FaxModule::CreateDecoder(
5834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    const uint8_t* src_buf,
5844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    uint32_t src_size,
5854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int width,
5864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int height,
5874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int K,
5884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    bool EndOfLine,
5894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    bool EncodedByteAlign,
5904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    bool BlackIs1,
5914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int Columns,
5924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int Rows) {
5934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int actual_width = Columns ? Columns : width;
5944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int actual_height = Rows ? Rows : height;
5954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  // Reject invalid values.
5974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (actual_width <= 0 || actual_height <= 0)
5984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
5994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  // Reject unreasonable large input.
6014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (actual_width > kMaxImageDimension || actual_height > kMaxImageDimension)
6024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
6034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
6044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t pitch = (static_cast<uint32_t>(actual_width) + 31) / 32 * 4;
6054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return pdfium::MakeUnique<CCodec_FaxDecoder>(
6064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      src_buf, src_size, actual_width, actual_height, pitch, K, EndOfLine,
6074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      EncodedByteAlign, BlackIs1);
6084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
6094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
610d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
6114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannnamespace {
612ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannconst uint8_t BlackRunTerminator[128] = {
613ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x37, 10, 0x02, 3,  0x03, 2,  0x02, 2,  0x03, 3,  0x03, 4,  0x02, 4,
614ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x03, 5,  0x05, 6,  0x04, 6,  0x04, 7,  0x05, 7,  0x07, 7,  0x04, 8,
615ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x07, 8,  0x18, 9,  0x17, 10, 0x18, 10, 0x08, 10, 0x67, 11, 0x68, 11,
616ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x6c, 11, 0x37, 11, 0x28, 11, 0x17, 11, 0x18, 11, 0xca, 12, 0xcb, 12,
617ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xcc, 12, 0xcd, 12, 0x68, 12, 0x69, 12, 0x6a, 12, 0x6b, 12, 0xd2, 12,
618ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xd3, 12, 0xd4, 12, 0xd5, 12, 0xd6, 12, 0xd7, 12, 0x6c, 12, 0x6d, 12,
619ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xda, 12, 0xdb, 12, 0x54, 12, 0x55, 12, 0x56, 12, 0x57, 12, 0x64, 12,
620ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x65, 12, 0x52, 12, 0x53, 12, 0x24, 12, 0x37, 12, 0x38, 12, 0x27, 12,
621ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x28, 12, 0x58, 12, 0x59, 12, 0x2b, 12, 0x2c, 12, 0x5a, 12, 0x66, 12,
622ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x67, 12,
623e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
624ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
625ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannconst uint8_t BlackRunMarkup[80] = {
626ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x0f, 10, 0xc8, 12, 0xc9, 12, 0x5b, 12, 0x33, 12, 0x34, 12, 0x35, 12,
627ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x6c, 13, 0x6d, 13, 0x4a, 13, 0x4b, 13, 0x4c, 13, 0x4d, 13, 0x72, 13,
628ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x73, 13, 0x74, 13, 0x75, 13, 0x76, 13, 0x77, 13, 0x52, 13, 0x53, 13,
629ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x54, 13, 0x55, 13, 0x5a, 13, 0x5b, 13, 0x64, 13, 0x65, 13, 0x08, 11,
630ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
631ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
632e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
633ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
634ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannconst uint8_t WhiteRunTerminator[128] = {
635ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x35, 8, 0x07, 6, 0x07, 4, 0x08, 4, 0x0B, 4, 0x0C, 4, 0x0E, 4, 0x0F, 4,
636ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x13, 5, 0x14, 5, 0x07, 5, 0x08, 5, 0x08, 6, 0x03, 6, 0x34, 6, 0x35, 6,
637ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x2a, 6, 0x2B, 6, 0x27, 7, 0x0c, 7, 0x08, 7, 0x17, 7, 0x03, 7, 0x04, 7,
638ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x28, 7, 0x2B, 7, 0x13, 7, 0x24, 7, 0x18, 7, 0x02, 8, 0x03, 8, 0x1a, 8,
639ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x1b, 8, 0x12, 8, 0x13, 8, 0x14, 8, 0x15, 8, 0x16, 8, 0x17, 8, 0x28, 8,
640ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x29, 8, 0x2a, 8, 0x2b, 8, 0x2c, 8, 0x2d, 8, 0x04, 8, 0x05, 8, 0x0a, 8,
641ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x0b, 8, 0x52, 8, 0x53, 8, 0x54, 8, 0x55, 8, 0x24, 8, 0x25, 8, 0x58, 8,
642ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x59, 8, 0x5a, 8, 0x5b, 8, 0x4a, 8, 0x4b, 8, 0x32, 8, 0x33, 8, 0x34, 8,
643e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
644ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
645ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannconst uint8_t WhiteRunMarkup[80] = {
646ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x1b, 5,  0x12, 5,  0x17, 6,  0x37, 7,  0x36, 8,  0x37, 8,  0x64, 8,
647ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x65, 8,  0x68, 8,  0x67, 8,  0xcc, 9,  0xcd, 9,  0xd2, 9,  0xd3, 9,
648ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xd4, 9,  0xd5, 9,  0xd6, 9,  0xd7, 9,  0xd8, 9,  0xd9, 9,  0xda, 9,
649ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0xdb, 9,  0x98, 9,  0x99, 9,  0x9a, 9,  0x18, 6,  0x9b, 9,  0x08, 11,
650ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x0c, 11, 0x0d, 11, 0x12, 12, 0x13, 12, 0x14, 12, 0x15, 12, 0x16, 12,
651ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    0x17, 12, 0x1c, 12, 0x1d, 12, 0x1e, 12, 0x1f, 12,
652e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
653ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
6544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid AddBitStream(uint8_t* dest_buf, int* dest_bitpos, int data, int bitlen) {
655ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int i = bitlen - 1; i >= 0; i--) {
656d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (data & (1 << i))
6574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
6584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    (*dest_bitpos)++;
659ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
660e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
661ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
6624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid FaxEncodeRun(uint8_t* dest_buf, int* dest_bitpos, int run, bool bWhite) {
663ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (run >= 2560) {
664ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    AddBitStream(dest_buf, dest_bitpos, 0x1f, 12);
665ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    run -= 2560;
666ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
667ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  if (run >= 64) {
668ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int markup = run - run % 64;
669ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    const uint8_t* p = bWhite ? WhiteRunMarkup : BlackRunMarkup;
670ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    p += (markup / 64 - 1) * 2;
671ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
672ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
673ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  run %= 64;
674ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const uint8_t* p = bWhite ? WhiteRunTerminator : BlackRunTerminator;
675ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  p += run * 2;
676ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  AddBitStream(dest_buf, dest_bitpos, *p, p[1]);
677e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
678ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
679ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannvoid FaxEncode2DLine(uint8_t* dest_buf,
6804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     int* dest_bitpos,
681ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     const uint8_t* src_buf,
6824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                     const std::vector<uint8_t>& ref_buf,
683ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                     int cols) {
684ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int a0 = -1;
685ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  bool a0color = true;
686ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  while (1) {
687ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int a1 = FindBit(src_buf, cols, a0 + 1, !a0color);
6884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int b1;
6894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int b2;
6904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    FaxG4FindB1B2(ref_buf, cols, a0, a0color, &b1, &b2);
691ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    if (b2 < a1) {
6924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      *dest_bitpos += 3;
6934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
6944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (*dest_bitpos)++;
695ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      a0 = b2;
696ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else if (a1 - b1 <= 3 && b1 - a1 <= 3) {
697ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int delta = a1 - b1;
698ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      switch (delta) {
699ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case 0:
7004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
701ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          break;
702ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case 1:
703ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case 2:
704ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case 3:
7054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          *dest_bitpos += delta == 1 ? 1 : delta + 2;
7064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
7074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          (*dest_bitpos)++;
7084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
709ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          break;
710ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case -1:
711ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case -2:
712ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        case -3:
7134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          *dest_bitpos += delta == -1 ? 1 : -delta + 2;
7144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
7154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          (*dest_bitpos)++;
716ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann          break;
717ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      }
7184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (*dest_bitpos)++;
719ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      a0 = a1;
720ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      a0color = !a0color;
721ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    } else {
722ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      int a2 = FindBit(src_buf, cols, a1 + 1, a0color);
7234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (*dest_bitpos)++;
7244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (*dest_bitpos)++;
7254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      dest_buf[*dest_bitpos / 8] |= 1 << (7 - *dest_bitpos % 8);
7264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (*dest_bitpos)++;
727d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann      if (a0 < 0)
728ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann        a0 = 0;
729ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FaxEncodeRun(dest_buf, dest_bitpos, a1 - a0, a0color);
730ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      FaxEncodeRun(dest_buf, dest_bitpos, a2 - a1, !a0color);
731ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      a0 = a2;
732ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    }
733d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    if (a0 >= cols)
734ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann      return;
735ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
736ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann}
737ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann
738ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmannclass CCodec_FaxEncoder {
739ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann public:
740ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CCodec_FaxEncoder(const uint8_t* src_buf, int width, int height, int pitch);
741ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  ~CCodec_FaxEncoder();
7424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  void Encode(std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
7434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann              uint32_t* dest_size);
7444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann private:
746ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  CFX_BinaryBuf m_DestBuf;
7474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  std::vector<uint8_t> m_RefLine;
748ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t* m_pLineBuf;
7494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const int m_Cols;
7504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const int m_Rows;
7514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const int m_Pitch;
752ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  const uint8_t* m_pSrcBuf;
753e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov};
7544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
755ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannCCodec_FaxEncoder::CCodec_FaxEncoder(const uint8_t* src_buf,
756ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                     int width,
757ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann                                     int height,
7584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     int pitch)
7594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    : m_Cols(width), m_Rows(height), m_Pitch(pitch), m_pSrcBuf(src_buf) {
7604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_RefLine.resize(m_Pitch);
761d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  memset(m_RefLine.data(), 0xff, m_Pitch);
762ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_pLineBuf = FX_Alloc2D(uint8_t, m_Pitch, 8);
763ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  m_DestBuf.EstimateSize(0, 10240);
764e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
7654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
766ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. MoltmannCCodec_FaxEncoder::~CCodec_FaxEncoder() {
767ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  FX_Free(m_pLineBuf);
768e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
7694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid CCodec_FaxEncoder::Encode(
7714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
7724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    uint32_t* dest_size) {
773ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  int dest_bitpos = 0;
774ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  uint8_t last_byte = 0;
775ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  for (int i = 0; i < m_Rows; i++) {
776ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    const uint8_t* scan_line = m_pSrcBuf + i * m_Pitch;
777d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memset(m_pLineBuf, 0, m_Pitch * 8);
778ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_pLineBuf[0] = last_byte;
7794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    FaxEncode2DLine(m_pLineBuf, &dest_bitpos, scan_line, m_RefLine, m_Cols);
780ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_DestBuf.AppendBlock(m_pLineBuf, dest_bitpos / 8);
781ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    last_byte = m_pLineBuf[dest_bitpos / 8];
782ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    dest_bitpos %= 8;
783d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann    memcpy(m_RefLine.data(), scan_line, m_Pitch);
784ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann  }
785d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann  if (dest_bitpos)
786ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    m_DestBuf.AppendByte(last_byte);
7874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *dest_size = m_DestBuf.GetSize();
7884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *dest_buf = m_DestBuf.DetachBuffer();
789e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
7904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}  // namespace
7924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
7934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid CCodec_FaxModule::FaxEncode(
794ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    const uint8_t* src_buf,
795ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int width,
796ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4Philip P. Moltmann    int height,
7974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int pitch,
7984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
7994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    uint32_t* dest_size) {
8004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CCodec_FaxEncoder encoder(src_buf, width, height, pitch);
8014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  encoder.Encode(dest_buf, dest_size);
802e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
8034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
804d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#endif  // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
805