changing RGB pixel in bitmap C++ - c++

I am trying to write a function which will change all RGB(255,0,0) pixels to RGB(255,0,255) but it doesn't seem to work :D Could anyone tell me the reason why it doesn't work/show me the right way to do it. All criticism all appreciated.
Here is part of my code:
#include <stdio.h>
#include <Windows.h>
#include <stdint.h>
struct BmpSignature
{
unsigned char data[2];
};
#pragma pack(1)
struct BmpHeader
{
BmpSignature signature;
uint32_t fileSize;
uint16_t reserved1;
uint16_t reserved2;
uint32_t dataOffset;
};
struct BmpDib
{
uint32_t dibSize;
int32_t imageWidth;
int32_t imageHeight;
uint16_t colorPlaneCount;
uint16_t pixelSize;
uint32_t compressMethod;
uint32_t bitmapByteCount;
int32_t horizontalResolution;
int32_t verticalResolution;
uint32_t colorCount;
uint32_t importantColorCount;
};
struct Color
{
unsigned char blue;
unsigned char green;
unsigned char red;
};
struct PixelArray
{
Color **pixels;
uint32_t rowCount;
uint32_t columnCount;
};
void changeBmp(PixelArray &p)
{
for (int i = 0; i < p.rowCount; i++)
for (int j = 0; j < p.columnCount; j++)
{
if (p.pixels[i][j].red == 255 && p.pixels[i][j].green == 0 && p.pixels[i][j].blue == 0)
{
p.pixels[i][j].blue = 255;
}
}
}
void readBmpPixelArray(FILE *f, BmpHeader header, BmpDib dib, PixelArray &data)
{
if (f == NULL)
return;
data.rowCount = dib.imageHeight;
data.columnCount = dib.imageWidth;
data.pixels = new Color*[data.rowCount];
char paddingCount = (4 - (dib.imageWidth * (dib.pixelSize / 8) % 4)) % 4;
fseek(f, header.dataOffset, 0L);
for (int i = 0; i < data.rowCount; i++)
{
scanBmpPixelLine(f, data.pixels[data.rowCount - i - 1], dib.imageWidth);
skipBmpPadding(f, paddingCount);
}
}
void writeBmpPixelArray(FILE *f, BmpHeader header, BmpDib dib, PixelArray &data)
{
if (f == NULL)
return;
data.rowCount = dib.imageHeight;
data.columnCount = dib.imageWidth;
char paddingCount = (4 - (dib.imageWidth * (dib.pixelSize / 8) % 4)) % 4;
fseek(f, header.dataOffset, 0L);
for (int i = 0; i < data.rowCount; i++)
{
writeBmpPixelLine(f, data.pixels[data.rowCount - i - 1], dib.imageWidth);
addBmpPadding(f, paddingCount);
}
}
void writeBmpPixelLine(FILE *f, Color *&line, uint32_t length)
{
if (f == NULL)
return;
fwrite(line, sizeof(Color), length, f);
}
void scanBmpPixelLine(FILE *f, Color *&line, uint32_t length)
{
if (f == NULL)
return;
line = new Color[length];
fread(line, sizeof(Color), length, f);
}
void addBmpPadding(FILE *f, char count)
{
if (f == NULL)
return;
if (count == 0)
return;
char padding[3];
fwrite(padding, count, 1, f);
}
void skipBmpPadding(FILE *f, char count)
{
if (f == NULL)
return;
if (count == 0)
return;
char padding[3];
fread(padding, count, 1, f);
}
void drawBmp(BmpDib dib, PixelArray data)
{
HWND console = GetConsoleWindow();
HDC hdc = GetDC(console);
for (int i = 0; i < dib.imageHeight; i++)
for (int j = 0; j < dib.imageWidth; j++)
{
Color pixel = data.pixels[i][j];
SetPixel(hdc, j, i, RGB(pixel.red, pixel.green, pixel.blue));
}
ReleaseDC(console, hdc);
}
void releaseBmpPixelArray(PixelArray data)
{
for (int i = 0; i < data.rowCount; i++)
delete[]data.pixels[i];
delete[]data.pixels;
}
int main()
{
BmpHeader header;
BmpDib info;
PixelArray data;
FILE * inputBMP;
inputBMP = fopen("D:\\Projects\\bitmap\\yoyo.bmp", "rb");
readBmpHeader(inputBMP, header);
printBmpHeader(header);
readBmpDib(inputBMP, info);
printBmpDib(info);
readBmpPixelArray(inputBMP, header, info, data);
HWND console = GetConsoleWindow();
if (console != NULL){ MoveWindow(console, 0, 0, 800, 600, TRUE); }
changeBmp(data);
drawBmp(info, data);
releaseBmpPixelArray(data);
fclose(inputBMP);
Sleep(100);
return 0;
}

Related

Invalid output for a custom print function when incorporating newline characters within a string for a kernel project

