mirror of http://192.168.1.51:8099/lmh188/twain3.0
增加针对G4 压缩的相关操作类
This commit is contained in:
parent
4079d5cb0d
commit
9d99bc37d0
|
@ -0,0 +1,102 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "G4Tiff.h"
|
||||||
|
#include <io.h>
|
||||||
|
|
||||||
|
G4Tiff::G4Tiff(cv::Mat & mat, int threshold)
|
||||||
|
{
|
||||||
|
m_tmppath = cv::tempfile(".tif");
|
||||||
|
if (mat.channels() != 1)
|
||||||
|
throw std::runtime_error("mat channel error");
|
||||||
|
TIFF* pTiffHandle = TIFFOpen(m_tmppath.c_str(), "w");
|
||||||
|
if (!pTiffHandle)
|
||||||
|
{
|
||||||
|
printf("can't open TIFF descriptor\n");
|
||||||
|
}
|
||||||
|
int width = mat.cols;
|
||||||
|
int height = mat.rows;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width), "width");
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height), "length");
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, 1), "bits per sample");
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, 1), "samples per pixel");
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, 1), "rows per strip");
|
||||||
|
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4), "compression");
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE), "photometric");
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB), "photometric");
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG), "planar config");
|
||||||
|
|
||||||
|
// not necessary
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_XRESOLUTION, 200.0), "res x");
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_YRESOLUTION, 200.0), "res y");
|
||||||
|
except(TIFFSetField(pTiffHandle, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH), "res unit");
|
||||||
|
|
||||||
|
std::vector<uchar> _buffer(width / 8 + 8, 0);
|
||||||
|
uchar* buffer = &_buffer[0];
|
||||||
|
int bytes = int(width / 8.0 + 0.5);
|
||||||
|
for (int y = 0; y < height; ++y)
|
||||||
|
{
|
||||||
|
uint8_t* src_row = mat.ptr(y);
|
||||||
|
for (int x = 0; x < width; ++x, ++src_row)
|
||||||
|
{
|
||||||
|
uint8_t eight_pixels = buffer[x / 8];
|
||||||
|
eight_pixels = eight_pixels << 1;
|
||||||
|
if (*src_row < threshold)
|
||||||
|
eight_pixels = eight_pixels | 1; //
|
||||||
|
buffer[x / 8] = eight_pixels;
|
||||||
|
}
|
||||||
|
except(TIFFWriteScanline(pTiffHandle, buffer, y, bytes) != -1, "write scanline");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (const std::runtime_error& e)
|
||||||
|
{
|
||||||
|
printf("TIFF writing: %s\n", e.what());
|
||||||
|
TIFFClose(pTiffHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
TIFFClose(pTiffHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
G4Tiff::~G4Tiff()
|
||||||
|
{
|
||||||
|
if (_access(m_tmppath.c_str(), 0) == 0)
|
||||||
|
{
|
||||||
|
if (!std::remove(m_tmppath.c_str())) {}//ɾ³ý³É¹¦
|
||||||
|
else
|
||||||
|
throw std::runtime_error("File is not exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void G4Tiff::GetCompressedData(std::vector<uchar>& cmpeddata)
|
||||||
|
{
|
||||||
|
if (m_tmppath.empty())
|
||||||
|
throw std::runtime_error("file is not exist");
|
||||||
|
FILE* file = fopen(m_tmppath.c_str(), "rb");
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
int filesize = _lseek(_fileno(file), 0, SEEK_END); // seek to EOF
|
||||||
|
fseek(file, 0, SEEK_SET);
|
||||||
|
if (filesize)
|
||||||
|
{
|
||||||
|
cmpeddata.resize(filesize);
|
||||||
|
fread(cmpeddata.data(), 1, filesize, file);
|
||||||
|
}
|
||||||
|
FILE* file1 = fopen("d:\\1.tiff", "wb");
|
||||||
|
fwrite(cmpeddata.data(), filesize, 1, file1);
|
||||||
|
fclose(file1);
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
|
||||||
|
//TIFF* pTiffHandle = TIFFOpen(m_tmppath.c_str(), "w");
|
||||||
|
//TIFFGetField()
|
||||||
|
//TIFFClose(pTiffHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void G4Tiff::except(bool condition, const std::string & message)
|
||||||
|
{
|
||||||
|
if (!condition)
|
||||||
|
throw std::runtime_error("Error " + message);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include <tiff.h>
|
||||||
|
#include <tiffio.h>
|
||||||
|
|
||||||
|
class G4Tiff
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
G4Tiff(cv::Mat& mat,int threshold=120);
|
||||||
|
~G4Tiff();
|
||||||
|
public:
|
||||||
|
void GetCompressedData(std::vector<uchar>& cmpeddata);
|
||||||
|
private:
|
||||||
|
void except(bool condition, const std::string& message = "");
|
||||||
|
std::string m_tmppath;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,516 @@
|
||||||
|
#include "TiffG4Compression.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef TIME
|
||||||
|
struct timeval t1, t2;
|
||||||
|
struct timezone tz;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TiffG4Compression::TiffG4Compression()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TiffG4Compression::~TiffG4Compression()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int TiffG4Compression::G4Compress(unsigned char * indata, int inbytes, int width, int height, unsigned char * outdata, int * outbytes)
|
||||||
|
{
|
||||||
|
struct uncompressed_descriptor uncompressed;
|
||||||
|
struct compressed_descriptor compressed;
|
||||||
|
|
||||||
|
uncompressed.pixels_per_line = width;
|
||||||
|
uncompressed.number_of_lines = height;
|
||||||
|
uncompressed.data = indata;
|
||||||
|
comp_alloc_flag = NOALLOC;
|
||||||
|
comp_write_init_flag = 1;
|
||||||
|
read_uncompressed_file_into_memory(&uncompressed);
|
||||||
|
compressed.data = outdata;
|
||||||
|
control_compression(&uncompressed, &compressed);
|
||||||
|
*outbytes = compressed.length_in_bytes;
|
||||||
|
return *outbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::control_compression(uncompressed_descriptor * uncompressed, compressed_descriptor * compressed)
|
||||||
|
{
|
||||||
|
struct parameters sole_parameters;
|
||||||
|
struct parameters *params = &sole_parameters;
|
||||||
|
|
||||||
|
#ifdef TIME
|
||||||
|
SHORT i;
|
||||||
|
tz.tz_minuteswest = 0;
|
||||||
|
tz.tz_dsttime = 0;
|
||||||
|
gettimeofday(&t1, &tz);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
prepare_to_compress(uncompressed, compressed, params);
|
||||||
|
compress_image(uncompressed, compressed, params);
|
||||||
|
/* memory deallocation added by Michael D. Garris 2/26/90 */
|
||||||
|
free(params->reference_line);
|
||||||
|
free(params->coding_line);
|
||||||
|
#ifdef TIME
|
||||||
|
gettimeofday(&t2, &tz);
|
||||||
|
printf("\ntime difference: %ld:%ld\n", t2.tv_sec - t1.tv_sec,
|
||||||
|
t2.tv_usec - t1.tv_usec);
|
||||||
|
for (i = 0; i < 5; i++) printf("%c", '\07'); */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::read_uncompressed_file_into_memory(uncompressed_descriptor * uncompressed)
|
||||||
|
{
|
||||||
|
int file_size;
|
||||||
|
|
||||||
|
if (comp_alloc_flag)
|
||||||
|
{
|
||||||
|
file_size = uncompressed->pixels_per_line * uncompressed->number_of_lines
|
||||||
|
/ Pixels_per_byte;
|
||||||
|
if ((uncompressed->data = (unsigned char *)calloc(file_size, sizeof(char))) == NULL)
|
||||||
|
{
|
||||||
|
printf("\nCannot allocate enough memory for uncomp file.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (uncompressed->data == NULL)
|
||||||
|
{
|
||||||
|
printf("\nNo memory allocated for input data!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::prepare_to_compress(uncompressed_descriptor * uncompressed, compressed_descriptor * compressed, parameters * params)
|
||||||
|
{
|
||||||
|
params->max_pixel = uncompressed->pixels_per_line;
|
||||||
|
compressed->pixels_per_line = uncompressed->pixels_per_line;
|
||||||
|
compressed->number_of_lines = uncompressed->number_of_lines;
|
||||||
|
|
||||||
|
set_up_first_line_c(params);
|
||||||
|
prepare_to_write_bits_c(compressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::compress_image(uncompressed_descriptor * uncompressed, compressed_descriptor * compressed, parameters * params)
|
||||||
|
{
|
||||||
|
SHORT line;
|
||||||
|
for (line = 0; line < uncompressed->number_of_lines; line++)
|
||||||
|
{
|
||||||
|
make_array_of_changing_elements(params, uncompressed, line);
|
||||||
|
set_up_first_and_last_changing_elements_c(params);
|
||||||
|
compress_line(params);
|
||||||
|
prepare_to_compress_next_line(params);
|
||||||
|
} /* end for each line loop */
|
||||||
|
write_bits_c(const_cast<char*>("000000000001000000000001"));
|
||||||
|
compressed->length_in_bytes = flush_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::make_array_of_changing_elements(parameters * params, uncompressed_descriptor * uncompressed, SHORT line_number)
|
||||||
|
{
|
||||||
|
SHORT bytes_per_line;
|
||||||
|
int line_offset;
|
||||||
|
SHORT byte_offset;
|
||||||
|
|
||||||
|
bytes_per_line = params->max_pixel / Pixels_per_byte;
|
||||||
|
line_offset = bytes_per_line * line_number;
|
||||||
|
for (byte_offset = 0; byte_offset < bytes_per_line; byte_offset++)
|
||||||
|
{
|
||||||
|
process_char(*(uncompressed->data + line_offset + byte_offset), params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::set_up_first_and_last_changing_elements_c(parameters * params)
|
||||||
|
{
|
||||||
|
*(params->coding_line) = Invalid;
|
||||||
|
*(params->coding_line + ++params->index) = params->max_pixel;
|
||||||
|
*(params->coding_line + ++params->index) = params->max_pixel;
|
||||||
|
*(params->coding_line + ++params->index) = params->max_pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::prepare_to_compress_next_line(parameters * params)
|
||||||
|
{
|
||||||
|
SHORT *temp;
|
||||||
|
|
||||||
|
/* swap the reference and unchanged coding lines */
|
||||||
|
|
||||||
|
temp = params->reference_line;
|
||||||
|
params->reference_line = params->coding_line;
|
||||||
|
params->coding_line = temp;
|
||||||
|
|
||||||
|
params->pixel = 0;
|
||||||
|
params->index = 0;
|
||||||
|
params->previous_color = White;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::set_up_first_line_c(parameters * params)
|
||||||
|
{
|
||||||
|
params->reference_line =
|
||||||
|
(SHORT *)malloc((params->max_pixel + Extra_positions) * sizeof(SHORT));
|
||||||
|
params->coding_line =
|
||||||
|
(SHORT *)malloc((params->max_pixel + Extra_positions) * sizeof(SHORT));
|
||||||
|
|
||||||
|
*(params->reference_line + 0) = Invalid;
|
||||||
|
*(params->reference_line + 1) = params->max_pixel;
|
||||||
|
*(params->reference_line + 2) = params->max_pixel;
|
||||||
|
*(params->reference_line + 3) = params->max_pixel;
|
||||||
|
|
||||||
|
/* initialize first changing element on coding line (A0 = -1) */
|
||||||
|
*(params->coding_line) = Invalid;
|
||||||
|
|
||||||
|
params->pixel = 0;
|
||||||
|
params->index = 0;
|
||||||
|
params->previous_color = White;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::compress_line(parameters * params)
|
||||||
|
{
|
||||||
|
#if Debug
|
||||||
|
static SHORT line = 0;
|
||||||
|
printf("\nLINE %d. ", line);
|
||||||
|
line++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
A_0 = Invalid; /* set A0 equal to imaginary first array element */
|
||||||
|
A0_color = White;
|
||||||
|
A_1 = 1;
|
||||||
|
initialize_b1(params);
|
||||||
|
b2 = b1 + 1;
|
||||||
|
|
||||||
|
#if Debug
|
||||||
|
printf("\nA0:%d A1:%d b1:%d b2:%d ",
|
||||||
|
A0, *(params->coding_line + A1),
|
||||||
|
*(params->reference_line + b1), *(params->reference_line + b2));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (*(params->reference_line + b2) < *(params->coding_line + A_1))
|
||||||
|
{
|
||||||
|
pass_mode_c(params);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (abs(*(params->coding_line + A_1) - *(params->reference_line + b1)) <= 3)
|
||||||
|
vertical_mode_c(params);
|
||||||
|
else
|
||||||
|
horizontal_mode_c(params);
|
||||||
|
#if Debug
|
||||||
|
printf("\nA0:%d A1:%d b1:%d b2:%d ", A0, *(params->coding_line + A1),
|
||||||
|
*(params->reference_line + b1), *(params->reference_line + b2));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} while (A_0 < params->max_pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::initialize_b1(parameters * params)
|
||||||
|
{
|
||||||
|
SHORT last_bit_of_b1;
|
||||||
|
|
||||||
|
b1 = 1;
|
||||||
|
last_bit_of_b1 = b1 & Last_bit_mask;
|
||||||
|
|
||||||
|
while (((*(params->reference_line + b1) <= A_0) || (A0_color == last_bit_of_b1))
|
||||||
|
&& (*(params->reference_line + b1) < params->max_pixel))
|
||||||
|
{
|
||||||
|
b1++;
|
||||||
|
last_bit_of_b1 = b1 & Last_bit_mask;
|
||||||
|
} /* end while loop */
|
||||||
|
|
||||||
|
#if Debug
|
||||||
|
printf("\nb1:%d :%d, A0:%d", b1, *(params->reference_line + b1), A0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::pass_mode_c(parameters * params)
|
||||||
|
{
|
||||||
|
write_bits_c(const_cast<char*>("0001"));
|
||||||
|
|
||||||
|
#if Debug
|
||||||
|
printf(" P ");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the value A0 points to to a'0 (the value that b2 points to).
|
||||||
|
*/
|
||||||
|
|
||||||
|
A_0 = *(params->reference_line + b2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since A0 is now greater than the pixel b1 points to, both b1 and b2
|
||||||
|
* must be advanced twice to maintain the color difference between A0 and
|
||||||
|
* b1, and the positional requirement that b1 point to a pixel greater than
|
||||||
|
* the one A0 points to.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b1 += 2;
|
||||||
|
b2 += 2;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that the b's can be advanced by two positions without fear of
|
||||||
|
* moving them beyond the last changing element because pass_mode cannot
|
||||||
|
* occur if b2 is already pointing to max_pixel.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::vertical_mode_c(parameters * params)
|
||||||
|
{
|
||||||
|
SHORT difference;
|
||||||
|
|
||||||
|
difference = *(params->coding_line + A_1) - *(params->reference_line + b1);
|
||||||
|
A_0 = *(params->coding_line + A_1);
|
||||||
|
A0_color = !A0_color;
|
||||||
|
A_1++;
|
||||||
|
|
||||||
|
#if Debug
|
||||||
|
printf(" V%d ", difference);
|
||||||
|
#endif
|
||||||
|
switch (difference) {
|
||||||
|
case 0:
|
||||||
|
write_bits_c(const_cast<char*>("1"));
|
||||||
|
if (*(params->reference_line + b1) != params->max_pixel)
|
||||||
|
{
|
||||||
|
b1++;
|
||||||
|
b2++;
|
||||||
|
} /* end if b1 is not on the last changing element */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
write_bits_c(const_cast<char*>("011"));
|
||||||
|
b1++;
|
||||||
|
b2++;
|
||||||
|
if ((*(params->reference_line + b1) <= A_0) &&
|
||||||
|
(*(params->reference_line + b1) != params->max_pixel))
|
||||||
|
{
|
||||||
|
b1 += 2;
|
||||||
|
b2 += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -1:
|
||||||
|
write_bits_c(const_cast<char*>("010"));
|
||||||
|
if (*(params->reference_line + b1) != params->max_pixel)
|
||||||
|
{
|
||||||
|
b1++;
|
||||||
|
b2++;
|
||||||
|
} /* end if b1 is not on the last changing element */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
write_bits_c(const_cast<char*>("000011"));
|
||||||
|
b1++;
|
||||||
|
b2++;
|
||||||
|
if ((*(params->reference_line + b1) <= A_0) &&
|
||||||
|
(*(params->reference_line + b1) != params->max_pixel))
|
||||||
|
{
|
||||||
|
b1 += 2;
|
||||||
|
b2 += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -2:
|
||||||
|
write_bits_c(const_cast<char*>("000010"));
|
||||||
|
if (*(params->reference_line + b1 - 1) > A_0)
|
||||||
|
{
|
||||||
|
b1--;
|
||||||
|
b2--;
|
||||||
|
}
|
||||||
|
else if (*(params->reference_line + b1) != params->max_pixel)
|
||||||
|
{
|
||||||
|
b1++;
|
||||||
|
b2++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
write_bits_c(const_cast<char*>("0000011"));
|
||||||
|
b1++;
|
||||||
|
b2++;
|
||||||
|
while ((*(params->reference_line + b1) <= A_0) &&
|
||||||
|
(*(params->reference_line + b1) != params->max_pixel))
|
||||||
|
{
|
||||||
|
b1 += 2;
|
||||||
|
b2 += 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -3:
|
||||||
|
write_bits_c(const_cast<char*>("0000010"));
|
||||||
|
if (*(params->reference_line + b1 - 1) > A_0)
|
||||||
|
{
|
||||||
|
b1--;
|
||||||
|
b2--;
|
||||||
|
}
|
||||||
|
else if (*(params->reference_line + b1) != params->max_pixel)
|
||||||
|
{
|
||||||
|
b1++;
|
||||||
|
b2++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("ERROR in vertical_mode_c() ");
|
||||||
|
|
||||||
|
} /* end case of difference */
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::horizontal_mode_c(parameters * params)
|
||||||
|
{
|
||||||
|
SHORT run_length;
|
||||||
|
|
||||||
|
#if Debug
|
||||||
|
printf(" a2:%d H ", *(params->coding_line + a2));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
a2 = A_1 + 1;
|
||||||
|
write_bits_c(const_cast<char*>("001"));
|
||||||
|
|
||||||
|
if (A_0 == Invalid) /* on imaginary first pixel */
|
||||||
|
run_length = *(params->coding_line + A_1);
|
||||||
|
else
|
||||||
|
run_length = *(params->coding_line + A_1) - A_0;
|
||||||
|
write_run_length(run_length, A0_color);
|
||||||
|
/* the last bit contains the color of the changing element */
|
||||||
|
|
||||||
|
run_length = *(params->coding_line + a2) - *(params->coding_line + A_1);
|
||||||
|
write_run_length(run_length, !A0_color);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must use !A0_color instead of A1 because in cases in which A1 occurs
|
||||||
|
* on max_pixel, its color is bogus.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* NOTE: is the above statement true? if A1 were on max_pixel, you should
|
||||||
|
not get horizontal mode. */
|
||||||
|
|
||||||
|
|
||||||
|
A_0 = *(params->coding_line + a2);
|
||||||
|
A_1 = a2 + 1;
|
||||||
|
|
||||||
|
while ((*(params->reference_line + b1) <= *(params->coding_line + a2)) &&
|
||||||
|
(*(params->reference_line + b1) < params->max_pixel))
|
||||||
|
{
|
||||||
|
b1 += 2; /* must move ahead by 2 to maintain color difference with */
|
||||||
|
b2 += 2; /* A0, whose color does not change in this mode. */
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::prepare_to_write_bits_c(compressed_descriptor * compressed)
|
||||||
|
{
|
||||||
|
if (comp_alloc_flag) {
|
||||||
|
compressed->data = (unsigned char*)calloc((compressed->pixels_per_line *
|
||||||
|
compressed->number_of_lines / Pixels_per_byte), sizeof(unsigned char));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* This allocation is usually very wasteful, but because there is no
|
||||||
|
* way of knowing how much space is needed, I decided to be generous.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (compressed->data == NULL) {
|
||||||
|
printf("\nMemory allocation error for compressed output data.\n");
|
||||||
|
//crash_c();
|
||||||
|
}
|
||||||
|
output_area = (char*)compressed->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::write_bits_c(char * string_ptr)
|
||||||
|
{
|
||||||
|
/* global switch added by Michael D. Garris 2/26/90 */
|
||||||
|
if (comp_write_init_flag)
|
||||||
|
{
|
||||||
|
bit_place_mark = 0;
|
||||||
|
byte_place_mark = 0;
|
||||||
|
comp_write_init_flag = 0;
|
||||||
|
}
|
||||||
|
while (*string_ptr != '\0')
|
||||||
|
{
|
||||||
|
if (*string_ptr == '1')
|
||||||
|
*(output_area + byte_place_mark) |= write_one[bit_place_mark];
|
||||||
|
else
|
||||||
|
*(output_area + byte_place_mark) &= write_zero[bit_place_mark];
|
||||||
|
if (bit_place_mark == Last_bit_in_a_byte)
|
||||||
|
{
|
||||||
|
bit_place_mark = 0;
|
||||||
|
byte_place_mark++;
|
||||||
|
} /* end if byte is full */
|
||||||
|
else
|
||||||
|
bit_place_mark++;
|
||||||
|
string_ptr++;
|
||||||
|
} /* end while */
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int TiffG4Compression::flush_buffer()
|
||||||
|
{
|
||||||
|
SHORT i;
|
||||||
|
|
||||||
|
if (bit_place_mark != 0) {
|
||||||
|
for (i = bit_place_mark; i < Pixels_per_byte; i++)
|
||||||
|
*(output_area + byte_place_mark) &= write_zero[i];
|
||||||
|
/*
|
||||||
|
* pad the rest of the last byte with '0' bits.
|
||||||
|
*/
|
||||||
|
++byte_place_mark;
|
||||||
|
}
|
||||||
|
return byte_place_mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::write_run_length(SHORT length, SHORT color)
|
||||||
|
{
|
||||||
|
SHORT multiples_of_largest_code, i,
|
||||||
|
make_up_code_index, remainder;
|
||||||
|
|
||||||
|
multiples_of_largest_code = length / Largest_code;
|
||||||
|
length %= Largest_code;
|
||||||
|
for (i = 0; i < multiples_of_largest_code; i++)
|
||||||
|
write_bits_c(const_cast<char*>(largest_colorless_code));
|
||||||
|
|
||||||
|
remainder = length % Size_of_make_up_code_increments;
|
||||||
|
|
||||||
|
/* remainder in the range 0 - 63 */
|
||||||
|
|
||||||
|
make_up_code_index = length / Size_of_make_up_code_increments;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make_up_code_index in the range 0 - 39, and represents a run length
|
||||||
|
* of 64 times its value (i.e. 0 - 2496). To translate this value into
|
||||||
|
* an index into the arrays that store the bit sequence that represents
|
||||||
|
* the appropriate run length, 1 must be subtracted from make_up_code_
|
||||||
|
* index. If this results in the value -1, no make up code should be
|
||||||
|
* written.
|
||||||
|
*/
|
||||||
|
|
||||||
|
make_up_code_index--;
|
||||||
|
|
||||||
|
if (make_up_code_index != Invalid) {
|
||||||
|
if (color == White)
|
||||||
|
write_bits_c(const_cast<char*>(white_make_up_code[make_up_code_index]));
|
||||||
|
else
|
||||||
|
write_bits_c(const_cast<char*>(black_make_up_code[make_up_code_index]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color == White)
|
||||||
|
write_bits_c(const_cast<char*>(white_terminating_code[remainder]));
|
||||||
|
else
|
||||||
|
write_bits_c(const_cast<char*>(black_terminating_code[remainder]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TiffG4Compression::process_char(unsigned char data_byte, parameters * params)
|
||||||
|
{
|
||||||
|
static char color = 0;
|
||||||
|
SHORT i = 0;
|
||||||
|
|
||||||
|
color = -(data_byte & Last_bit_mask);
|
||||||
|
data_byte ^= params->previous_color;
|
||||||
|
|
||||||
|
/* if the previous color is black - which is contrary to our assumptions -
|
||||||
|
* the bits in the byte must all be changed so that the result, when used
|
||||||
|
* as an index into the array 'bytes,' yields the correct result. In the
|
||||||
|
* above operation, if the previous color is black (11111111b), all bits
|
||||||
|
* are changed; if the previous color is white (00000000b), no bits are
|
||||||
|
* changed. */
|
||||||
|
|
||||||
|
while (table[data_byte].pixel[i] != Invalid)
|
||||||
|
*(params->coding_line + ++params->index) =
|
||||||
|
params->pixel + table[data_byte].pixel[i++];
|
||||||
|
|
||||||
|
params->pixel += Pixels_per_byte;
|
||||||
|
params->previous_color = color;
|
||||||
|
|
||||||
|
/* 'color' is a temporary holding place for the value of previous color */
|
||||||
|
}
|
|
@ -0,0 +1,668 @@
|
||||||
|
#pragma once
|
||||||
|
#define White 0
|
||||||
|
#define Black 1
|
||||||
|
#define Black_byte 255 // byte of all black bits: 11111111b
|
||||||
|
|
||||||
|
|
||||||
|
/* WARNING */
|
||||||
|
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||||
|
/* !!!!!!!!!!!!!!!!!! Change Here. Redeclaration of Type. !!!!!!!!!!!!!!!! */
|
||||||
|
#define SHORT int /* this type was just a regular old C "short". */
|
||||||
|
/* In images with > 2^15 rows the 2 byte definition */
|
||||||
|
/* gave garbage output because short overflowed. */
|
||||||
|
/* Increasing all variables from 2 to 4 bytes seems */
|
||||||
|
/* to fix it. I have used the macro SHORT here to show */
|
||||||
|
/* where this change applies, so that it can be undone */
|
||||||
|
/* if desired. Some variables of type "int" existed in */
|
||||||
|
/* the code before this change, and the SHORT macro */
|
||||||
|
/* allows reversal of just the correct ones. */
|
||||||
|
/* Patrick Grother Dec 9 1994 */
|
||||||
|
/* !!!!!!!!!!!!!!!!!! Change Here. Redeclaration of Type. !!!!!!!!!!!!!!!! */
|
||||||
|
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||||
|
|
||||||
|
|
||||||
|
#define Largest_code 2560
|
||||||
|
#define Size_of_make_up_code_increments 64
|
||||||
|
#define Max_terminating_length 63 /* longest terminating code*/
|
||||||
|
#define Number_of_different_bytes 256
|
||||||
|
|
||||||
|
#define Pixels_per_byte 8
|
||||||
|
#define Bits_per_byte 8
|
||||||
|
#define Last_bit_in_a_byte 7 /* assumes bits numbered from 0 - 7 */
|
||||||
|
#define Last_bit_mask 1 /* masks the last (low magnitude) bit */
|
||||||
|
#define Default_width_in_pixels 2560 /* default width of a scan line */
|
||||||
|
#define Default_number_of_lines 3300 /* default length of an image */
|
||||||
|
|
||||||
|
#define Invalid -1
|
||||||
|
#define Extra_positions 25 /* ensures extra room in allocations */
|
||||||
|
#define Not_done_yet 0
|
||||||
|
|
||||||
|
#define VL3 -3 /* Vertical Left 3 mode */
|
||||||
|
#define VL2 -2 /* Vertical Left 2 mode */
|
||||||
|
#define VL1 -1 /* Vertical Left 1 mode */
|
||||||
|
#define V0 0 /* Vertical mode */
|
||||||
|
#define VR1 1 /* Vertical Right 1 mode */
|
||||||
|
#define VR2 2 /* Vertical Right 2 mode */
|
||||||
|
#define VR3 3 /* Vertical Right 3 mode */
|
||||||
|
#define P 4 /* Pass mode */
|
||||||
|
#define H 5 /* Horizontal mode */
|
||||||
|
#define EOFB 6 /* End Of File Buffer */
|
||||||
|
|
||||||
|
#define No_offset 0 /* no offset during fseek() */
|
||||||
|
#define End_of_file 2 /* start at EOF during fseek() */
|
||||||
|
#define Start_of_file 0 /* start at SOF during fseek() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
unsigned char *calloc();
|
||||||
|
SHORT *malloc();
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct parameters {
|
||||||
|
SHORT previous_color; /* color of last run of pixels */
|
||||||
|
SHORT index; /* indicates current position in "coding_line" */
|
||||||
|
SHORT max_pixel; /* the number of pixels in a scan line */
|
||||||
|
SHORT pixel; /* pixel number of the last changing element */
|
||||||
|
SHORT *reference_line; /* array of changing elements on reference line */
|
||||||
|
SHORT *coding_line; /* array of changing elements on coding line */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct compressed_descriptor {
|
||||||
|
unsigned char *data; /* pointer to compressed image */
|
||||||
|
SHORT pixels_per_line; /* the number of pixels in a scan line */
|
||||||
|
SHORT number_of_lines; /* the number of scan lines in the image */
|
||||||
|
int length_in_bytes; /* length of the compressed image in bytes */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uncompressed_descriptor {
|
||||||
|
unsigned char *data; /* pointer to uncompressed image */
|
||||||
|
SHORT pixels_per_line; /* the number of pixels in a scan line */
|
||||||
|
SHORT number_of_lines; /* the number of scan lines in the image */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char write_one[Pixels_per_byte] =
|
||||||
|
{
|
||||||
|
(char)0x80,
|
||||||
|
(char)0x40,
|
||||||
|
(char)0x20,
|
||||||
|
(char)0x10,
|
||||||
|
(char)0x8,
|
||||||
|
(char)0x4,
|
||||||
|
(char)0x2,
|
||||||
|
(char)0x1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char write_zero[Pixels_per_byte] =
|
||||||
|
{
|
||||||
|
(char)0x7F,
|
||||||
|
(char)0xBF,
|
||||||
|
(char)0xDF,
|
||||||
|
(char)0xEF,
|
||||||
|
(char)0xF7,
|
||||||
|
(char)0xFB,
|
||||||
|
(char)0xFD,
|
||||||
|
(char)0xFE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *white_terminating_code[64] =
|
||||||
|
{
|
||||||
|
"00110101",
|
||||||
|
"000111",
|
||||||
|
"0111",
|
||||||
|
"1000",
|
||||||
|
"1011",
|
||||||
|
"1100",
|
||||||
|
"1110",
|
||||||
|
"1111",
|
||||||
|
"10011",
|
||||||
|
"10100",
|
||||||
|
"00111",
|
||||||
|
"01000",
|
||||||
|
"001000",
|
||||||
|
"000011",
|
||||||
|
"110100",
|
||||||
|
"110101",
|
||||||
|
"101010",
|
||||||
|
"101011",
|
||||||
|
"0100111",
|
||||||
|
"0001100",
|
||||||
|
"0001000",
|
||||||
|
"0010111",
|
||||||
|
"0000011",
|
||||||
|
"0000100",
|
||||||
|
"0101000",
|
||||||
|
"0101011",
|
||||||
|
"0010011",
|
||||||
|
"0100100",
|
||||||
|
"0011000",
|
||||||
|
"00000010",
|
||||||
|
"00000011",
|
||||||
|
"00011010",
|
||||||
|
"00011011",
|
||||||
|
"00010010",
|
||||||
|
"00010011",
|
||||||
|
"00010100",
|
||||||
|
"00010101",
|
||||||
|
"00010110",
|
||||||
|
"00010111",
|
||||||
|
"00101000",
|
||||||
|
"00101001",
|
||||||
|
"00101010",
|
||||||
|
"00101011",
|
||||||
|
"00101100",
|
||||||
|
"00101101",
|
||||||
|
"00000100",
|
||||||
|
"00000101",
|
||||||
|
"00001010",
|
||||||
|
"00001011",
|
||||||
|
"01010010",
|
||||||
|
"01010011",
|
||||||
|
"01010100",
|
||||||
|
"01010101",
|
||||||
|
"00100100",
|
||||||
|
"00100101",
|
||||||
|
"01011000",
|
||||||
|
"01011001",
|
||||||
|
"01011010",
|
||||||
|
"01011011",
|
||||||
|
"01001010",
|
||||||
|
"01001011",
|
||||||
|
"00110010",
|
||||||
|
"00110011",
|
||||||
|
"00110100",
|
||||||
|
};/* end array of white terminating code */
|
||||||
|
|
||||||
|
|
||||||
|
static const char *black_terminating_code[64] =
|
||||||
|
{
|
||||||
|
"0000110111",
|
||||||
|
"010",
|
||||||
|
"11",
|
||||||
|
"10",
|
||||||
|
"011",
|
||||||
|
"0011",
|
||||||
|
"0010",
|
||||||
|
"00011",
|
||||||
|
"000101",
|
||||||
|
"000100",
|
||||||
|
"0000100",
|
||||||
|
"0000101",
|
||||||
|
"0000111",
|
||||||
|
"00000100",
|
||||||
|
"00000111",
|
||||||
|
"000011000",
|
||||||
|
"0000010111",
|
||||||
|
"0000011000",
|
||||||
|
"0000001000",
|
||||||
|
"00001100111",
|
||||||
|
"00001101000",
|
||||||
|
"00001101100",
|
||||||
|
"00000110111",
|
||||||
|
"00000101000",
|
||||||
|
"00000010111",
|
||||||
|
"00000011000",
|
||||||
|
"000011001010",
|
||||||
|
"000011001011",
|
||||||
|
"000011001100",
|
||||||
|
"000011001101",
|
||||||
|
"000001101000",
|
||||||
|
"000001101001",
|
||||||
|
"000001101010",
|
||||||
|
"000001101011",
|
||||||
|
"000011010010",
|
||||||
|
"000011010011",
|
||||||
|
"000011010100",
|
||||||
|
"000011010101",
|
||||||
|
"000011010110",
|
||||||
|
"000011010111",
|
||||||
|
"000001101100",
|
||||||
|
"000001101101",
|
||||||
|
"000011011010",
|
||||||
|
"000011011011",
|
||||||
|
"000001010100",
|
||||||
|
"000001010101",
|
||||||
|
"000001010110",
|
||||||
|
"000001010111",
|
||||||
|
"000001100100",
|
||||||
|
"000001100101",
|
||||||
|
"000001010010",
|
||||||
|
"000001010011",
|
||||||
|
"000000100100",
|
||||||
|
"000000110111",
|
||||||
|
"000000111000",
|
||||||
|
"000000100111",
|
||||||
|
"000000101000",
|
||||||
|
"000001011000",
|
||||||
|
"000001011001",
|
||||||
|
"000000101011",
|
||||||
|
"000000101100",
|
||||||
|
"000001011010",
|
||||||
|
"000001100110",
|
||||||
|
"000001100111",
|
||||||
|
}; /* end black_terminating_array */
|
||||||
|
|
||||||
|
|
||||||
|
static const char *white_make_up_code[40] =
|
||||||
|
{
|
||||||
|
"11011",
|
||||||
|
"10010",
|
||||||
|
"010111",
|
||||||
|
"0110111",
|
||||||
|
"00110110",
|
||||||
|
"00110111",
|
||||||
|
"01100100",
|
||||||
|
"01100101",
|
||||||
|
"01101000",
|
||||||
|
"01100111",
|
||||||
|
"011001100",
|
||||||
|
"011001101",
|
||||||
|
"011010010",
|
||||||
|
"011010011",
|
||||||
|
"011010100",
|
||||||
|
"011010101",
|
||||||
|
"011010110",
|
||||||
|
"011010111",
|
||||||
|
"011011000",
|
||||||
|
"011011001",
|
||||||
|
"011011010",
|
||||||
|
"011011011",
|
||||||
|
"010011000",
|
||||||
|
"010011001",
|
||||||
|
"010011010",
|
||||||
|
"011000",
|
||||||
|
"010011011",
|
||||||
|
|
||||||
|
/*
|
||||||
|
* from this line on, the codes are colorless and represnt runs from
|
||||||
|
* 1792 pixels to 2560 pixels. In other words, the longest run length
|
||||||
|
* codes have been added onto both the white make up codes and the black
|
||||||
|
* make up codes. This has been done to make the procedure
|
||||||
|
* "write_run_length()" easier to write and to understand. No other
|
||||||
|
* procedure in the compression algorithm is affected by this merging of
|
||||||
|
* different types of run length codes, and the compatibility of the
|
||||||
|
* program is in no way effected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"00000001000",
|
||||||
|
"00000001100",
|
||||||
|
"00000001101",
|
||||||
|
"000000010010",
|
||||||
|
"000000010011",
|
||||||
|
"000000010100",
|
||||||
|
"000000010101",
|
||||||
|
"000000010110",
|
||||||
|
"000000010111",
|
||||||
|
"000000011100",
|
||||||
|
"000000011101",
|
||||||
|
"000000011110",
|
||||||
|
"000000011111",
|
||||||
|
}; /* end case of white makeup code */
|
||||||
|
|
||||||
|
|
||||||
|
static const char *black_make_up_code[40] =
|
||||||
|
{
|
||||||
|
"0000001111",
|
||||||
|
"000011001000",
|
||||||
|
"000011001001",
|
||||||
|
"000001011011",
|
||||||
|
"000000110011",
|
||||||
|
"000000110100",
|
||||||
|
"000000110101",
|
||||||
|
"0000001101100",
|
||||||
|
"0000001101101",
|
||||||
|
"0000001001010",
|
||||||
|
"0000001001011",
|
||||||
|
"0000001001100",
|
||||||
|
"0000001001101",
|
||||||
|
"0000001110010",
|
||||||
|
"0000001110011",
|
||||||
|
"0000001110100",
|
||||||
|
"0000001110101",
|
||||||
|
"0000001110110",
|
||||||
|
"0000001110111",
|
||||||
|
"0000001010010",
|
||||||
|
"0000001010011",
|
||||||
|
"0000001010100",
|
||||||
|
"0000001010101",
|
||||||
|
"0000001011010",
|
||||||
|
"0000001011011",
|
||||||
|
"0000001100100",
|
||||||
|
"0000001100101",
|
||||||
|
|
||||||
|
/*
|
||||||
|
* from this line on, the codes are colorless and represnt runs from
|
||||||
|
* 1792 pixels to 2560 pixels. In other words, the longest run length
|
||||||
|
* codes have been added onto both the white make up codes and the black
|
||||||
|
* make up codes. This has been done to make the procedure
|
||||||
|
* "write_run_length()" easier to write and to understand. No other
|
||||||
|
* procedure in the compression algorithm is affected by this merging of
|
||||||
|
* different types of run length codes, and the compatibility of the
|
||||||
|
* program is in no way compromised.
|
||||||
|
*/
|
||||||
|
|
||||||
|
"00000001000",
|
||||||
|
"00000001100",
|
||||||
|
"00000001101",
|
||||||
|
"000000010010",
|
||||||
|
"000000010011",
|
||||||
|
"000000010100",
|
||||||
|
"000000010101",
|
||||||
|
"000000010110",
|
||||||
|
"000000010111",
|
||||||
|
"000000011100",
|
||||||
|
"000000011101",
|
||||||
|
"000000011110",
|
||||||
|
"000000011111",
|
||||||
|
}; /* end black makeup code */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct byte_descriptor {
|
||||||
|
SHORT pixel[9];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const struct byte_descriptor table[Number_of_different_bytes] =
|
||||||
|
{
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
7, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
6, 7, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
6, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
5, 6, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
5, 6, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
5, 7, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
5, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
4, 5, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
4, 5, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
4, 5, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
4, 5, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
4, 6, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
4, 6, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
4, 7, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
4, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 4, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 4, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 4, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
3, 4, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 4, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
3, 4, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
3, 4, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
3, 4, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 5, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 5, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 5, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
3, 5, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 6, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 6, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, 7, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
3, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
2, 3, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 4, 5, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 4, 5, 7, -1, -1, -1, -1,
|
||||||
|
2, 3, 4, 5, 6, 7, -1, -1, -1,
|
||||||
|
2, 3, 4, 5, 6, -1, -1, -1, -1,
|
||||||
|
2, 3, 4, 6, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 4, 6, 7, -1, -1, -1, -1,
|
||||||
|
2, 3, 4, 7, -1, -1, -1, -1, -1,
|
||||||
|
2, 3, 4, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 4, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 4, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 4, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
2, 4, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 4, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
2, 4, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
2, 4, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
2, 4, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 5, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 5, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 5, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
2, 5, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 6, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 6, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, 7, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
2, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
1, 2, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 4, 5, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 4, 5, 7, -1, -1, -1, -1,
|
||||||
|
1, 2, 4, 5, 6, 7, -1, -1, -1,
|
||||||
|
1, 2, 4, 5, 6, -1, -1, -1, -1,
|
||||||
|
1, 2, 4, 6, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 4, 6, 7, -1, -1, -1, -1,
|
||||||
|
1, 2, 4, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 4, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 4, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 4, 7, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 4, 6, 7, -1, -1, -1,
|
||||||
|
1, 2, 3, 4, 6, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 4, 5, 6, -1, -1, -1,
|
||||||
|
1, 2, 3, 4, 5, 6, 7, -1, -1,
|
||||||
|
1, 2, 3, 4, 5, 7, -1, -1, -1,
|
||||||
|
1, 2, 3, 4, 5, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 5, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 5, 7, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 5, 6, 7, -1, -1, -1,
|
||||||
|
1, 2, 3, 5, 6, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 6, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 6, 7, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 2, 3, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
1, 3, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 4, 5, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 4, 5, 7, -1, -1, -1, -1,
|
||||||
|
1, 3, 4, 5, 6, 7, -1, -1, -1,
|
||||||
|
1, 3, 4, 5, 6, -1, -1, -1, -1,
|
||||||
|
1, 3, 4, 6, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 4, 6, 7, -1, -1, -1, -1,
|
||||||
|
1, 3, 4, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 3, 4, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 4, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 4, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 4, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 4, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 4, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
1, 4, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
1, 4, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 4, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 5, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 5, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 5, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
1, 5, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 6, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 6, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, 7, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 4, 5, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 4, 5, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 4, 5, 6, 7, -1, -1, -1,
|
||||||
|
0, 1, 4, 5, 6, -1, -1, -1, -1,
|
||||||
|
0, 1, 4, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 4, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 4, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 4, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 4, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 4, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 4, 6, 7, -1, -1, -1,
|
||||||
|
0, 1, 3, 4, 6, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 4, 5, 6, -1, -1, -1,
|
||||||
|
0, 1, 3, 4, 5, 6, 7, -1, -1,
|
||||||
|
0, 1, 3, 4, 5, 7, -1, -1, -1,
|
||||||
|
0, 1, 3, 4, 5, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 5, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 5, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 5, 6, 7, -1, -1, -1,
|
||||||
|
0, 1, 3, 5, 6, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 3, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 6, 7, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 6, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 5, 6, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 5, 6, 7, -1, -1,
|
||||||
|
0, 1, 2, 3, 5, 7, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 5, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 4, 5, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 4, 5, 7, -1, -1,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, -1,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, -1, -1,
|
||||||
|
0, 1, 2, 3, 4, 6, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 4, 6, 7, -1, -1,
|
||||||
|
0, 1, 2, 3, 4, 7, -1, -1, -1,
|
||||||
|
0, 1, 2, 3, 4, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 4, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 4, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 4, 6, 7, -1, -1, -1,
|
||||||
|
0, 1, 2, 4, 6, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 4, 5, 6, -1, -1, -1,
|
||||||
|
0, 1, 2, 4, 5, 6, 7, -1, -1,
|
||||||
|
0, 1, 2, 4, 5, 7, -1, -1, -1,
|
||||||
|
0, 1, 2, 4, 5, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 5, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 5, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 5, 6, 7, -1, -1, -1,
|
||||||
|
0, 1, 2, 5, 6, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 1, 2, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 2, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 4, 5, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 4, 5, 7, -1, -1, -1, -1,
|
||||||
|
0, 2, 4, 5, 6, 7, -1, -1, -1,
|
||||||
|
0, 2, 4, 5, 6, -1, -1, -1, -1,
|
||||||
|
0, 2, 4, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 4, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 2, 4, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 4, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 4, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 4, 7, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 4, 6, 7, -1, -1, -1,
|
||||||
|
0, 2, 3, 4, 6, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 4, 5, 6, -1, -1, -1,
|
||||||
|
0, 2, 3, 4, 5, 6, 7, -1, -1,
|
||||||
|
0, 2, 3, 4, 5, 7, -1, -1, -1,
|
||||||
|
0, 2, 3, 4, 5, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 5, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 5, 7, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 5, 6, 7, -1, -1, -1,
|
||||||
|
0, 2, 3, 5, 6, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 2, 3, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 3, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 4, 5, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 4, 5, 7, -1, -1, -1, -1,
|
||||||
|
0, 3, 4, 5, 6, 7, -1, -1, -1,
|
||||||
|
0, 3, 4, 5, 6, -1, -1, -1, -1,
|
||||||
|
0, 3, 4, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 4, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 3, 4, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 3, 4, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 4, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 4, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 4, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 4, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 4, 5, 6, -1, -1, -1, -1, -1,
|
||||||
|
0, 4, 5, 6, 7, -1, -1, -1, -1,
|
||||||
|
0, 4, 5, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 4, 5, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 5, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 5, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 5, 6, 7, -1, -1, -1, -1, -1,
|
||||||
|
0, 5, 6, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 6, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 6, 7, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, 7, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
0, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
}; /* end of data for list of byte descriptors */
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
#define NOALLOC 0
|
||||||
|
#define ALLOC 1
|
||||||
|
|
||||||
|
class TiffG4Compression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TiffG4Compression();
|
||||||
|
~TiffG4Compression();
|
||||||
|
public:
|
||||||
|
int G4Compress(unsigned char *indata, int inbytes, int width, int height, unsigned char *outdata, int *outbytes);
|
||||||
|
private:
|
||||||
|
void control_compression(struct uncompressed_descriptor *uncompressed, struct compressed_descriptor *compressed);
|
||||||
|
void read_uncompressed_file_into_memory(struct uncompressed_descriptor *uncompressed);
|
||||||
|
void prepare_to_compress(struct uncompressed_descriptor* uncompressed,struct compressed_descriptor* compressed,struct parameters* params);
|
||||||
|
void compress_image(struct uncompressed_descriptor* uncompressed, struct compressed_descriptor* compressed, struct parameters* params);
|
||||||
|
void make_array_of_changing_elements(struct parameters *params, struct uncompressed_descriptor* uncompressed, SHORT line_number);
|
||||||
|
void set_up_first_and_last_changing_elements_c(struct parameters *params);
|
||||||
|
void prepare_to_compress_next_line(struct parameters *params);
|
||||||
|
void set_up_first_line_c(struct parameters *params);
|
||||||
|
void compress_line(struct parameters *params);
|
||||||
|
void initialize_b1(struct parameters *params);
|
||||||
|
void pass_mode_c(struct parameters *params);
|
||||||
|
void vertical_mode_c(struct parameters *params);
|
||||||
|
void horizontal_mode_c(struct parameters *params);
|
||||||
|
void prepare_to_write_bits_c(struct compressed_descriptor *compressed);
|
||||||
|
void write_bits_c(char *string_ptr);
|
||||||
|
unsigned int flush_buffer();
|
||||||
|
void write_run_length(SHORT length, SHORT color);
|
||||||
|
void process_char(unsigned char data_byte, struct parameters *params);
|
||||||
|
private:
|
||||||
|
const char* largest_colorless_code =
|
||||||
|
{
|
||||||
|
"000000011111"
|
||||||
|
};
|
||||||
|
|
||||||
|
int comp_alloc_flag = ALLOC;
|
||||||
|
int comp_write_init_flag;
|
||||||
|
char *output_area=nullptr;
|
||||||
|
int bit_place_mark;
|
||||||
|
int byte_place_mark;
|
||||||
|
SHORT A_0, A0_color, A_1, a2, b1, b2;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* main program to drive CCITT Group 4 decompression
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "g4codec.h"
|
||||||
|
#include <memory.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define _BYTE_ASCII
|
||||||
|
|
||||||
|
#ifdef _BYTE_ASCII
|
||||||
|
#define _BYTE_ZERO 0x30
|
||||||
|
#define _BYTE_ONE 0x31
|
||||||
|
#else
|
||||||
|
#define _BYTE_ZERO 0x00 // _BYTE_BINARY
|
||||||
|
#define _BYTE_ONE 0x01 // _BYTE_BINARY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Program extracts a compressed image from the file pointer passed,
|
||||||
|
* stripping the file header and loads it into memory. It gets the
|
||||||
|
* dimensions of the resultant pixrect image from the compressed header
|
||||||
|
* and allocates the pixrect structure. It reverses the bits in the
|
||||||
|
* compressed image and calls decompress4() for decompression. The
|
||||||
|
* pixrect structure is used so the image can be displayed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int convertFromByte(char *inData, char *outData, int total, int width, int height)
|
||||||
|
{
|
||||||
|
int in, out, maxOut;
|
||||||
|
char outByte;
|
||||||
|
int inVal;
|
||||||
|
|
||||||
|
maxOut = width * height;
|
||||||
|
outByte = 0;
|
||||||
|
out = 0;
|
||||||
|
for (in=0; in<total, out<maxOut; in++)
|
||||||
|
{
|
||||||
|
inVal = inData[in];
|
||||||
|
switch(inVal)
|
||||||
|
{
|
||||||
|
case _BYTE_ZERO: // 0
|
||||||
|
outByte = outByte<<1;
|
||||||
|
out ++;
|
||||||
|
if ((out % 8) == 0)
|
||||||
|
{
|
||||||
|
outData[(out/8)-1] = outByte;
|
||||||
|
outByte = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case _BYTE_ONE: // 1
|
||||||
|
outByte = (outByte<<1) + 1;
|
||||||
|
out ++;
|
||||||
|
if ((out % 8) == 0)
|
||||||
|
{
|
||||||
|
outData[(out/8)-1] = outByte;
|
||||||
|
outByte = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // don't care
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((out % 8) != 0)
|
||||||
|
{
|
||||||
|
outData[out/8] = outByte; // flush
|
||||||
|
return (out/8+1);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
return (out/8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
u_char *source; /* Pointer to compressed image in memory */
|
||||||
|
u_char *destination; /* Pointer to decompressed raster in memory */
|
||||||
|
char *infile; /* Pointer to compressed name (argv[1]) */
|
||||||
|
char *outfile; /* Pointer to uncompressed name (argv[2]) */
|
||||||
|
FILE *input; /* Compressed file pointer */
|
||||||
|
FILE *output; /* Decompressed file pointer */
|
||||||
|
int height; /* Raster image height in pixels */
|
||||||
|
int width; /* Raster image width in pixels */
|
||||||
|
u_int filesize; /* Size of compressed image in bytes */
|
||||||
|
int outbytes; /* Output length */
|
||||||
|
int iCodec;
|
||||||
|
|
||||||
|
if(argc < 6)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s codec(0/1/2) srcFile destFile width height\n",
|
||||||
|
argv[0]);
|
||||||
|
fprintf(stderr, "Flag: 0 decode, 1 compress 1BPP, 2 compress 8BPP\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
iCodec = atoi(argv[1]); // 0 for decode, 1 for comp binary, 2 for comp byte
|
||||||
|
infile = argv[2];
|
||||||
|
outfile = argv[3];
|
||||||
|
width = atoi(argv[4]);
|
||||||
|
height = atoi(argv[5]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open input
|
||||||
|
*/
|
||||||
|
if ((input = fopen(infile,"rb")) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"%s: Can't open %s\n",argv[0], infile);
|
||||||
|
exit(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open output
|
||||||
|
*/
|
||||||
|
if ((output = fopen(outfile,"wb")) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: Can't open %s\n", argv[0], outfile);
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find out input size
|
||||||
|
|
||||||
|
if (iCodec == 1) // encoding binary, file can be larger than image
|
||||||
|
{
|
||||||
|
filesize = width*height/8;
|
||||||
|
if ((width*height%8) != 0)
|
||||||
|
filesize ++;
|
||||||
|
} else
|
||||||
|
{ // in other case we don't know the real size of input
|
||||||
|
filesize = _lseek(_fileno(input), 0L, SEEK_END); // seek to EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (source = (u_char *) malloc(filesize)) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: Can't malloc %d bytes for %s.\n",
|
||||||
|
argv[0], filesize,infile);
|
||||||
|
exit(-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
_lseek(_fileno(input), 62L, SEEK_SET); // seek to Beginning of file
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read input image
|
||||||
|
*/
|
||||||
|
if (fread(source, 1, filesize, input) != filesize)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: Error reading compressed file.\n", argv[0]);
|
||||||
|
exit(-6);
|
||||||
|
}
|
||||||
|
fclose(input);
|
||||||
|
// maximum size of destination, assuming binary image
|
||||||
|
destination = (u_char *) malloc(2*width*height/8);
|
||||||
|
if ( destination == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: Destination_create failed.\n",argv[0]);
|
||||||
|
exit(-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// special treatment to covert from byte per pixel to bit per pixel
|
||||||
|
if (iCodec == 2)
|
||||||
|
{
|
||||||
|
outbytes = convertFromByte(source, destination, filesize, width, height);
|
||||||
|
if (outbytes != width*height/8)
|
||||||
|
exit (-7);
|
||||||
|
else // store the raw data back at the source
|
||||||
|
memcpy(source, destination, outbytes);
|
||||||
|
filesize = outbytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform codec
|
||||||
|
if (iCodec == 0)
|
||||||
|
{
|
||||||
|
grp4decomp(source,filesize, width,height, destination, &outbytes);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
grp4comp(source,filesize, width,height, destination, &outbytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the output as pbm for decoded image
|
||||||
|
if (iCodec == 0)
|
||||||
|
fprintf(output, "P4\n%d %d\n", width, height);
|
||||||
|
|
||||||
|
fwrite(destination, outbytes, 1, output);
|
||||||
|
fclose(output);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// g4codec.h
|
||||||
|
//
|
||||||
|
#ifndef _G4DECOC_H
|
||||||
|
#define _G4DECOC_H
|
||||||
|
|
||||||
|
#define White 0
|
||||||
|
#define Black 1
|
||||||
|
#define Black_byte 255 // byte of all black bits: 11111111b
|
||||||
|
|
||||||
|
//int grp4decomp(unsigned char *indata,
|
||||||
|
// int inbytes,
|
||||||
|
// int width,
|
||||||
|
// int height,
|
||||||
|
// unsigned char *outdata,
|
||||||
|
// int *outbytes);
|
||||||
|
|
||||||
|
int grp4comp(unsigned char *indata,
|
||||||
|
int inbytes,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
unsigned char *outdata,
|
||||||
|
int *outbytes);
|
||||||
|
|
||||||
|
#endif //#ifndef _G4DECOC_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,133 @@
|
||||||
|
/*********************************************************************/
|
||||||
|
/* grp4comp.h */
|
||||||
|
/* Originally compression.h */
|
||||||
|
/*********************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* WARNING */
|
||||||
|
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||||
|
/* !!!!!!!!!!!!!!!!!! Change Here. Redeclaration of Type. !!!!!!!!!!!!!!!! */
|
||||||
|
#define SHORT int /* this type was just a regular old C "short". */
|
||||||
|
/* In images with > 2^15 rows the 2 byte definition */
|
||||||
|
/* gave garbage output because short overflowed. */
|
||||||
|
/* Increasing all variables from 2 to 4 bytes seems */
|
||||||
|
/* to fix it. I have used the macro SHORT here to show */
|
||||||
|
/* where this change applies, so that it can be undone */
|
||||||
|
/* if desired. Some variables of type "int" existed in */
|
||||||
|
/* the code before this change, and the SHORT macro */
|
||||||
|
/* allows reversal of just the correct ones. */
|
||||||
|
/* Patrick Grother Dec 9 1994 */
|
||||||
|
/* !!!!!!!!!!!!!!!!!! Change Here. Redeclaration of Type. !!!!!!!!!!!!!!!! */
|
||||||
|
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||||
|
|
||||||
|
|
||||||
|
#define Largest_code 2560
|
||||||
|
#define Size_of_make_up_code_increments 64
|
||||||
|
#define Max_terminating_length 63 /* longest terminating code*/
|
||||||
|
#define Number_of_different_bytes 256
|
||||||
|
|
||||||
|
#define Pixels_per_byte 8
|
||||||
|
#define Bits_per_byte 8
|
||||||
|
#define Last_bit_in_a_byte 7 /* assumes bits numbered from 0 - 7 */
|
||||||
|
#define Last_bit_mask 1 /* masks the last (low magnitude) bit */
|
||||||
|
#define Default_width_in_pixels 2560 /* default width of a scan line */
|
||||||
|
#define Default_number_of_lines 3300 /* default length of an image */
|
||||||
|
|
||||||
|
#define Invalid -1
|
||||||
|
#define None 0
|
||||||
|
#define Extra_positions 25 /* ensures extra room in allocations */
|
||||||
|
#define Not_done_yet 0
|
||||||
|
|
||||||
|
#define VL3 -3 /* Vertical Left 3 mode */
|
||||||
|
#define VL2 -2 /* Vertical Left 2 mode */
|
||||||
|
#define VL1 -1 /* Vertical Left 1 mode */
|
||||||
|
#define V0 0 /* Vertical mode */
|
||||||
|
#define VR1 1 /* Vertical Right 1 mode */
|
||||||
|
#define VR2 2 /* Vertical Right 2 mode */
|
||||||
|
#define VR3 3 /* Vertical Right 3 mode */
|
||||||
|
#define P 4 /* Pass mode */
|
||||||
|
#define H 5 /* Horizontal mode */
|
||||||
|
#define EOFB 6 /* End Of File Buffer */
|
||||||
|
|
||||||
|
#define No_offset 0 /* no offset during fseek() */
|
||||||
|
#define End_of_file 2 /* start at EOF during fseek() */
|
||||||
|
#define Start_of_file 0 /* start at SOF during fseek() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
unsigned char *calloc();
|
||||||
|
SHORT *malloc();
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct parameters {
|
||||||
|
SHORT previous_color; /* color of last run of pixels */
|
||||||
|
SHORT index; /* indicates current position in "coding_line" */
|
||||||
|
SHORT max_pixel; /* the number of pixels in a scan line */
|
||||||
|
SHORT pixel; /* pixel number of the last changing element */
|
||||||
|
SHORT *reference_line; /* array of changing elements on reference line */
|
||||||
|
SHORT *coding_line; /* array of changing elements on coding line */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct compressed_descriptor {
|
||||||
|
unsigned char *data; /* pointer to compressed image */
|
||||||
|
SHORT pixels_per_line; /* the number of pixels in a scan line */
|
||||||
|
SHORT number_of_lines; /* the number of scan lines in the image */
|
||||||
|
int length_in_bytes; /* length of the compressed image in bytes */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uncompressed_descriptor {
|
||||||
|
unsigned char *data; /* pointer to uncompressed image */
|
||||||
|
SHORT pixels_per_line; /* the number of pixels in a scan line */
|
||||||
|
SHORT number_of_lines; /* the number of scan lines in the image */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
|
||||||
|
declarations of all the procedures in the group4 compression routines
|
||||||
|
follow. The names of the files that contain the procedures are enclosed
|
||||||
|
in comments above the declarations.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* compress.c */
|
||||||
|
void control_compression();
|
||||||
|
struct uncompressed_descriptor process_arguments();
|
||||||
|
void set_up_first_and_last_changing_elements_c();
|
||||||
|
void set_up_first_and_last_changing_elements_d();
|
||||||
|
void read_uncompressed_file_into_memory();
|
||||||
|
void write_compressed_data_into_a_file();
|
||||||
|
void prepare_to_compress();
|
||||||
|
void compress_image();
|
||||||
|
void make_array_of_changing_elements();
|
||||||
|
void prepare_to_compress_next_line();
|
||||||
|
void set_up_first_line_c();
|
||||||
|
void set_up_first_line_d();
|
||||||
|
void crash_c();
|
||||||
|
|
||||||
|
/* table.c */
|
||||||
|
void process_char();
|
||||||
|
|
||||||
|
|
||||||
|
/* mode.c */
|
||||||
|
void compress_line();
|
||||||
|
void initialize_b1();
|
||||||
|
void pass_mode_c();
|
||||||
|
void pass_mode_d();
|
||||||
|
void vertical_mode_c();
|
||||||
|
void vertical_mode_d();
|
||||||
|
void horizontal_mode_c();
|
||||||
|
void horizontal_mode_d();
|
||||||
|
|
||||||
|
|
||||||
|
/* write_run.c */
|
||||||
|
void write_run_length();
|
||||||
|
|
||||||
|
|
||||||
|
/* write_bits.c */
|
||||||
|
void prepare_to_write_bits_c();
|
||||||
|
void prepare_to_write_bits_d();
|
||||||
|
void write_bits_c();
|
||||||
|
void write_bits_d();
|
||||||
|
unsigned int flush_buffer();
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,118 @@
|
||||||
|
/*********************************************************************/
|
||||||
|
/* grp4decomp.h */
|
||||||
|
/* Originally decompression.h */
|
||||||
|
/*********************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define SHORT int
|
||||||
|
/*
|
||||||
|
#define True 1
|
||||||
|
#define False 0
|
||||||
|
#define Debug True // False
|
||||||
|
|
||||||
|
#define White 0
|
||||||
|
#define Black 1
|
||||||
|
#define Black_byte 255 // byte of all black bits: 11111111b
|
||||||
|
*/
|
||||||
|
#define Max_terminating_length 63 /* longest terminating code*/
|
||||||
|
|
||||||
|
#define Pixels_per_byte 8
|
||||||
|
#define Bits_per_byte 8
|
||||||
|
#define Last_bit_in_a_byte 7 /* assumes bits numbered from 0 - 7 */
|
||||||
|
#define Last_bit_mask 1 /* masks the last (low magnitude) bit */
|
||||||
|
#define Default_width_in_pixels 1728 /* default width of a scan line */
|
||||||
|
#define Default_number_of_lines 2200 /* default length of an image */
|
||||||
|
|
||||||
|
#define Invalid -1
|
||||||
|
#define None 0
|
||||||
|
#define Extra_positions 25 /* ensures extra room in allocations */
|
||||||
|
#define Not_done_yet 0
|
||||||
|
|
||||||
|
#define VL3 -3 /* Vertical Left 3 mode */
|
||||||
|
#define VL2 -2 /* Vertical Left 2 mode */
|
||||||
|
#define VL1 -1 /* Vertical Left 1 mode */
|
||||||
|
#define V0 0 /* Vertical mode */
|
||||||
|
#define VR1 1 /* Vertical Right 1 mode */
|
||||||
|
#define VR2 2 /* Vertical Right 2 mode */
|
||||||
|
#define VR3 3 /* Vertical Right 3 mode */
|
||||||
|
#define P 4 /* Pass mode */
|
||||||
|
#define H 5 /* Horizontal mode */
|
||||||
|
#define EOFB 6 /* End Of File Buffer */
|
||||||
|
|
||||||
|
#define No_offset 0 /* no offset during fseek() */
|
||||||
|
#define End_of_file 2 /* start at EOF during fseek() */
|
||||||
|
#define Start_of_file 0 /* start at BOF during fseek() */
|
||||||
|
|
||||||
|
/*
|
||||||
|
char *calloc();
|
||||||
|
SHORT *malloc();
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct parameters {
|
||||||
|
SHORT index; /* indicates current position in "coding_line" */
|
||||||
|
SHORT max_pixel; /* the number of pixels in a scan line */
|
||||||
|
SHORT *reference_line;/* array of changing elements on reference line */
|
||||||
|
SHORT *coding_line; /* array of changing elements on coding line */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct decompressed_descriptor {
|
||||||
|
char *data; /* pointer to decompressed image */
|
||||||
|
SHORT pixels_per_line; /* the number of pixels in a scan line */
|
||||||
|
SHORT number_of_lines; /* the number of scan lines in the image */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct compressed_descriptor {
|
||||||
|
char *data; /* pointer to compressed image */
|
||||||
|
SHORT pixels_per_line; /* the number of pixels in a scan line */
|
||||||
|
SHORT number_of_lines; /* the number of scan lines in the image */
|
||||||
|
int length_in_bytes; /* length of the compressed image in bytes */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
|
||||||
|
declarations of all the procedures in the group4 decompression routines
|
||||||
|
follow. The names of the files that contain the procedures are enclosed
|
||||||
|
in comments above the declarations.
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/* decompress.c */
|
||||||
|
void control_decompression();
|
||||||
|
struct compressed_descriptor process_arguments();
|
||||||
|
void read_compressed_file_into_memory();
|
||||||
|
void write_decompressed_data_into_a_file();
|
||||||
|
void prepare_to_decompress();
|
||||||
|
void set_up_first_line_c();
|
||||||
|
void set_up_first_line_d();
|
||||||
|
void set_up_first_and_last_changing_elements_c();
|
||||||
|
void set_up_first_and_last_changing_elements_d();
|
||||||
|
void prepare_to_decompress_next_line();
|
||||||
|
void swap_the_reference_and_coding_lines();
|
||||||
|
void crash_d();
|
||||||
|
|
||||||
|
|
||||||
|
/* decomp.c */
|
||||||
|
SHORT decompress_line();
|
||||||
|
SHORT get_mode();
|
||||||
|
void pass_mode_c();
|
||||||
|
void pass_mode_d();
|
||||||
|
void vertical_mode_c();
|
||||||
|
void vertical_mode_d();
|
||||||
|
void horizontal_mode_c();
|
||||||
|
void horizontal_mode_d();
|
||||||
|
|
||||||
|
|
||||||
|
/* read.c */
|
||||||
|
void prepare_to_read_bits();
|
||||||
|
SHORT read_bit();
|
||||||
|
|
||||||
|
|
||||||
|
/* write.c */
|
||||||
|
void prepare_to_write_bits_c();
|
||||||
|
void prepare_to_write_bits_d();
|
||||||
|
void write_bits_c();
|
||||||
|
void write_bits_d();
|
||||||
|
|
||||||
|
|
||||||
|
/* tree.c */
|
||||||
|
SHORT find_run_length_code();
|
Loading…
Reference in New Issue