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