I'm in the process of working on a kernel program to handle printing capabilities of input for a custom OS. I'm following Poncho's 2nd YouTube Video series found here, I'm currently on Video 4 in the series where he starts to add numerical types as inputs to the renderer's print function. Now, my code isn't exactly like his as I made some modifications.
-Note- This won't compile directly as there is no main function. _start is being called or invoked by a bootloader that isn't shown here, I will however, add it to the bottom of this question.
When I use the class's print function like this within my kernel:
#include "BasicRenderer.h"
extern "C" void _start(Framebuffer* framebuffer, PSF1_FONT** fonts) {
BasicRenderer = renderer(framebuffer, fonts);
renderer.Print("This is some text");
renderer.Print('\n');
renderer.Print(uint64_t(123456789));
renderer.Print('\n');
renderer.Print(int64_t(-123456789));
return;
}
And I run the kernel in emu. I'm getting the following output displayed:
This is some text
123456789
-123456789
The above is correct, however, when I try to incorporate the ability to parse a newline set of characters being either \n or \0 within of a const char* that acts as a string as seen in the following example:
#include "BasicRenderer.h"
extern "C" void _start(Framebuffer* framebuffer, PSF1_FONT** fonts) {
BasicRenderer = renderer(framebuffer, fonts);
renderer.Print("This is some text\n");
renderer.Print(uint64_t(123456789));
renderer.Print('\n');
renderer.Print(int64_t(-123456789));
return;
}
And now the displayed output is:
This is some text
123456789
-123456789
Here, the output in the second line has a space preceding the numerical value to be displayed after the call to Print() that has a \n within its string. I'm not sure what is causing this in my code. Does it have to do with the while condition or how I'm incrementing and indexing into the character string within BasicRenderer::Print(const char* str)? Or is it coming from BasicRender::PutChar(char c)? Or is it within one of the to_string() functions?
Here is the relevant implementation code...
BasicRenderer.cpp
#include "BasicRenderer.h"
void BasicRenderer::Print(const char* str) {
char* chr = (char*)str;
while(*chr != 0) {
if ( (*chr == '\\') && ((*chr+1 == 'n') || (*chr+1 == '0')) ) {
PutChar('\n');
chr++;
chr++;
} else {
PutChar(*chr);
cursor_position_.x += 8;
if (cursor_position_.x + 8 > framebuffer_->Width) {
cursor_position_.x = 0;
cursor_position_.y += 16;
}
chr++;
}
}
}
void BasicRenderer::Print(uint64_t val) {
const char* str = to_string(val);
Print(str);
}
void BasicRenderer::Print(int64_t val) {
const char* str = to_string(val);
Print(str);
}
void BasicRenderer::PutChar(char c) {
if (c == '\n' || c == '\0') {
cursor_position_.x = 0;
cursor_position_.y += 16;
} else {
unsigned int* pixPtr = (unsigned int*)framebuffer_->BaseAddress;
char* fontPtr = (char*)selected_font_->glyphBuffer + (c * selected_font_->psf1_Header->charsize);
for (unsigned long y = cursor_position_.y; y < cursor_position_.y + 16; y++) {
for (unsigned long x = cursor_position_.x; x < cursor_position_.x + 8; x++) {
if ((*fontPtr & (0b10000000 >> (x - cursor_position_.x))) > 0) {
*(unsigned int*)(pixPtr + x + (y * framebuffer_->PixelsPerScanLine)) = font_color_;
}
}
fontPtr++;
}
}
}
cstr.cpp
#include "cstr.h"
const char* to_string(uint64_t value) {
static char output_uint_buffer[128];
uint8_t size = 0;
uint64_t sizeTest = value;
while (sizeTest / 10 > 0) {
sizeTest /= 10;
size++;
}
uint8_t idx = 0;
while (value / 10 > 0) {
uint8_t remainder = value % 10;
value /= 10;
output_uint_buffer[size - idx] = remainder + '0';
idx++;
}
uint8_t remainder = value % 10;
output_uint_buffer[size-idx] = remainder + '0';
output_uint_buffer[size + 1] = 0;
return output_uint_buffer;
}
const char* to_string(int64_t value) {
static char output_int_buffer[128];
uint8_t isNegative = 0;
if (value < 0) {
isNegative = 1;
value *= -1;
output_int_buffer[0] = '-';
}
uint8_t size = 0;
uint64_t sizeTest = value;
while (sizeTest / 10 > 0) {
sizeTest /= 10;
size++;
}
uint8_t idx = 0;
while (value / 10 > 0) {
uint8_t remainder = value % 10;
value /= 10;
output_int_buffer[isNegative + size - idx] = remainder + '0';
idx++;
}
uint8_t remainder = value % 10;
output_int_buffer[isNegative + size - idx] = remainder + '0';
output_int_buffer[isNegative + size + 1] = 0;
return output_int_buffer;
}
And here is the rest of the declarations...
BasicRender.h
#pragma once
#include "cstr.h"
#include "math.h"
#include "framebuffer.h"
#include "SimpleFonts.h"
class BasicRenderer {
public:
BasicRenderer(Framebuffer* framebuffer, PSF1_FONT** fonts) :
framebuffer_{framebuffer},
fonts_{fonts},
cursor_position_({0,0}),
selected_font_{fonts_[0]},
font_color_{0xFFFFFFFF}
{}
void Print(const char* str);
void Print(char c) { PutChar(c); }
void Print(uint64_t val);
void Print(int64_t val);
private:
void PutChar(char c);
Framebuffer* framebuffer_;
Point cursor_position_;
PSF1_FONT** fonts_;
PSF1_FONT* selected_font_;
unsigned int font_color_;
};
cstr.h
#pragma once
#include <stdint.h>
const char* to_string(uint64_t value);
const char* to_string(int64_t value);
math.h
#pragma once
struct Point {
unsigned int x;
unsigned int y;
};
Framebuffer.h
#pragma once
#include <stddef.h>
struct Framebuffer {
void* BaseAddress;
size_t BufferSize;
unsigned int Width;
unsigned int Height;
unsigned int PixelsPerScanLine;
};
SimpleFonts.h
#pragma once
struct PSF1_HEADER {
unsigned char magic[2];
unsigned char mode;
unsigned char charsize;
};
struct PSF1_FONT {
PSF1_HEADER* psf1_Header;
void* glyphBuffer;
};
Here is the bootloader application that invokes the above kernel.
main.c
#include <efi.h>
#include <efilib.h>
#include <elf.h>
#define PSF1_MAGIC0 0x36
#define PSF1_MAGIC1 0x04
typedef unsigned long long size_t;
typedef struct {
unsigned char magic[2];
unsigned char mode;
unsigned char charsize;
} PSF1_HEADER;
typedef struct {
PSF1_HEADER* psf1_Header;
void* glyphBuffer;
} PSF1_FONT;
typedef struct {
void* BaseAddress;
size_t BufferSize;
unsigned int Width;
unsigned int Height;
unsigned int PixelsPerScanLine;
} Framebuffer; Framebuffer framebuffer;
Framebuffer* InitializeGOP() {
EFI_GUID gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
EFI_STATUS status;
status = uefi_call_wrapper(BS->LocateProtocol, 3, &gopGuid, NULL, (void**)&gop);
if (EFI_ERROR(status)) {
Print(L"Unable to locate GOP\n\r");
return NULL;
} else {
Print(L"GOP located\n\r");
}
framebuffer.BaseAddress = (void*)gop->Mode->FrameBufferBase;
framebuffer.BufferSize = gop->Mode->FrameBufferSize;
framebuffer.Width = gop->Mode->Info->HorizontalResolution;
framebuffer.Height = gop->Mode->Info->VerticalResolution;
framebuffer.PixelsPerScanLine = gop->Mode->Info->PixelsPerScanLine;
return &framebuffer;
}
EFI_FILE* LoadFile(EFI_FILE* Directory, CHAR16* Path, EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
EFI_FILE* LoadedFile;
EFI_LOADED_IMAGE_PROTOCOL* LoadedImage;
SystemTable->BootServices->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (void**)&LoadedImage);
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* FileSystem;
SystemTable->BootServices->HandleProtocol(LoadedImage->DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (void**)&FileSystem);
if (Directory == NULL) {
FileSystem->OpenVolume(FileSystem, &Directory);
}
EFI_STATUS s = Directory->Open(Directory, &LoadedFile, Path, EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY);
if (s != EFI_SUCCESS) {
return NULL;
}
return LoadedFile;
}
PSF1_FONT* LoadPSF1Font(EFI_FILE* Directory, CHAR16* Path, EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
EFI_FILE* font = LoadFile(Directory, Path, ImageHandle, SystemTable);
if (font == NULL) return NULL;
PSF1_HEADER* fontHeader;
SystemTable->BootServices->AllocatePool(EfiLoaderData, sizeof(PSF1_HEADER), (void**)&fontHeader);
UINTN size = sizeof(PSF1_HEADER);
font->Read(font, &size, fontHeader);
if (fontHeader->magic[0] != PSF1_MAGIC0 || fontHeader->magic[1] != PSF1_MAGIC1) return NULL;
UINTN glyphBufferSize = fontHeader->charsize * 256;
if (fontHeader->mode == 1) { // 512 glyph mode
glyphBufferSize *= 2;
}
void* glyphBuffer;
font->SetPosition(font, sizeof(PSF1_HEADER));
SystemTable->BootServices->AllocatePool(EfiLoaderData, glyphBufferSize, (void**)&glyphBuffer);
font->Read(font, &glyphBufferSize, glyphBuffer);
PSF1_FONT* finishedFont;
SystemTable->BootServices->AllocatePool(EfiLoaderData, sizeof(PSF1_FONT), (void**)&finishedFont);
finishedFont->psf1_Header = fontHeader;
finishedFont->glyphBuffer = glyphBuffer;
return finishedFont;
}
int memcmp(const void* aptr, const void* bptr, size_t n) {
const unsigned char* a = aptr, *b = bptr;
for (size_t i = 0; i < n; i++) {
if (a[i] < b[i]) return -1;
else if(a[i] > b[i]) return 1;
}
return 0;
}
EFI_STATUS efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
InitializeLib(ImageHandle, SystemTable);
Print(L"Hello World!\n\r");
EFI_FILE* Kernel = LoadFile(NULL, L"kernel.elf", ImageHandle, SystemTable);
if ( Kernel == NULL) {
Print(L"Could not load kernel \n\r");
} else {
Print(L"Kernel Loaded Successfully \n\r");
}
Elf64_Ehdr header;
{
UINTN FileInfoSize;
EFI_FILE_INFO* FileInfo;
Kernel->GetInfo(Kernel, &gEfiFileInfoGuid, &FileInfoSize, NULL);
SystemTable->BootServices->AllocatePool(EfiLoaderData, FileInfoSize, (void**)&FileInfo);
Kernel->GetInfo(Kernel, &gEfiFileInfoGuid, &FileInfoSize, (void**)&FileInfo);
UINTN size = sizeof(header);
Kernel->Read(Kernel, &size, &header);
}
if (
memcmp(&header.e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 ||
header.e_ident[EI_CLASS] != ELFCLASS64 ||
header.e_ident[EI_DATA] != ELFDATA2LSB ||
header.e_type != ET_EXEC ||
header.e_machine != EM_X86_64 ||
header.e_version != EV_CURRENT
) {
Print(L"kernel format is bad\r\n");
} else {
Print(L"kernel header successfully verified\r\n");
}
Elf64_Phdr* phdrs;
{
Kernel->SetPosition(Kernel, header.e_phoff);
UINTN size = header.e_phnum * header.e_phentsize;
SystemTable->BootServices->AllocatePool(EfiLoaderData, size, (void**)&phdrs);
Kernel->Read(Kernel, &size, phdrs);
}
for (
Elf64_Phdr* phdr = phdrs;
(char*)phdr < (char*)phdrs + header.e_phnum * header.e_phentsize;
phdr = (Elf64_Phdr*)((char*)phdr + header.e_phentsize)
) {
switch(phdr->p_type) {
case PT_LOAD: {
int pages = (phdr->p_memsz + 0x1000 - 1) / 0x1000;
Elf64_Addr segment = phdr->p_paddr;
SystemTable->BootServices->AllocatePages(AllocateAddress, EfiLoaderData, pages, &segment);
Kernel->SetPosition(Kernel, phdr->p_offset);
UINTN size = phdr->p_filesz;
Kernel->Read(Kernel, &size, (void*)segment);
break;
}
}
}
Print(L"Kernel Loaded\n\r");
void (*KernelStart)(Framebuffer*, PSF1_FONT**) = ((__attribute__((sysv_abi)) void(*)(Framebuffer*, PSF1_FONT**) ) header.e_entry);
PSF1_FONT* newFont = LoadPSF1Font(NULL, L"zap-light16.psf", ImageHandle, SystemTable);
if (newFont == NULL) {
Print(L"Font is not valid or is not found\n\r");
} else {
Print(L"Font found, char size = %d\n\r", newFont->psf1_Header->charsize);
}
PSF1_FONT* newFontExt = LoadPSF1Font(NULL, L"zap-ext-light16.psf", ImageHandle, SystemTable);
if (newFont == NULL) {
Print(L"Font is not valid or is not found\n\r");
} else {
Print(L"Font found, char size = %d\n\r", newFont->psf1_Header->charsize);
}
PSF1_FONT* fonts[] = {newFont, newFontExt};
Framebuffer* newBuffer = InitializeGOP();
Print(L"Base: 0x%x\n\rSize: 0x%x\n\rWidth: %d\n\rHeight: %d\n\rPixelsPerScanline: %d\n\r",
newBuffer->BaseAddress,
newBuffer->BufferSize,
newBuffer->Width,
newBuffer->Height,
newBuffer->PixelsPerScanLine);
KernelStart(newBuffer, fonts);
return EFI_SUCCESS; // Exit the UEFI application
}
The problem is here:
if ( (*chr == '\\') && ((*chr+1 == 'n') || (*chr+1 == '0')) ) {
PutChar('\n');
chr++;
chr++;
}
...
You should not be parsing out \n since this will be present in the string as a linefeed character. What you want instead is:
if (*chr == '\n') {
PutChar('\n');
chr++;
}
...

strange behaviour saving file

