Implemented Delta Row Compression.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10775 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
a6d74a56c6
commit
d647d0afe9
155
src/add-ons/print/drivers/pcl6/DeltaRowCompression.cpp
Normal file
155
src/add-ons/print/drivers/pcl6/DeltaRowCompression.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
** DeltaRowCompression.cpp
|
||||||
|
** Copyright 2005, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
|
||||||
|
** Distributed under the terms of the OpenBeOS License.
|
||||||
|
*/
|
||||||
|
#include "DeltaRowCompression.h"
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
AbstractDeltaRowCompressor::AbstractDeltaRowCompressor(int rowSize, uchar initialSeed)
|
||||||
|
: fSeedRow(new uchar[rowSize])
|
||||||
|
, fSize(rowSize)
|
||||||
|
, fInitialSeed(initialSeed)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractDeltaRowCompressor::~AbstractDeltaRowCompressor()
|
||||||
|
{
|
||||||
|
delete fSeedRow;
|
||||||
|
fSeedRow = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t AbstractDeltaRowCompressor::InitCheck()
|
||||||
|
{
|
||||||
|
if (fSeedRow != NULL) {
|
||||||
|
return B_OK;
|
||||||
|
} else {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractDeltaRowCompressor::Reset()
|
||||||
|
{
|
||||||
|
if (fSeedRow != NULL) {
|
||||||
|
memset(fSeedRow, fInitialSeed, fSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int AbstractDeltaRowCompressor::CompressRaw(const uchar* row, bool updateSeedRow, bool updateDeltaRow)
|
||||||
|
{
|
||||||
|
int index = DiffersIndex(row, 0);
|
||||||
|
if (index == -1) {
|
||||||
|
// no differences
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fUpdateDeltaRow = updateDeltaRow;
|
||||||
|
fDeltaRowIndex = 0;
|
||||||
|
|
||||||
|
int seedRowIndex = 0;
|
||||||
|
do {
|
||||||
|
int length = DiffersLength(row, index);
|
||||||
|
|
||||||
|
// delta starts at index and contains length bytes
|
||||||
|
do {
|
||||||
|
|
||||||
|
// control byte limits data bytes to 8 bytes
|
||||||
|
int deltaBytes = length;
|
||||||
|
if (length > 8) {
|
||||||
|
deltaBytes = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate offset
|
||||||
|
int totalOffset = index - seedRowIndex;
|
||||||
|
bool needsOffsetBytes = totalOffset > 30;
|
||||||
|
int offset = totalOffset;
|
||||||
|
// control byte limits offset value to 31
|
||||||
|
if (needsOffsetBytes) {
|
||||||
|
offset = 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write control byte (delta bytes bits 5-7; offset bits 0-4)
|
||||||
|
Put(((deltaBytes-1) << 5) | offset);
|
||||||
|
|
||||||
|
if (needsOffsetBytes) {
|
||||||
|
// write additional offset bytes after control byte
|
||||||
|
// the last offset byte must be less than 255
|
||||||
|
totalOffset -= offset;
|
||||||
|
while (totalOffset >= 255) {
|
||||||
|
Put(255);
|
||||||
|
totalOffset -= 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
Put(totalOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write data bytes
|
||||||
|
for (int i = 0; i < deltaBytes; i ++) {
|
||||||
|
// copy row to seed row and delta row
|
||||||
|
uchar byte = row[index];
|
||||||
|
if (updateSeedRow) {
|
||||||
|
ASSERT (index < fSize);
|
||||||
|
fSeedRow[index] = byte;
|
||||||
|
}
|
||||||
|
Put(byte);
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
seedRowIndex = index;
|
||||||
|
|
||||||
|
length -= deltaBytes;
|
||||||
|
|
||||||
|
} while (length > 0);
|
||||||
|
|
||||||
|
index = DiffersIndex(row, index);
|
||||||
|
|
||||||
|
} while (index != -1);
|
||||||
|
|
||||||
|
return fDeltaRowIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AbstractDeltaRowCompressor::CalculateSize(const uchar* row, bool updateSeedRow)
|
||||||
|
{
|
||||||
|
return CompressRaw(row, updateSeedRow, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractDeltaRowCompressor::Compress(const uchar* row)
|
||||||
|
{
|
||||||
|
CompressRaw(row, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TEST_DELTA_ROW_COMPRESSION
|
||||||
|
void test(AbstractDeltaRowCompressor* compressor, uchar* row) {
|
||||||
|
int size = compressor->CalculateSize(row);
|
||||||
|
printf("size %d\n", size);
|
||||||
|
|
||||||
|
if (size > 0) {
|
||||||
|
uchar* buffer = new uchar[size];
|
||||||
|
compressor->Compress(row, buffer, size);
|
||||||
|
for (int i = 0; i < size; i ++) {
|
||||||
|
printf("%2.2x ", (int)buffer[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
delete buffer;
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int n = 5;
|
||||||
|
uchar row1[] = {0, 0, 0, 0, 0};
|
||||||
|
uchar row2[] = {0, 1, 0, 0, 0};
|
||||||
|
uchar row3[] = {1, 1, 0, 2, 2};
|
||||||
|
|
||||||
|
DeltaRowCompressor compressor(n, 0);
|
||||||
|
test(&compressor, row1);
|
||||||
|
test(&compressor, row2);
|
||||||
|
test(&compressor, row3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
120
src/add-ons/print/drivers/pcl6/DeltaRowCompression.h
Normal file
120
src/add-ons/print/drivers/pcl6/DeltaRowCompression.h
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
** DeltaRowCompression.h
|
||||||
|
** Copyright 2005, Michael Pfeiffer, laplace@users.sourceforge.net. All rights reserved.
|
||||||
|
** Distributed under the terms of the OpenBeOS License.
|
||||||
|
*/
|
||||||
|
#ifndef _DELTA_ROW_COMPRESSION_H
|
||||||
|
#define _DELTA_ROW_COMPRESSION_H
|
||||||
|
|
||||||
|
#include <Debug.h>
|
||||||
|
|
||||||
|
class AbstractDeltaRowCompressor {
|
||||||
|
public:
|
||||||
|
AbstractDeltaRowCompressor(int rowSize, uchar initialSeed);
|
||||||
|
virtual ~AbstractDeltaRowCompressor();
|
||||||
|
|
||||||
|
// InitCheck returns B_OK on successful construction of this object or
|
||||||
|
// B_NO_MEMORY if the buffer for the seed row could not be allocated.
|
||||||
|
status_t InitCheck();
|
||||||
|
|
||||||
|
// Clears the seed row to the initial seed specified in the constructor
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
// Returns the size of the delta row.
|
||||||
|
// The size is 0 if the row is equal to the seed row (previous row).
|
||||||
|
// The seed row is updated only if updateSeedRow is true.
|
||||||
|
int CalculateSize(const uchar* row, bool updateSeedRow = false);
|
||||||
|
|
||||||
|
// Compresses the row using the delta row compression algorithm.
|
||||||
|
// The seed row is updated.
|
||||||
|
void Compress(const uchar* row);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// append byte to delta row
|
||||||
|
virtual void AppendByteToDeltaRow(uchar byte) = 0;
|
||||||
|
|
||||||
|
// returns the current size of the delta row
|
||||||
|
inline int CurrentDeltaRowSize() {
|
||||||
|
return fDeltaRowIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Returns the index where seed row and row differ
|
||||||
|
// or -1 if both arrays are equal.
|
||||||
|
inline int DiffersIndex(const uchar* row, int index)
|
||||||
|
{
|
||||||
|
while (index < fSize) {
|
||||||
|
if (fSeedRow[index] != row[index]) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the number of bytes that row differs from seed row
|
||||||
|
// starting at the specified index.
|
||||||
|
inline int DiffersLength(const uchar* row, int index)
|
||||||
|
{
|
||||||
|
int startIndex = index;
|
||||||
|
|
||||||
|
while (index < fSize) {
|
||||||
|
if (fSeedRow[index] == row[index]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
index ++;
|
||||||
|
}
|
||||||
|
return index - startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compresses row with delta row compression algorithm.
|
||||||
|
// The seed row is updated only if updateSeedRow is true.
|
||||||
|
// If updateDeltaRow is true the method AppendByteToDeltaRow is called.
|
||||||
|
int CompressRaw(const uchar* row, bool updateSeedRow, bool updateDeltaRow);
|
||||||
|
|
||||||
|
// write byte to delta row and calculate size of delta row
|
||||||
|
// If a client overrides this method and wants to calculate the
|
||||||
|
// size of the delta row the method must be called.
|
||||||
|
void Put(uchar byte) {
|
||||||
|
if (fUpdateDeltaRow) {
|
||||||
|
AppendByteToDeltaRow(byte);
|
||||||
|
}
|
||||||
|
fDeltaRowIndex ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar* fSeedRow; // the seed row
|
||||||
|
int fSize; // the size of the seed row in bytes
|
||||||
|
uchar fInitialSeed; // the value to initialize the seed row with
|
||||||
|
|
||||||
|
int fDeltaRowIndex; // the index of the next byte to be written into the delta row
|
||||||
|
bool fUpdateDeltaRow; // write delta row
|
||||||
|
};
|
||||||
|
|
||||||
|
class DeltaRowCompressor : public AbstractDeltaRowCompressor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DeltaRowCompressor(int rowSize, uchar initialSeed)
|
||||||
|
: AbstractDeltaRowCompressor(rowSize, initialSeed)
|
||||||
|
{
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
// The delta row to be written to.
|
||||||
|
void SetDeltaRow(uchar* deltaRow) {
|
||||||
|
fDeltaRow = deltaRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void AppendByteToDeltaRow(uchar byte) {
|
||||||
|
fDeltaRow[CurrentDeltaRowSize()] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uchar* fDeltaRow; // the delta row
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user