Skip to content

Commit

Permalink
Working PNG decoder, not optimized but working
Browse files Browse the repository at this point in the history
  • Loading branch information
Remco123 committed Sep 25, 2021
1 parent b325c17 commit e294226
Show file tree
Hide file tree
Showing 23 changed files with 951 additions and 17 deletions.
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
{
"description": "Load additional app binary",
"ignoreFailures": true,
"text": "add-symbol-file ${workspaceRoot}/isofiles/apps/init.bin 0x800000"
"text": "add-symbol-file ${workspaceRoot}/isofiles/apps/compositor.bin 0x800000"
}
]
},
Expand Down Expand Up @@ -79,7 +79,7 @@
{
"description": "Load additional app binary",
"ignoreFailures": true,
"text": "add-symbol-file ${workspaceRoot}/isofiles/apps/init.bin 0x800000"
"text": "add-symbol-file ${workspaceRoot}/isofiles/apps/compositor.bin 0x800000"
}
]
}
Expand Down
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@
"memory_resource": "cpp",
"hash_map": "cpp",
"list": "cpp",
"iterator": "cpp"
"iterator": "cpp",
"bit": "cpp",
"ctime": "cpp",
"numeric": "cpp",
"cinttypes": "cpp"
},
"C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: WebKit, PointerAlignment: Left}",
"python.pythonPath": "/usr/bin/python3"
Expand Down
9 changes: 3 additions & 6 deletions apps/desktop/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <gui/context.h>
#include <gui/gui.h>
#include <imaging/image.h>
#include <imaging/bmpformat.h>
#include <imaging/pngformat.h>