I use lzmaspec.cpp from 7zip library lzma1900/cpp/7zip/Bundles/Lzmaspec to decompress lzma file.
it works fine and save file correctly.
when I take main2 function and and make header file to use it in my project,it does not save the whole file.
this is lzmaspec.h
/*
* LzmaSpec.h
*
* Created on: Oct 14, 2020
* Author: za2ponubuntu1844
*/
#ifndef LZMASPEC_H_
#define LZMASPEC_H_
int main2(const char *,const char *);
#endif /* LZMASPEC_H_ */
and this is my modified main2 function
/* LzmaSpec.cpp -- LZMA Reference Decoder
2015-06-14 : Igor Pavlov : Public domain */
// This code implements LZMA file decoding according to LZMA specification.
// This code is not optimized for speed.
#include <stdio.h>
#ifdef _MSC_VER
#pragma warning(disable : 4710) // function not inlined
#pragma warning(disable : 4996) // This function or variable may be unsafe
#endif
typedef unsigned char Byte;
typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG
typedef unsigned long UInt32;
#else
typedef unsigned int UInt32;
#endif
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 UInt64;
#else
typedef unsigned long long int UInt64;
#endif
struct CInputStream
{
FILE *File;
UInt64 Processed;
void Init() { Processed = 0; }
Byte ReadByte()
{
int c = getc(File);
if (c < 0)
throw "Unexpected end of file";
Processed++;
return (Byte)c;
}
};
struct COutStream
{
FILE *File;
UInt64 Processed;
void Init() { Processed = 0; }
void WriteByte(Byte b)
{
if (putc(b, File) == EOF)
throw "File writing error";
Processed++;
}
};
class COutWindow
{
Byte *Buf;
UInt32 Pos;
UInt32 Size;
bool IsFull;
public:
unsigned TotalPos;
COutStream OutStream;
COutWindow(): Buf(NULL) {}
~COutWindow() { delete []Buf; }
void Create(UInt32 dictSize)
{
Buf = new Byte[dictSize];
Pos = 0;
Size = dictSize;
IsFull = false;
TotalPos = 0;
}
void PutByte(Byte b)
{
TotalPos++;
Buf[Pos++] = b;
if (Pos == Size)
{
Pos = 0;
IsFull = true;
}
OutStream.WriteByte(b);
}
Byte GetByte(UInt32 dist) const
{
return Buf[dist <= Pos ? Pos - dist : Size - dist + Pos];
}
void CopyMatch(UInt32 dist, unsigned len)
{
for (; len > 0; len--)
PutByte(GetByte(dist));
}
bool CheckDistance(UInt32 dist) const
{
return dist <= Pos || IsFull;
}
bool IsEmpty() const
{
return Pos == 0 && !IsFull;
}
};
#define kNumBitModelTotalBits 11
#define kNumMoveBits 5
typedef UInt16 CProb;
#define PROB_INIT_VAL ((1 << kNumBitModelTotalBits) / 2)
#define INIT_PROBS(p) \
{ for (unsigned i = 0; i < sizeof(p) / sizeof(p[0]); i++) p[i] = PROB_INIT_VAL; }
class CRangeDecoder
{
UInt32 Range;
UInt32 Code;
void Normalize();
public:
CInputStream *InStream;
bool Corrupted;
bool Init();
bool IsFinishedOK() const { return Code == 0; }
UInt32 DecodeDirectBits(unsigned numBits);
unsigned DecodeBit(CProb *prob);
};
bool CRangeDecoder::Init()
{
Corrupted = false;
Range = 0xFFFFFFFF;
Code = 0;
Byte b = InStream->ReadByte();
for (int i = 0; i < 4; i++)
Code = (Code << 8) | InStream->ReadByte();
if (b != 0 || Code == Range)
Corrupted = true;
return b == 0;
}
#define kTopValue ((UInt32)1 << 24)
void CRangeDecoder::Normalize()
{
if (Range < kTopValue)
{
Range <<= 8;
Code = (Code << 8) | InStream->ReadByte();
}
}
UInt32 CRangeDecoder::DecodeDirectBits(unsigned numBits)
{
UInt32 res = 0;
do
{
Range >>= 1;
Code -= Range;
UInt32 t = 0 - ((UInt32)Code >> 31);
Code += Range & t;
if (Code == Range)
Corrupted = true;
Normalize();
res <<= 1;
res += t + 1;
}
while (--numBits);
return res;
}
unsigned CRangeDecoder::DecodeBit(CProb *prob)
{
unsigned v = *prob;
UInt32 bound = (Range >> kNumBitModelTotalBits) * v;
unsigned symbol;
if (Code < bound)
{
v += ((1 << kNumBitModelTotalBits) - v) >> kNumMoveBits;
Range = bound;
symbol = 0;
}
else
{
v -= v >> kNumMoveBits;
Code -= bound;
Range -= bound;
symbol = 1;
}
*prob = (CProb)v;
Normalize();
return symbol;
}
unsigned BitTreeReverseDecode(CProb *probs, unsigned numBits, CRangeDecoder *rc)
{
unsigned m = 1;
unsigned symbol = 0;
for (unsigned i = 0; i < numBits; i++)
{
unsigned bit = rc->DecodeBit(&probs[m]);
m <<= 1;
m += bit;
symbol |= (bit << i);
}
return symbol;
}
template <unsigned NumBits>
class CBitTreeDecoder
{
CProb Probs[(unsigned)1 << NumBits];
public:
void Init()
{
INIT_PROBS(Probs);
}
unsigned Decode(CRangeDecoder *rc)
{
unsigned m = 1;
for (unsigned i = 0; i < NumBits; i++)
m = (m << 1) + rc->DecodeBit(&Probs[m]);
return m - ((unsigned)1 << NumBits);
}
unsigned ReverseDecode(CRangeDecoder *rc)
{
return BitTreeReverseDecode(Probs, NumBits, rc);
}
};
#define kNumPosBitsMax 4
#define kNumStates 12
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kMatchMinLen 2
class CLenDecoder
{
CProb Choice;
CProb Choice2;
CBitTreeDecoder<3> LowCoder[1 << kNumPosBitsMax];
CBitTreeDecoder<3> MidCoder[1 << kNumPosBitsMax];
CBitTreeDecoder<8> HighCoder;
public:
void Init()
{
Choice = PROB_INIT_VAL;
Choice2 = PROB_INIT_VAL;
HighCoder.Init();
for (unsigned i = 0; i < (1 << kNumPosBitsMax); i++)
{
LowCoder[i].Init();
MidCoder[i].Init();
}
}
unsigned Decode(CRangeDecoder *rc, unsigned posState)
{
if (rc->DecodeBit(&Choice) == 0)
return LowCoder[posState].Decode(rc);
if (rc->DecodeBit(&Choice2) == 0)
return 8 + MidCoder[posState].Decode(rc);
return 16 + HighCoder.Decode(rc);
}
};
unsigned UpdateState_Literal(unsigned state)
{
if (state < 4) return 0;
else if (state < 10) return state - 3;
else return state - 6;
}
unsigned UpdateState_Match (unsigned state) { return state < 7 ? 7 : 10; }
unsigned UpdateState_Rep (unsigned state) { return state < 7 ? 8 : 11; }
unsigned UpdateState_ShortRep(unsigned state) { return state < 7 ? 9 : 11; }
#define LZMA_DIC_MIN (1 << 12)
class CLzmaDecoder
{
public:
CRangeDecoder RangeDec;
COutWindow OutWindow;
bool markerIsMandatory;
unsigned lc, pb, lp;
UInt32 dictSize;
UInt32 dictSizeInProperties;
void DecodeProperties(const Byte *properties)
{
unsigned d = properties[0];
if (d >= (9 * 5 * 5))
throw "Incorrect LZMA properties";
lc = d % 9;
d /= 9;
pb = d / 5;
lp = d % 5;
dictSizeInProperties = 0;
for (int i = 0; i < 4; i++)
dictSizeInProperties |= (UInt32)properties[i + 1] << (8 * i);
dictSize = dictSizeInProperties;
if (dictSize < LZMA_DIC_MIN)
dictSize = LZMA_DIC_MIN;
}
CLzmaDecoder(): LitProbs(NULL) {}
~CLzmaDecoder() { delete []LitProbs; }
void Create()
{
OutWindow.Create(dictSize);
CreateLiterals();
}
int Decode(bool unpackSizeDefined, UInt64 unpackSize);
private:
CProb *LitProbs;
void CreateLiterals()
{
LitProbs = new CProb[(UInt32)0x300 << (lc + lp)];
}
void InitLiterals()
{
UInt32 num = (UInt32)0x300 << (lc + lp);
for (UInt32 i = 0; i < num; i++)
LitProbs[i] = PROB_INIT_VAL;
}
void DecodeLiteral(unsigned state, UInt32 rep0)
{
unsigned prevByte = 0;
if (!OutWindow.IsEmpty())
prevByte = OutWindow.GetByte(1);
unsigned symbol = 1;
unsigned litState = ((OutWindow.TotalPos & ((1 << lp) - 1)) << lc) + (prevByte >> (8 - lc));
CProb *probs = &LitProbs[(UInt32)0x300 * litState];
if (state >= 7)
{
unsigned matchByte = OutWindow.GetByte(rep0 + 1);
do
{
unsigned matchBit = (matchByte >> 7) & 1;
matchByte <<= 1;
unsigned bit = RangeDec.DecodeBit(&probs[((1 + matchBit) << 8) + symbol]);
symbol = (symbol << 1) | bit;
if (matchBit != bit)
break;
}
while (symbol < 0x100);
}
while (symbol < 0x100)
symbol = (symbol << 1) | RangeDec.DecodeBit(&probs[symbol]);
OutWindow.PutByte((Byte)(symbol - 0x100));
}
CBitTreeDecoder<6> PosSlotDecoder[kNumLenToPosStates];
CBitTreeDecoder<kNumAlignBits> AlignDecoder;
CProb PosDecoders[1 + kNumFullDistances - kEndPosModelIndex];
void InitDist()
{
for (unsigned i = 0; i < kNumLenToPosStates; i++)
PosSlotDecoder[i].Init();
AlignDecoder.Init();
INIT_PROBS(PosDecoders);
}
unsigned DecodeDistance(unsigned len)
{
unsigned lenState = len;
if (lenState > kNumLenToPosStates - 1)
lenState = kNumLenToPosStates - 1;
unsigned posSlot = PosSlotDecoder[lenState].Decode(&RangeDec);
if (posSlot < 4)
return posSlot;
unsigned numDirectBits = (unsigned)((posSlot >> 1) - 1);
UInt32 dist = ((2 | (posSlot & 1)) << numDirectBits);
if (posSlot < kEndPosModelIndex)
dist += BitTreeReverseDecode(PosDecoders + dist - posSlot, numDirectBits, &RangeDec);
else
{
dist += RangeDec.DecodeDirectBits(numDirectBits - kNumAlignBits) << kNumAlignBits;
dist += AlignDecoder.ReverseDecode(&RangeDec);
}
return dist;
}
CProb IsMatch[kNumStates << kNumPosBitsMax];
CProb IsRep[kNumStates];
CProb IsRepG0[kNumStates];
CProb IsRepG1[kNumStates];
CProb IsRepG2[kNumStates];
CProb IsRep0Long[kNumStates << kNumPosBitsMax];
CLenDecoder LenDecoder;
CLenDecoder RepLenDecoder;
void Init()
{
InitLiterals();
InitDist();
INIT_PROBS(IsMatch);
INIT_PROBS(IsRep);
INIT_PROBS(IsRepG0);
INIT_PROBS(IsRepG1);
INIT_PROBS(IsRepG2);
INIT_PROBS(IsRep0Long);
LenDecoder.Init();
RepLenDecoder.Init();
}
};
#define LZMA_RES_ERROR 0
#define LZMA_RES_FINISHED_WITH_MARKER 1
#define LZMA_RES_FINISHED_WITHOUT_MARKER 2
int CLzmaDecoder::Decode(bool unpackSizeDefined, UInt64 unpackSize)
{
if (!RangeDec.Init())
return LZMA_RES_ERROR;
Init();
UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
unsigned state = 0;
for (;;)
{
if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory)
if (RangeDec.IsFinishedOK())
return LZMA_RES_FINISHED_WITHOUT_MARKER;
unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1);
if (RangeDec.DecodeBit(&IsMatch[(state << kNumPosBitsMax) + posState]) == 0)
{
if (unpackSizeDefined && unpackSize == 0)
return LZMA_RES_ERROR;
DecodeLiteral(state, rep0);
state = UpdateState_Literal(state);
unpackSize--;
continue;
}
unsigned len;
if (RangeDec.DecodeBit(&IsRep[state]) != 0)
{
if (unpackSizeDefined && unpackSize == 0)
return LZMA_RES_ERROR;
if (OutWindow.IsEmpty())
return LZMA_RES_ERROR;
if (RangeDec.DecodeBit(&IsRepG0[state]) == 0)
{
if (RangeDec.DecodeBit(&IsRep0Long[(state << kNumPosBitsMax) + posState]) == 0)
{
state = UpdateState_ShortRep(state);
OutWindow.PutByte(OutWindow.GetByte(rep0 + 1));
unpackSize--;
continue;
}
}
else
{
UInt32 dist;
if (RangeDec.DecodeBit(&IsRepG1[state]) == 0)
dist = rep1;
else
{
if (RangeDec.DecodeBit(&IsRepG2[state]) == 0)
dist = rep2;
else
{
dist = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = dist;
}
len = RepLenDecoder.Decode(&RangeDec, posState);
state = UpdateState_Rep(state);
}
else
{
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
len = LenDecoder.Decode(&RangeDec, posState);
state = UpdateState_Match(state);
rep0 = DecodeDistance(len);
if (rep0 == 0xFFFFFFFF)
return RangeDec.IsFinishedOK() ?
LZMA_RES_FINISHED_WITH_MARKER :
LZMA_RES_ERROR;
if (unpackSizeDefined && unpackSize == 0)
return LZMA_RES_ERROR;
if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0))
return LZMA_RES_ERROR;
}
len += kMatchMinLen;
bool isError = false;
if (unpackSizeDefined && unpackSize < len)
{
len = (unsigned)unpackSize;
isError = true;
}
OutWindow.CopyMatch(rep0 + 1, len);
unpackSize -= len;
if (isError)
return LZMA_RES_ERROR;
}
}
static void Print(const char *s)
{
fputs(s, stdout);
}
static void PrintError(const char *s)
{
fputs(s, stderr);
}
#define CONVERT_INT_TO_STR(charType, tempSize) \
void ConvertUInt64ToString(UInt64 val, char *s)
{
char temp[32];
unsigned i = 0;
while (val >= 10)
{
temp[i++] = (char)('0' + (unsigned)(val % 10));
val /= 10;
}
*s++ = (char)('0' + (unsigned)val);
while (i != 0)
{
i--;
*s++ = temp[i];
}
*s = 0;
}
void PrintUInt64(const char *title, UInt64 v)
{
Print(title);
Print(" : ");
char s[32];
ConvertUInt64ToString(v, s);
Print(s);
Print(" bytes \n");
}
int main2(const char * infile, const char *outfile)
{
try
{
Print("\nLZMA Reference Decoder 15.00 : Igor Pavlov : Public domain : 2015-04-16\n");
//if (numArgs == 1)
// Print("\nUse: lzmaSpec a.lzma outFile");
//if (numArgs != 3)
// throw "you must specify two parameters";
CInputStream inStream;
inStream.File = fopen(infile, "rb");
inStream.Init();
if (inStream.File == 0)
throw "Can't open input file";
CLzmaDecoder lzmaDecoder;
lzmaDecoder.OutWindow.OutStream.File = fopen(outfile, "wb+");
lzmaDecoder.OutWindow.OutStream.Init();
if (inStream.File == 0)
throw "Can't open output file";
Byte header[13];
int i;
for (i = 0; i < 13; i++)
header[i] = inStream.ReadByte();
lzmaDecoder.DecodeProperties(header);
printf("\nlc=%d, lp=%d, pb=%d", lzmaDecoder.lc, lzmaDecoder.lp, lzmaDecoder.pb);
printf("\nDictionary Size in properties = %u", lzmaDecoder.dictSizeInProperties);
printf("\nDictionary Size for decoding = %u", lzmaDecoder.dictSize);
UInt64 unpackSize = 0;
bool unpackSizeDefined = false;
for (i = 0; i < 8; i++)
{
Byte b = header[5 + i];
if (b != 0xFF)
unpackSizeDefined = true;
unpackSize |= (UInt64)b << (8 * i);
}
lzmaDecoder.markerIsMandatory = !unpackSizeDefined;
Print("\n");
if (unpackSizeDefined)
PrintUInt64("Uncompressed Size", unpackSize);
else
Print("End marker is expected\n");
lzmaDecoder.RangeDec.InStream = &inStream;
Print("\n");
lzmaDecoder.Create();
int res = lzmaDecoder.Decode(unpackSizeDefined, unpackSize);
PrintUInt64("Read ", inStream.Processed);
PrintUInt64("Written ", lzmaDecoder.OutWindow.OutStream.Processed);
if (res == LZMA_RES_ERROR)
throw "LZMA decoding error";
else if (res == LZMA_RES_FINISHED_WITHOUT_MARKER)
Print("Finished without end marker");
else if (res == LZMA_RES_FINISHED_WITH_MARKER)
{
if (unpackSizeDefined)
{
if (lzmaDecoder.OutWindow.OutStream.Processed != unpackSize)
throw "Finished with end marker before than specified size";
Print("Warning: ");
}
Print("Finished with end marker");
}
else
throw "Internal Error";
Print("\n");
if (lzmaDecoder.RangeDec.Corrupted)
{
Print("\nWarning: LZMA stream is corrupted\n");
}
//15-10-2020
}
catch (const char *s)
{
PrintError("\nError:\n");
PrintError(s);
PrintError("\n");
return 1;
}
catch(...)
{
PrintError("\nError\n");
return 1;
}
return 0;
}
/*
int
#ifdef _MSC_VER
__cdecl
#endif
main(int numArgs, const char *args[])
{
try { return main2(numArgs, args); }
catch (const char *s)
{
PrintError("\nError:\n");
PrintError(s);
PrintError("\n");
return 1;
}
catch(...)
{
PrintError("\nError\n");
return 1;
}
}
*/
when i debug it i find that function
void WriteByte(Byte b)
works fine but the resulting file does not have correct size.
i used this file
13h_ticks.bi5 from dukascopy
i uploaded it here
https://github.com/ahmed-allam/starting_coding
I do not know why this happens.
when i try to decompress same file using lzmaspec.cpp outside project ,it works fine.
I need guide line where the error could be?