using namespace LIBCactusOS;
using namespace LIBCactusOS::Imaging;
Expand Down Expand Up @@ -35,14 +35,11 @@ void DesktopItem::DrawToContext()
{
if(this->iconBuffer)
{
Image img = ConvertBMPRaw(this->iconBuffer);
Image img = PNGDecoder::ConvertRAW(this->iconBuffer);
for(int x = 0; x < img.GetWidth(); x++)
for(int y = 0; y < img.GetHeight(); y++) {
uint32_t argb = img[y * img.GetWidth() + x];
if(argb != 0xFFFFFFFF)
this->context->canvas->SetPixel(x, y, argb);
else
this->context->canvas->SetPixel(x, y, 0x00000000);
this->context->canvas->SetPixel(x, y, argb);
}
}
if(this->drawLabel) {
Expand Down
Binary file removed isofiles/desktop/browser.bmp
Binary file not shown.
Binary file removed isofiles/desktop/calc.bmp
Binary file not shown.
Binary file added isofiles/desktop/calculator.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added isofiles/desktop/explorer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 5 additions & 5 deletions isofiles/desktop/items.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ This file contains the items that are present on the desktop
This file is parsed by the desktop application on startup
//////////////////

"Calculator" file="B:\apps\calc.bin" icon="B:\desktop\calc.bmp"
"Terminal" file="B:\apps\terminal.bin" icon="B:\desktop\term.bmp"
"Power Manager" file="B:\apps\powermanager.bin" icon="B:\desktop\power.bmp"
"Mines" file="B:\apps\mines.bin" icon="B:\desktop\mine.bmp"
"Browser" file="B:\apps\browser.bin" icon="B:\desktop\browser.bmp"
"Calculator" file="B:\apps\calc.bin" icon="B:\desktop\calculator.png"
"Terminal" file="B:\apps\terminal.bin" icon="B:\desktop\terminal.png"
"Power Manager" file="B:\apps\powermanager.bin" icon="B:\desktop\power.png"
"Mines" file="B:\apps\mines.bin" icon="B:\desktop\mine.png"
"Browser" file="B:\apps\browser.bin" icon="B:\desktop\explorer.png"
Binary file removed isofiles/desktop/mine.bmp
Binary file not shown.
Binary file added isofiles/desktop/mine.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed isofiles/desktop/power.bmp
Binary file not shown.
Binary file added isofiles/desktop/power.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed isofiles/desktop/term.bmp
Binary file not shown.
Binary file added isofiles/desktop/terminal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions lib/include/bitreader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#ifndef __LIBCACTUSOS__BITREADER_H
#define __LIBCACTUSOS__BITREADER_H

#include <types.h>

namespace LIBCactusOS
{
// Used to read specific bits of a datastream
class BitReader
{
private:
uint8_t* dataPtr = 0;
uint32_t pos = 0;
uint8_t byte = 0;
uint32_t numBits = 0;
public:
BitReader(uint8_t* data)
{
this->dataPtr = data;
this->pos = 0;
this->byte = 0;
this->numBits = 0;
}

// Read single byte
uint8_t ReadByte()
{
// Discard other bits
this->numBits = 0;
uint8_t b = this->dataPtr[this->pos];
this->pos += 1;
return b;
}

// Read single bit
uint8_t ReadBit()
{
if(this->numBits <= 0) {
this->byte = this->ReadByte();
this->numBits = 8;
}
this->numBits -= 1;
uint8_t bit = this->byte & 1;
this->byte >>= 1;
return bit;
}

// Read bits as type
template<typename T>
T ReadBits(uint32_t n)
{
T ret = 0;
for(uint32_t i = 0; i < n; i++)
ret |= (this->ReadBit() << i);

return ret;
}

// Read bytes as type
template<typename T>
T ReadBytes(uint32_t n)
{
T ret = 0;
for(uint32_t i = 0; i < n; i++)
ret |= (this->ReadByte() << (i*8));

return ret;
}
};
}

#endif
2 changes: 1 addition & 1 deletion lib/include/gui/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace LIBCactusOS
class IEventCallback
{
public:
virtual void Invoke(void*, ArgumentType) = 0;
virtual void Invoke(void*, ArgumentType) {}
};

// A callback that is a class method
Expand Down
2 changes: 1 addition & 1 deletion lib/include/heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace LIBCactusOS
uint32_t pageRoundUp(uint32_t address);
uint32_t pageRoundDown(uint32_t address);

#define HEAP_INCREASE_SIZE 1_MB
#define HEAP_INCREASE_SIZE 10_MB

struct MemoryHeader
{
Expand Down
163 changes: 163 additions & 0 deletions lib/include/imaging/pngformat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#ifndef __CACTUSOSLIB__IMAGING__PNGIMAGE_H
#define __CACTUSOSLIB__IMAGING__PNGIMAGE_H

#include <imaging/image.h>
#include <bitreader.h>
#include <list.h>
#include <string.h>

namespace LIBCactusOS
{
namespace Imaging
{
#define ZLIB_BUFFER_SIZE 10_MB

struct PNGChunk
{
uint32_t length;
uint8_t type[4];
//uint8_t data;
//uint32_t crc;
} __attribute__((packed));

struct IHDRChunk
{
uint32_t width;
uint32_t height;
uint8_t bits;
uint8_t colorType;
uint8_t compression;
uint8_t filter;
uint8_t interlace;
} __attribute__((packed));

class PNGBuffer
{
public:
uint32_t index = 0;
public:
uint8_t* buffer = 0;
PNGBuffer(uint32_t size)
{
buffer = new uint8_t[size];
memset(buffer, 0, size);
}
~PNGBuffer() { }

void Add(uint8_t byte)
{
buffer[index++] = byte;
}
uint8_t Get(uint32_t i)
{
return buffer[i];
}
uint32_t Size()
{
return index;
}
};

class PNGDecoder
{
private:
static uint8_t PaethPredictor(uint8_t* recon, uint8_t a, uint8_t b, uint8_t c);
static uint8_t Recon_a(uint8_t* recon, uint32_t stride, uint32_t r, uint32_t c);
static uint8_t Recon_b(uint8_t* recon, uint32_t stride, uint32_t r, uint32_t c);
static uint8_t Recon_c(uint8_t* recon, uint32_t stride, uint32_t r, uint32_t c);
public:
// Convert image file into image buffer
static Image Convert(const char* filepath);

// Create image from array of bytes in png format
static Image ConvertRAW(const uint8_t* rawData);
};

// Represents a single node in the huffman tree
class HuffmanNode
{
public:
uint32_t symbol = 0;
HuffmanNode* left = 0;
HuffmanNode* right = 0;

HuffmanNode()
{
this->symbol = 0;
this->left = 0;
this->right = 0;
}
};
class HuffmanTree
{
public:
HuffmanNode* root = 0;

HuffmanTree()
{
this->root = new HuffmanNode();
}
void Insert(uint32_t codeWord, uint32_t n, uint32_t symbol)
{
HuffmanNode* node = this->root;
HuffmanNode* nextNode = 0;
for(int i = n - 1; i >= 0; i--) {
uint32_t b = codeWord & (1 << i);
if(b) {
nextNode = node->right;
if(nextNode == 0) {
node->right = new HuffmanNode();
nextNode = node->right;
}
}
else {
nextNode = node->left;
if(nextNode == 0) {
node->left = new HuffmanNode();
nextNode = node->left;
}
}
node = nextNode;
}
node->symbol = symbol;
}
};

struct DecodeTreesResult
{
HuffmanTree* literalLengthTree;
HuffmanTree* distanceTree;
};

// Class used to decompress ZLIB data such as png and zip files
class ZLIBDecompressor
{
private:
// Reads data from a non compression block
static void InflateBlockNoCompression(BitReader* reader, PNGBuffer* target);

// Reads data from dynamic block
static void InflateBlockDynamic(BitReader* reader, PNGBuffer* target);

// Reads data from static block
static void InflateBlockStatic(BitReader* reader, PNGBuffer* target);

// Decodes one symbol from bitstream using a HuffmanTree
static uint32_t DecodeSymbol(BitReader* reader, HuffmanTree* tree);

static void InflateBlockData(BitReader* reader, HuffmanTree* literalLengthTree, HuffmanTree* distanceTree, PNGBuffer* target);

static HuffmanTree* BitListToTree(List<uint32_t>* bitList, List<uint8_t>* alphabet);

static DecodeTreesResult DecodeTrees(BitReader* reader);
public:
// Perform decompression on input and return the complete set of data
static uint8_t* Decompress(uint8_t* input, uint32_t* lenOut = 0);

// Perform the actual inflation of the DEFLATE block
static uint8_t* Inflate(BitReader* reader, uint32_t* lenOut = 0);
};
}
}

#endif
31 changes: 31 additions & 0 deletions lib/include/vector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef __LIBCACTUSOS__VECTOR_H
#define __LIBCACTUSOS__VECTOR_H

#include <types.h>

namespace LIBCactusOS
{
template<typename T>
class Vector
{
private:
uint32_t size = 0;
uint32_t capacity = 0;
T* buffer = 0;

void reserve(int capacity);
public:
Vector();

int Size();
void push_back(const T& item);
void pop_back();
void clear();

T& GetAt(int n);
T& operator[](int i);
T* data();
};
}

#endif
2 changes: 1 addition & 1 deletion lib/src/heap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void* UserHeap::Malloc(uint32_t size)
Log(Warning, "Heap needs to be expanded for this process");

//Call Kernel
if(DoSyscall(SYSCALL_SET_HEAP_SIZE, endAddress + size + HEAP_INCREASE_SIZE) == SYSCALL_RET_SUCCES) {
if(DoSyscall(SYSCALL_SET_HEAP_SIZE, pageRoundUp(endAddress + size + HEAP_INCREASE_SIZE)) == SYSCALL_RET_SUCCES) {
MemoryHeader* lastHeader = 0;

//Find last block
Expand Down
4 changes: 4 additions & 0 deletions lib/src/imaging/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <imaging/bmpformat.h>
#include <imaging/jpeg_decoder.h>
#include <imaging/pngformat.h>

using namespace LIBCactusOS;
using namespace LIBCactusOS::Imaging;
Expand Down Expand Up @@ -126,6 +127,9 @@ Image Image::CreateFromFile(const char* filepath, const char* ext)
}
}
}
else if(strcmp(extension, "png") == 1) {
return PNGDecoder::Convert(filepath);
}
else
Print("Could not found a image converter for extension %s\n", extension);

Expand Down
Loading

0 comments on commit e294226

Please sign in to comment.