ambiguous symbol /visual studio/ c code

Hy ,so my project to migrate to Visual Studio 2015. However I got stuck when I saw that receive 13 errors.
Error C2872 'data': ambiguous symbol Error C2872 'size': ambiguous symbol
Before you migrate to vss2015 everything work perfectly, I can not understand why we have moved the program after receiving this error.
Here is my Jpeg.cpp
#include "StdAfx.h"
#include "JpegFile.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <libjpeg-6b/jpeglib.h>
#include <libjpeg-6b/jpegLibLink.h>
#define OUTBUFFER_SIZE 0x8000
static FILE*fi;
static JOCTET * buffer;
static unsigned char*dest;
static int len;
static int destlen;
static unsigned char*data;
static int pos;
static int size;
static void file_init_destination(j_compress_ptr cinfo)
{
struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
buffer = (JOCTET*)malloc(OUTBUFFER_SIZE);
if(!buffer) {
perror("malloc");
printf("Out of memory!\n");
exit(1);
}
dmgr->next_output_byte = buffer;
dmgr->free_in_buffer = OUTBUFFER_SIZE;
}
static boolean file_empty_output_buffer(j_compress_ptr cinfo)
{
struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
if(fi)
fwrite(buffer, OUTBUFFER_SIZE, 1, fi);
dmgr->next_output_byte = buffer;
dmgr->free_in_buffer = OUTBUFFER_SIZE;
return 1;
}
static void file_term_destination(j_compress_ptr cinfo)
{ struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
if(fi)
fwrite(buffer, OUTBUFFER_SIZE-dmgr->free_in_buffer, 1, fi);
free(buffer);
buffer = 0;
dmgr->free_in_buffer = 0;
}
static void mem_init_destination(j_compress_ptr cinfo)
{
struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
dmgr->next_output_byte = dest;
dmgr->free_in_buffer = destlen;
}
static boolean mem_empty_output_buffer(j_compress_ptr cinfo)
{
printf("jpeg mem overflow!\n");
exit(1);
}
static void mem_term_destination(j_compress_ptr cinfo)
{
struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
len = destlen - dmgr->free_in_buffer;
dmgr->free_in_buffer = 0;
}
int jpeg_save(unsigned char*data, int width, int height, int quality, const char*filename)
{
struct jpeg_destination_mgr mgr;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
int t;
if(filename) {
fi = fopen(filename, "wb");
if(fi == NULL)
return 0;
} else
fi = NULL;
memset(&cinfo, 0, sizeof(cinfo));
memset(&jerr, 0, sizeof(jerr));
memset(&mgr, 0, sizeof(mgr));
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
mgr.init_destination = file_init_destination;
mgr.empty_output_buffer = file_empty_output_buffer;
mgr.term_destination = file_term_destination;
cinfo.dest = &mgr;
// init compression
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo,quality,TRUE);
//jpeg_write_tables(&cinfo);
//jpeg_suppress_tables(&cinfo, TRUE);
jpeg_start_compress(&cinfo, FALSE);
for(t=0;t<height;t++) {
unsigned char*data2 = &data[width*3*t];
jpeg_write_scanlines(&cinfo, &data2, 1);
}
jpeg_finish_compress(&cinfo);
if(fi)
fclose(fi);
jpeg_destroy_compress(&cinfo);
return 1;
}
int jpeg_save_to_file(unsigned char*data, int width, int height, int quality, FILE*_fi)
{
struct jpeg_destination_mgr mgr;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
int t;
fi = _fi;
memset(&cinfo, 0, sizeof(cinfo));
memset(&jerr, 0, sizeof(jerr));
memset(&mgr, 0, sizeof(mgr));
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
mgr.init_destination = file_init_destination;
mgr.empty_output_buffer = file_empty_output_buffer;
mgr.term_destination = file_term_destination;
cinfo.dest = &mgr;
// init compression
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
cinfo.dct_method = JDCT_IFAST;
jpeg_set_quality(&cinfo,quality,TRUE);
//jpeg_write_tables(&cinfo);
//jpeg_suppress_tables(&cinfo, TRUE);
jpeg_start_compress(&cinfo, FALSE);
for(t=0;t<height;t++) {
unsigned char*data2 = &data[width*3*t];
jpeg_write_scanlines(&cinfo, &data2, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
return 1;
}
int jpeg_save_to_mem(unsigned char*data, int width, int height, int quality, unsigned char*_dest, int _destlen)
{
struct jpeg_destination_mgr mgr;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
int t;
memset(&cinfo, 0, sizeof(cinfo));
memset(&jerr, 0, sizeof(jerr));
memset(&mgr, 0, sizeof(mgr));
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
dest = _dest;
len = 0;
destlen = _destlen;
mgr.init_destination = mem_init_destination;
mgr.empty_output_buffer = mem_empty_output_buffer;
mgr.term_destination = mem_term_destination;
cinfo.dest = &mgr;
// init compression
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
cinfo.dct_method = JDCT_IFAST;
jpeg_set_quality(&cinfo,quality,TRUE);
jpeg_start_compress(&cinfo, FALSE);
for(t=0;t<height;t++) {
unsigned char*data2 = &data[width*3*t];
jpeg_write_scanlines(&cinfo, &data2, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
return len;
}
void mem_init_source (j_decompress_ptr cinfo)
{
struct jpeg_source_mgr* mgr = cinfo->src;
mgr->next_input_byte = data;
mgr->bytes_in_buffer = size;
//printf("init %d\n", size - mgr->bytes_in_buffer);
}
boolean mem_fill_input_buffer (j_decompress_ptr cinfo)
{
struct jpeg_source_mgr* mgr = cinfo->src;
printf("fill %d\n", size - mgr->bytes_in_buffer);
return 0;
}
void mem_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
struct jpeg_source_mgr* mgr = cinfo->src;
printf("skip %d +%d\n", size - mgr->bytes_in_buffer, num_bytes);
if(num_bytes<=0)
return;
mgr->next_input_byte += num_bytes;
mgr->bytes_in_buffer -= num_bytes;
}
boolean mem_resync_to_restart (j_decompress_ptr cinfo, int desired)
{
struct jpeg_source_mgr* mgr = cinfo->src;
printf("resync %d\n", size - mgr->bytes_in_buffer);
mgr->next_input_byte = data;
mgr->bytes_in_buffer = size;
return 1;
}
void mem_term_source (j_decompress_ptr cinfo)
{
struct jpeg_source_mgr* mgr = cinfo->src;
//printf("term %d\n", size - mgr->bytes_in_buffer);
}
int jpeg_load_from_mem(unsigned char*_data, int _size, unsigned char*dest, int width, int height)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
struct jpeg_source_mgr mgr;
int y;
//int x;
data = _data;
size = _size;
jpeg_create_decompress(&cinfo);
mgr.next_input_byte = data;
mgr.bytes_in_buffer = size;
mgr.init_source =mem_init_source ;
mgr.fill_input_buffer =mem_fill_input_buffer ;
mgr.skip_input_data =mem_skip_input_data ;
mgr.resync_to_restart =mem_resync_to_restart ;
mgr.term_source =mem_term_source ;
cinfo.err = jpeg_std_error(&jerr);
cinfo.src = &mgr;
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
for(y=0;y<height;y++) {
unsigned char*j = &dest[width*y*3];
jpeg_read_scanlines(&cinfo,&j,1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
return 1;
}
typedef struct _RGBA {
unsigned char a,r,g,b;
} RGBA;
typedef unsigned char U8;
int jpeg_load(const char*filename, unsigned char**dest, int*_width, int*_height)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
//struct jpeg_source_mgr mgr;
FILE*fi = fopen(filename, "rb");
if(!fi) {
fprintf(stderr, "Couldn't open file %s\n", filename);
return 0;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, fi);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
U8*scanline = (U8 *)malloc(4 * cinfo.output_width);
int width = *_width = cinfo.output_width;
int height = *_height = cinfo.output_height;
*dest = (unsigned char*)malloc(width*height*4);
int y;
for (y=0;y<height;y++) {
int x;
U8 *js = scanline;
RGBA*line = &((RGBA*)(*dest))[y*width];
jpeg_read_scanlines(&cinfo, &js, 1);
if (cinfo.out_color_space == JCS_GRAYSCALE) {
for (x = 0; x < width; x++) {
line[x].a = 255;
line[x].r = line[x].g = line[x].b = js[x];
}
} else if (cinfo.out_color_space == JCS_RGB) {
for (x = width - 1; x >= 0; x--) {
line[x].a = 255;
line[x].r = js[x*3+0];
line[x].g = js[x*3+1];
line[x].b = js[x*3+2];
}
} else if (cinfo.out_color_space == JCS_YCCK) {
fprintf(stderr, "Error: Can't convert YCCK to RGB.\n");
return 0;
} else if (cinfo.out_color_space == JCS_YCbCr) {
for (x = 0; x < width; x++) {
int y = js[x * 3 + 0];
int u = js[x * 3 + 1];
int v = js[x * 3 + 1];
line[x].a = 255;
line[x].r = y + ((360 * (v - 128)) >> 8);
line[x].g = y - ((88 * (u - 128) + 183 * (v - 128)) >> 8);
line[x].b = y + ((455 * (u - 128)) >> 8);
}
} else if (cinfo.out_color_space == JCS_CMYK) {
for (x = 0; x < width; x++) {
int white = 255 - js[x * 4 + 3];
line[x].a = 255;
line[x].r = white - ((js[x * 4] * white) >> 8);
line[x].g = white - ((js[x * 4 + 1] * white) >> 8);
line[x].b = white - ((js[x * 4 + 2] * white) >> 8);
}
}
}
free(scanline);
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(fi);
return 1;
}
And here is Jpeg.h
#include <stdio.h>
int jpeg_save(unsigned char*data, int width, int height, int quality, const char*filename);
int jpeg_save_to_file(unsigned char*data, int width, int height, int quality, FILE*fi);
int jpeg_save_to_mem(unsigned char*data, int width, int height, int quality, unsigned char*dest, int destsize);
int jpeg_load(const char*filename, unsigned char**dest, int*width, int*height);
int jpeg_load_from_mem(unsigned char*_data, int size, unsigned char*dest, int width, int height);
I get the error for "data" and also for "size" symbol.
Best regards.
Why in visual studio 2013 i dont have that this error? And how to solve..
I get ambiguous symbol 10 times, in 10 sintax in jpeg.cpp

Color switching of an image using C++ code

Since i am quiet new to C++ and Image processing i have a problem modifying and adding a function to the code.
The requirement is only to switch between the RGB colors.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"
#include "math.h"
class myImageData
{
private:
int mW;
int mH;
int mCH;
double * mData;
void SkipComments(FILE *fp)
{
int ch;
char line[100];
while ((ch = fgetc(fp)) != EOF && isspace(ch))
;
if (ch == '#')
{
fgets(line, sizeof(line), fp);
SkipComments(fp);
}
else
{
fseek(fp, -1, SEEK_CUR);
}
}
public:
myImageData(void)
{
this->mData = NULL;
}
~myImageData()
{
if (this->mData != NULL)
{
delete[] this->mData;
}
}
void init(int W, int H, int CH)
{
this->mW = W;
this->mH = H;
this->mCH = CH;
if (this->mData != NULL)
delete[] this->mData;
this->mData = new double[(this->mW)*(this->mH)*(this->mCH)];
}
int getWidth(void)
{
return this->mW;
}
int getHeight(void)
{
return this->mH;
}
int getCH(void)
{
return this->mCH;
}
double * getDataPtr(void)
{
return this->mData;
}
double get(int x, int y)
{
return this->mData[y*(this->mW) + x];
}
double get(int x, int y, int CH)
{
return this->mData[this->mCH * (y*(this->mW) + x) + CH];
}
void set(int x, int y, double value)
{
this->mData[y*(this->mW) + x] = value;
}
void set(int x, int y, int CH, double value)
{
this->mData[this->mCH *(y*(this->mW) + x) + CH] = value;
}
void read(const char *filename);
void save(const char *filename);
};
void myImageData::read(const char *filename)
{
FILE *file = fopen(filename, "r");
if (file == NULL){
printf("Cannot open %s\n", filename);
exit(1); //abnormal termination
}
printf("Read an image from: %s\n", filename);
// read ppm/pgm header
char buf[256];
char filetype[256];
int W, H, Range, CH;
fgets(buf, sizeof(buf), file);
sscanf(buf, "%s", filetype);
SkipComments(file);
fgets(buf, sizeof(buf), file);
sscanf(buf, "%d%d", &W, &H);
SkipComments(file);
fgets(buf, sizeof(buf), file);
sscanf(buf, "%d", &Range);
//printf("Header: %s, %d, %d, %d\n", filetype, W, H, Range);
SkipComments(file);
if (strcmp(filetype, "P5") == 0)
{
CH = 1;
}
else if (strcmp(filetype, "P6") == 0)
{
CH = 3;
}
else
{
printf("Unknown image type\n");
exit(1); //abnormal termination
}
if (Range != 255){
printf("Invalid data\n");
exit(1); //abnormal termination
}
// create myImageData class
init(W, H, CH);
// read ppm data
int datalength = this->mW * this->mH * this->mCH;
unsigned char * temp = new unsigned char[datalength];
fread(temp, sizeof(unsigned char), datalength, file);
double * ptr1 = this->mData;
unsigned char *ptr2 = temp;
for (int i = 0; i < datalength; i++){
*ptr1 = (double)*ptr2;
ptr1++;
ptr2++;
}
delete[] temp;
fclose(file);
}
void myImageData::save(const char *filename){
char filenamefull[256];
if (this->mCH == 1){
sprintf(filenamefull, "%s.pgm", filename);
}
else{
sprintf(filenamefull, "%s.ppm", filename);
}
FILE *file = fopen(filenamefull, "w");
printf("Write an image to: %s \n", filenamefull);
if (this->mCH == 1){
fprintf(file, "P5\n");
}
else{
fprintf(file, "P6\n");
}
fprintf(file, "%d %d\n", this->mW, this->mH);
fprintf(file, "255\n");
int datalength = this->mW * this->mH * this->mCH;
unsigned char * temp = new unsigned char[datalength];
double * ptr1 = this->mData;
unsigned char * ptr2 = temp;
for (int i = 0; i < datalength; i++){
double value = *ptr1;
value = round(value);
if (value > 255) value = 255;
if (value < 0) value = 0;
*ptr2 = (unsigned char)value;
ptr1++;
ptr2++;
}
fwrite(temp, sizeof(unsigned char), datalength, file);
delete[] temp;
fprintf(file, "Â¥n");
fclose(file);
}
The errors i am having:
error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup
error LNK1120: 1 unresolved externals
Firstly, you have no main function. No surprise that your code doesn't work.. all you have is a class to load, save and manipulate PPM image files.
You appear to me using Visual Studio, so you'll need a function that looks like this:
int _tmain(int argc, _TCHAR* argv[])
{
myImageData image;
image.read("atestfile.ppm");
// do some stuff to your image
image.write("outputfile.ppm");
}
I'm assuming you have a test image in PPM format you can use here, of course.
Now this is madness:
double * ptr1 = this->mData;
unsigned char * ptr2 = temp;
for (int i = 0; i < datalength; i++){
double value = *ptr1;
value = round(value);
if (value > 255) value = 255;
if (value < 0) value = 0;
*ptr2 = (unsigned char)value;
ptr1++;
ptr2++;
}
You've read from an unsigned char, so there's no point stuffing it into a double, and there's definitely no point in checking if the value lies outside of 0 to 255. Why are you storing things in doubles? It makes no sense! Even if you did do something that needed a full double-precision floating point value per channel, you throw it all away in the output when you clamp everything to 0-255 again:
for (int i = 0; i < datalength; i++){
double value = *ptr1;
value = round(value);
if (value > 255) value = 255;
if (value < 0) value = 0;
*ptr2 = (unsigned char)value;
ptr1++;
ptr2++;
}
Also, this is basically C dressed up in a thin C++ veneer. That's okay, everyone has to start somewhere. But instead of using new to create an array, you can do this:
// read ppm data
int datalength = this->mW * this->mH * this->mCH;
// using a std::vector here means that the allocated memory will be freed
// automatically, even in the result of an error occurring.
std::vector<unsigned char> temp(datalength);
fread(&temp[0], sizeof(unsigned char), datalength, file);
I'd also consider using iostream classes such as fstream instead of fread and fopen and so on. But this is not really the place to get into those kinds of details.
Anyway, What to do with your image once it is loaded? You've got dead easy helper functions to read and write pixel values, which will let you do pretty much anything you want. Here's a simple example, swapping the R and B channels. You might get something better when you actually tell us what you wanted.
void swapRB(myImageData& image)
{
assert(image.getCH() == 3);
for (int x = 0; x < image.getWidth())
{
for (int y = 0; x < image.getHeight())
{
double R = image.get(x, y, 0);
double G = image.get(x, y, 1);
double B = image.get(x, y, 2);
image.set(x, y, 0, B);
image.set(x, y, 2, R);
}
}
}

How to use LZMA SDK in C++?

i have difficulties in using LZMA SDK in my application.
I would like to create a kind of single file compression tool. I dont need any directory support, just need only the LZMA2 stream. But i have no idea on how LZMA SDK is to be used for this.
Please can anyone give me a little example on how the LZMA SDK can be used under C++?
I think that it's a properly little example to use LZMA SDK.
/* LzmaUtil.c -- Test application for LZMA compression
2008-08-05
Igor Pavlov
public domain */
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../LzmaDec.h"
#include "../LzmaEnc.h"
#include "../Alloc.h"
const char *kCantReadMessage = "Can not read input file";
const char *kCantWriteMessage = "Can not write output file";
const char *kCantAllocateMessage = "Can not allocate memory";
const char *kDataErrorMessage = "Data error";
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
#define kInBufferSize (1 << 15)
#define kOutBufferSize (1 << 15)
unsigned char g_InBuffer[kInBufferSize];
unsigned char g_OutBuffer[kOutBufferSize];
size_t MyReadFile(FILE *file, void *data, size_t size)
{ return fread(data, 1, size, file); }
int MyReadFileAndCheck(FILE *file, void *data, size_t size)
{ return (MyReadFile(file, data, size) == size); }
size_t MyWriteFile(FILE *file, const void *data, size_t size)
{
if (size == 0)
return 0;
return fwrite(data, 1, size, file);
}
int MyWriteFileAndCheck(FILE *file, const void *data, size_t size)
{ return (MyWriteFile(file, data, size) == size); }
long MyGetFileLength(FILE *file)
{
long length;
fseek(file, 0, SEEK_END);
length = ftell(file);
fseek(file, 0, SEEK_SET);
return length;
}
void PrintHelp(char *buffer)
{
strcat(buffer, "\nLZMA Utility 4.58 Copyright (c) 1999-2008 Igor Pavlov 2008-04-11\n"
"\nUsage: lzma <e|d> inputFile outputFile\n"
" e: encode file\n"
" d: decode file\n");
}
int PrintError(char *buffer, const char *message)
{
strcat(buffer, "\nError: ");
strcat(buffer, message);
strcat(buffer, "\n");
return 1;
}
int PrintErrorNumber(char *buffer, SRes val)
{
sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val);
return 1;
}
int PrintUserError(char *buffer)
{
return PrintError(buffer, "Incorrect command");
}
#define IN_BUF_SIZE (1 << 16)
#define OUT_BUF_SIZE (1 << 16)
static int Decode(FILE *inFile, FILE *outFile, char *rs)
{
UInt64 unpackSize;
int thereIsSize; /* = 1, if there is uncompressed size in headers */
int i;
int res = 0;
CLzmaDec state;
/* header: 5 bytes of LZMA properties and 8 bytes of uncompressed size */
unsigned char header[LZMA_PROPS_SIZE + 8];
/* Read and parse header */
if (!MyReadFileAndCheck(inFile, header, sizeof(header)))
return PrintError(rs, kCantReadMessage);
unpackSize = 0;
thereIsSize = 0;
for (i = 0; i < 8; i++)
{
unsigned char b = header[LZMA_PROPS_SIZE + i];
if (b != 0xFF)
thereIsSize = 1;
unpackSize += (UInt64)b << (i * 8);
}
LzmaDec_Construct(&state);
res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
if (res != SZ_OK)
return res;
{
Byte inBuf[IN_BUF_SIZE];
Byte outBuf[OUT_BUF_SIZE];
size_t inPos = 0, inSize = 0, outPos = 0;
LzmaDec_Init(&state);
for (;;)
{
if (inPos == inSize)
{
inSize = MyReadFile(inFile, inBuf, IN_BUF_SIZE);
inPos = 0;
}
{
SizeT inProcessed = inSize - inPos;
SizeT outProcessed = OUT_BUF_SIZE - outPos;
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
ELzmaStatus status;
if (thereIsSize && outProcessed > unpackSize)
{
outProcessed = (SizeT)unpackSize;
finishMode = LZMA_FINISH_END;
}
res = LzmaDec_DecodeToBuf(&state, outBuf + outPos, &outProcessed,
inBuf + inPos, &inProcessed, finishMode, &status);
inPos += (UInt32)inProcessed;
outPos += outProcessed;
unpackSize -= outProcessed;
if (outFile != 0)
MyWriteFile(outFile, outBuf, outPos);
outPos = 0;
if (res != SZ_OK || thereIsSize && unpackSize == 0)
break;
if (inProcessed == 0 && outProcessed == 0)
{
if (thereIsSize || status != LZMA_STATUS_FINISHED_WITH_MARK)
res = SZ_ERROR_DATA;
break;
}
}
}
}
LzmaDec_Free(&state, &g_Alloc);
return res;
}
typedef struct _CFileSeqInStream
{
ISeqInStream funcTable;
FILE *file;
} CFileSeqInStream;
static SRes MyRead(void *p, void *buf, size_t *size)
{
if (*size == 0)
return SZ_OK;
*size = MyReadFile(((CFileSeqInStream*)p)->file, buf, *size);
/*
if (*size == 0)
return SZE_FAIL;
*/
return SZ_OK;
}
typedef struct _CFileSeqOutStream
{
ISeqOutStream funcTable;
FILE *file;
} CFileSeqOutStream;
static size_t MyWrite(void *pp, const void *buf, size_t size)
{
return MyWriteFile(((CFileSeqOutStream *)pp)->file, buf, size);
}
static SRes Encode(FILE *inFile, FILE *outFile, char *rs)
{
CLzmaEncHandle enc;
SRes res;
CFileSeqInStream inStream;
CFileSeqOutStream outStream;
CLzmaEncProps props;
enc = LzmaEnc_Create(&g_Alloc);
if (enc == 0)
return SZ_ERROR_MEM;
inStream.funcTable.Read = MyRead;
inStream.file = inFile;
outStream.funcTable.Write = MyWrite;
outStream.file = outFile;
LzmaEncProps_Init(&props);
res = LzmaEnc_SetProps(enc, &props);
if (res == SZ_OK)
{
Byte header[LZMA_PROPS_SIZE + 8];
size_t headerSize = LZMA_PROPS_SIZE;
UInt64 fileSize;
int i;
res = LzmaEnc_WriteProperties(enc, header, &headerSize);
fileSize = MyGetFileLength(inFile);
for (i = 0; i < 8; i++)
header[headerSize++] = (Byte)(fileSize >> (8 * i));
if (!MyWriteFileAndCheck(outFile, header, headerSize))
return PrintError(rs, "writing error");
if (res == SZ_OK)
res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable,
NULL, &g_Alloc, &g_Alloc);
}
LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
return res;
}
int main2(int numArgs, const char *args[], char *rs)
{
FILE *inFile = 0;
FILE *outFile = 0;
char c;
int res;
int encodeMode;
if (numArgs == 1)
{
PrintHelp(rs);
return 0;
}
if (numArgs < 3 || numArgs > 4 || strlen(args[1]) != 1)
return PrintUserError(rs);
c = args[1][0];
encodeMode = (c == 'e' || c == 'E');
if (!encodeMode && c != 'd' && c != 'D')
return PrintUserError(rs);
{
size_t t4 = sizeof(UInt32);
size_t t8 = sizeof(UInt64);
if (t4 != 4 || t8 != 8)
return PrintError(rs, "LZMA UTil needs correct UInt32 and UInt64");
}
inFile = fopen(args[2], "rb");
if (inFile == 0)
return PrintError(rs, "Can not open input file");
if (numArgs > 3)
{
outFile = fopen(args[3], "wb+");
if (outFile == 0)
return PrintError(rs, "Can not open output file");
}
else if (encodeMode)
PrintUserError(rs);
if (encodeMode)
{
res = Encode(inFile, outFile, rs);
}
else
{
res = Decode(inFile, outFile, rs);
}
if (outFile != 0)
fclose(outFile);
fclose(inFile);
if (res != SZ_OK)
{
if (res == SZ_ERROR_MEM)
return PrintError(rs, kCantAllocateMessage);
else if (res == SZ_ERROR_DATA)
return PrintError(rs, kDataErrorMessage);
else
return PrintErrorNumber(rs, res);
}
return 0;
}
int MY_CDECL main(int numArgs, const char *args[])
{
char rs[800] = { 0 };
int res = main2(numArgs, args, rs);
printf(rs);
return res;
}
Also you can see it at:
http://read.pudn.com/downloads151/sourcecode/zip/656407/7z460/C/LzmaUtil/LzmaUtil.c__.htm
http://read.pudn.com/downloads157/sourcecode/zip/698262/LZMA/LzmaUtil.c__.htm
I recently found a nice example, written in C++. Credit goes to GH user Treeki who published the original gist:
// note: -D_7ZIP_ST is required when compiling on non-Windows platforms
// g++ -o lzma_sample -std=c++14 -D_7ZIP_ST lzma_sample.cpp LzmaDec.c LzmaEnc.c LzFind.c
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <memory>
#include "LzmaEnc.h"
#include "LzmaDec.h"
static void *_lzmaAlloc(ISzAllocPtr, size_t size) {
return new uint8_t[size];
}
static void _lzmaFree(ISzAllocPtr, void *addr) {
if (!addr)
return;
delete[] reinterpret_cast<uint8_t *>(addr);
}
static ISzAlloc _allocFuncs = {
_lzmaAlloc, _lzmaFree
};
std::unique_ptr<uint8_t[]> lzmaCompress(const uint8_t *input, uint32_t inputSize, uint32_t *outputSize) {
std::unique_ptr<uint8_t[]> result;
// set up properties
CLzmaEncProps props;
LzmaEncProps_Init(&props);
if (inputSize >= (1 << 20))
props.dictSize = 1 << 20; // 1mb dictionary
else
props.dictSize = inputSize; // smaller dictionary = faster!
props.fb = 40;
// prepare space for the encoded properties
SizeT propsSize = 5;
uint8_t propsEncoded[5];
// allocate some space for the compression output
// this is way more than necessary in most cases...
// but better safe than sorry
// (a smarter implementation would use a growing buffer,
// but this requires a bunch of fuckery that is out of
/// scope for this simple example)
SizeT outputSize64 = inputSize * 1.5;
if (outputSize64 < 1024)
outputSize64 = 1024;
auto output = std::make_unique<uint8_t[]>(outputSize64);
int lzmaStatus = LzmaEncode(
output.get(), &outputSize64, input, inputSize,
&props, propsEncoded, &propsSize, 0,
NULL,
&_allocFuncs, &_allocFuncs);
*outputSize = outputSize64 + 13;
if (lzmaStatus == SZ_OK) {
// tricky: we have to generate the LZMA header
// 5 bytes properties + 8 byte uncompressed size
result = std::make_unique<uint8_t[]>(outputSize64 + 13);
uint8_t *resultData = result.get();
memcpy(resultData, propsEncoded, 5);
for (int i = 0; i < 8; i++)
resultData[5 + i] = (inputSize >> (i * 8)) & 0xFF;
memcpy(resultData + 13, output.get(), outputSize64);
}
return result;
}
std::unique_ptr<uint8_t[]> lzmaDecompress(const uint8_t *input, uint32_t inputSize, uint32_t *outputSize) {
if (inputSize < 13)
return NULL; // invalid header!
// extract the size from the header
UInt64 size = 0;
for (int i = 0; i < 8; i++)
size |= (input[5 + i] << (i * 8));
if (size <= (256 * 1024 * 1024)) {
auto blob = std::make_unique<uint8_t[]>(size);
ELzmaStatus lzmaStatus;
SizeT procOutSize = size, procInSize = inputSize - 13;
int status = LzmaDecode(blob.get(), &procOutSize, &input[13], &procInSize, input, 5, LZMA_FINISH_END, &lzmaStatus, &_allocFuncs);
if (status == SZ_OK && procOutSize == size) {
*outputSize = size;
return blob;
}
}
return NULL;
}
void hexdump(const uint8_t *buf, int size) {
int lines = (size + 15) / 16;
for (int i = 0; i < lines; i++) {
printf("%08x | ", i * 16);
int lineMin = i * 16;
int lineMax = lineMin + 16;
int lineCappedMax = (lineMax > size) ? size : lineMax;
for (int j = lineMin; j < lineCappedMax; j++)
printf("%02x ", buf[j]);
for (int j = lineCappedMax; j < lineMax; j++)
printf(" ");
printf("| ");
for (int j = lineMin; j < lineCappedMax; j++) {
if (buf[j] >= 32 && buf[j] <= 127)
printf("%c", buf[j]);
else
printf(".");
}
printf("\n");
}
}
void testIt(const uint8_t *input, int size) {
printf("Test Input:\n");
hexdump(input, size);
uint32_t compressedSize;
auto compressedBlob = lzmaCompress(input, size, &compressedSize);
if (compressedBlob) {
printf("Compressed:\n");
hexdump(compressedBlob.get(), compressedSize);
} else {
printf("Nope, we screwed it\n");
return;
}
// let's try decompressing it now
uint32_t decompressedSize;
auto decompressedBlob = lzmaDecompress(compressedBlob.get(), compressedSize, &decompressedSize);
if (decompressedBlob) {
printf("Decompressed:\n");
hexdump(decompressedBlob.get(), decompressedSize);
} else {
printf("Nope, we screwed it (part 2)\n");
return;
}
printf("----------\n");
}
void testIt(const char *string) {
testIt((const uint8_t *)string, strlen(string));
}
int main(int argc, char **argv) {
testIt("a");
testIt("here is a cool string");
testIt("here's something that should compress pretty well: abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdef");
return 0;
}
You can refer to this file on how to use lzma2。
https://github.com/Tencent/libpag/blob/aab6391e455193c8ec5b8e2031b495b3fe77b034/test/framework/utils/LzmaUtil.cpp
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tencent is pleased to support the open source community by making libpag available.
//
// Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// unless required by applicable law or agreed to in writing, software distributed under the
// license is distributed on an "as is" basis, without warranties or conditions of any kind,
// either express or implied. see the license for the specific language governing permissions
// and limitations under the license.
//
/////////////////////////////////////////////////////////////////////////////////////////////////
#include "LzmaUtil.h"
#include "test/framework/lzma/Lzma2DecMt.h"
#include "test/framework/lzma/Lzma2Enc.h"
namespace pag {
static void* LzmaAlloc(ISzAllocPtr, size_t size) {
return new uint8_t[size];
}
static void LzmaFree(ISzAllocPtr, void* address) {
if (!address) {
return;
}
delete[] reinterpret_cast<uint8_t*>(address);
}
static ISzAlloc gAllocFuncs = {LzmaAlloc, LzmaFree};
class SequentialOutStream {
public:
virtual ~SequentialOutStream() = default;
virtual bool write(const void* data, size_t size) = 0;
};
class SequentialInStream {
public:
virtual ~SequentialInStream() = default;
virtual bool read(void* data, size_t size, size_t* processedSize) = 0;
};
struct CSeqInStreamWrap {
ISeqInStream vt;
std::unique_ptr<SequentialInStream> inStream;
};
struct CSeqOutStreamWrap {
ISeqOutStream vt;
std::unique_ptr<SequentialOutStream> outStream;
};
class BuffPtrInStream : public SequentialInStream {
public:
explicit BuffPtrInStream(const uint8_t* buffer, size_t bufferSize)
: buffer(buffer), bufferSize(bufferSize) {
}
bool read(void* data, size_t size, size_t* processedSize) override {
if (processedSize) {
*processedSize = 0;
}
if (size == 0 || position >= bufferSize) {
return true;
}
auto remain = bufferSize - position;
if (remain > size) {
remain = size;
}
memcpy(data, static_cast<const uint8_t*>(buffer) + position, remain);
position += remain;
if (processedSize) {
*processedSize = remain;
}
return true;
}
private:
const uint8_t* buffer = nullptr;
size_t bufferSize = 0;
size_t position = 0;
};
class VectorOutStream : public SequentialOutStream {
public:
explicit VectorOutStream(std::vector<uint8_t>* buffer) : buffer(buffer) {
}
bool write(const void* data, size_t size) override {
auto oldSize = buffer->size();
buffer->resize(oldSize + size);
memcpy(&(*buffer)[oldSize], data, size);
return true;
}
private:
std::vector<uint8_t>* buffer;
};
class BuffPtrSeqOutStream : public SequentialOutStream {
public:
BuffPtrSeqOutStream(uint8_t* buffer, size_t size) : buffer(buffer), bufferSize(size) {
}
bool write(const void* data, size_t size) override {
auto remain = bufferSize - position;
if (remain > size) {
remain = size;
}
if (remain != 0) {
memcpy(buffer + position, data, remain);
position += remain;
}
return remain != 0 || size == 0;
}
private:
uint8_t* buffer = nullptr;
size_t bufferSize = 0;
size_t position = 0;
};
static const size_t kStreamStepSize = 1 << 31;
static SRes MyRead(const ISeqInStream* p, void* data, size_t* size) {
CSeqInStreamWrap* wrap = CONTAINER_FROM_VTBL(p, CSeqInStreamWrap, vt);
auto curSize = (*size < kStreamStepSize) ? *size : kStreamStepSize;
if (!wrap->inStream->read(data, curSize, &curSize)) {
return SZ_ERROR_READ;
}
*size = curSize;
return SZ_OK;
}
static size_t MyWrite(const ISeqOutStream* p, const void* buf, size_t size) {
auto* wrap = CONTAINER_FROM_VTBL(p, CSeqOutStreamWrap, vt);
if (wrap->outStream->write(buf, size)) {
return size;
}
return 0;
}
class Lzma2Encoder {
public:
Lzma2Encoder() {
encoder = Lzma2Enc_Create(&gAllocFuncs, &gAllocFuncs);
}
~Lzma2Encoder() {
Lzma2Enc_Destroy(encoder);
}
std::shared_ptr<Data> code(const std::shared_ptr<Data>& inputData) {
if (encoder == nullptr || inputData == nullptr || inputData->size() == 0) {
return nullptr;
}
auto inputSize = inputData->size();
CLzma2EncProps lzma2Props;
Lzma2EncProps_Init(&lzma2Props);
lzma2Props.lzmaProps.dictSize = inputSize;
lzma2Props.lzmaProps.level = 9;
lzma2Props.numTotalThreads = 4;
Lzma2Enc_SetProps(encoder, &lzma2Props);
std::vector<uint8_t> outBuf;
outBuf.resize(1 + 8);
outBuf[0] = Lzma2Enc_WriteProperties(encoder);
for (int i = 0; i < 8; i++) {
outBuf[1 + i] = static_cast<uint8_t>(inputSize >> (8 * i));
}
CSeqInStreamWrap inWrap = {};
inWrap.vt.Read = MyRead;
inWrap.inStream = std::make_unique<BuffPtrInStream>(
static_cast<const uint8_t*>(inputData->data()), inputSize);
CSeqOutStreamWrap outStream = {};
outStream.vt.Write = MyWrite;
outStream.outStream = std::make_unique<VectorOutStream>(&outBuf);
auto status =
Lzma2Enc_Encode2(encoder, &outStream.vt, nullptr, nullptr, &inWrap.vt, nullptr, 0, nullptr);
if (status != SZ_OK) {
return nullptr;
}
return Data::MakeWithCopy(&outBuf[0], outBuf.size());
}
private:
CLzma2EncHandle encoder = nullptr;
};
std::shared_ptr<Data> LzmaUtil::Compress(const std::shared_ptr<Data>& pixelData) {
Lzma2Encoder encoder;
return encoder.code(pixelData);
}
class Lzma2Decoder {
public:
Lzma2Decoder() {
decoder = Lzma2DecMt_Create(&gAllocFuncs, &gAllocFuncs);
}
~Lzma2Decoder() {
if (decoder) {
Lzma2DecMt_Destroy(decoder);
}
}
std::shared_ptr<Data> code(const std::shared_ptr<Data>& inputData) {
if (decoder == nullptr || inputData == nullptr || inputData->size() == 0) {
return nullptr;
}
auto input = static_cast<const uint8_t*>(inputData->data());
auto inputSize = inputData->size() - 9;
Byte prop = static_cast<const Byte*>(input)[0];
CLzma2DecMtProps props;
Lzma2DecMtProps_Init(&props);
props.inBufSize_ST = inputSize;
props.numThreads = 1;
UInt64 outBufferSize = 0;
for (int i = 0; i < 8; i++) {
outBufferSize |= (input[1 + i] << (i * 8));
}
auto outBuffer = new uint8_t[outBufferSize];
CSeqInStreamWrap inWrap = {};
inWrap.vt.Read = MyRead;
inWrap.inStream = std::make_unique<BuffPtrInStream>(input + 9, inputSize);
CSeqOutStreamWrap outWrap = {};
outWrap.vt.Write = MyWrite;
outWrap.outStream = std::make_unique<BuffPtrSeqOutStream>(outBuffer, outBufferSize);
UInt64 inProcessed = 0;
int isMT = false;
auto res = Lzma2DecMt_Decode(decoder, prop, &props, &outWrap.vt, &outBufferSize, 1, &inWrap.vt,
&inProcessed, &isMT, nullptr);
if (res == SZ_OK && inputSize == inProcessed) {
return Data::MakeAdopted(outBuffer, outBufferSize, Data::DeleteProc);
}
delete[] outBuffer;
return nullptr;
}
private:
CLzma2DecMtHandle decoder = nullptr;
};
std::shared_ptr<Data> LzmaUtil::Decompress(const std::shared_ptr<Data>& data) {
Lzma2Decoder decoder;
return decoder.code(data);
}
} // namespace pag