This repository has been archived by the owner on Apr 25, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Marcin Kurczewski
committed
Dec 7, 2014
1 parent
9ac690c
commit 75f13e6
Showing
16 changed files
with
285 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
class Image | ||
attr_accessor :width | ||
attr_accessor :height | ||
attr_accessor :pixels | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
require_relative 'tlg_reader' | ||
require_relative 'tlg5_reader' | ||
require_relative 'tlg6_reader' | ||
require 'rubygems' | ||
require 'RMagick' | ||
|
||
class Tlg0Reader < TlgReader | ||
MAGIC = "\x54\x4c\x47\x30\x2e\x30\x00\x73\x64\x73\x1a" | ||
|
||
def read_stream(file) | ||
assert_magic(file) | ||
_raw_data_size = file.read(4).unpack('<L')[0] | ||
magic2 = file.read(11) | ||
file.seek(-11, 1) | ||
image = reader_from_magic(magic2).new.read_stream(file) | ||
process_chunks(file) | ||
image | ||
end | ||
|
||
private | ||
|
||
def process_chunks(file) | ||
until file.eof? | ||
chunk_name = file.read(4) | ||
chunk_size = file.read(4).unpack('<L')[0] | ||
chunk_data = file.read(chunk_size) | ||
process_tag_chunk(chunk_data) if chunk_name == 'tags' | ||
end | ||
end | ||
|
||
def process_tag_chunk(chunk_data) | ||
until chunk_data.empty? | ||
key, chunk_data = extract_string(chunk_data) | ||
_, _, chunk_data = chunk_data.partition('=') | ||
value, chunk_data = extract_string(chunk_data) | ||
_, _, chunk_data = chunk_data.partition(',') | ||
puts 'Tag found: ' + key + ' = ' + value | ||
end | ||
end | ||
|
||
def extract_string(raw) | ||
size, _colon, raw = raw.partition(':') | ||
size = size.to_i | ||
value = raw[0..(size - 1)] | ||
raw = raw[size..-1] | ||
[value, raw] | ||
end | ||
|
||
def assert_magic(file) | ||
fail 'Not a TLG0 file ' if file.read(11) != MAGIC | ||
end | ||
|
||
def reader_from_magic(magic) | ||
return Tlg5Reader if magic == Tlg5Reader::MAGIC | ||
return Tlg6Reader if magic == Tlg6Reader::MAGIC | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,10 @@ | ||
class Tlg6Reader | ||
MAGIC = "\x54\x4c\x47\x36\x2e\x30\x00\x72\x61\x77\x1a" | ||
require_relative 'tlg_reader' | ||
|
||
attr_accessor :width | ||
attr_accessor :height | ||
attr_accessor :pixels | ||
class Tlg6Reader < TlgReader | ||
MAGIC = "\x54\x4c\x47\x36\x2e\x30\x00\x72\x61\x77\x1a" | ||
|
||
def self.read(_input_path) | ||
def read_stream(file) | ||
fail 'Not a TLG6 file ' if file.read(11) != MAGIC | ||
fail 'Not implemented! Please send sample files to @rr- on github.' | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
class TlgReader | ||
def read(input_path) | ||
open(input_path, 'rb') { |file| read_stream(file) } | ||
end | ||
|
||
def read_stream(file) | ||
fail 'Implement me' | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,82 @@ | ||
#include <cstring> | ||
#include <fstream> | ||
#include <memory> | ||
#include <stdexcept> | ||
#include <vector> | ||
#include "AbstractTlgReader.h" | ||
#include "BadMagicException.h" | ||
#include "Tlg0Reader.h" | ||
#include "Tlg5Reader.h" | ||
#include "Tlg6Reader.h" | ||
|
||
std::unique_ptr<const AbstractTlgReader> | ||
AbstractTlgReader::choose_reader(std::ifstream &ifs) | ||
{ | ||
std::vector<AbstractTlgReader*> readers | ||
{ | ||
new Tlg0Reader(), | ||
new Tlg5Reader(), | ||
new Tlg6Reader(), | ||
}; | ||
|
||
off_t pos = ifs.tellg(); | ||
for (auto reader : readers) | ||
{ | ||
try | ||
{ | ||
ifs.seekg(pos, ifs.beg); | ||
if (reader->is_magic_valid(ifs)) | ||
{ | ||
return std::unique_ptr<AbstractTlgReader>(reader); | ||
} | ||
} | ||
catch (BadMagicException const &e) | ||
{ | ||
continue; | ||
} | ||
} | ||
|
||
throw std::runtime_error("Not a TLG image"); | ||
} | ||
|
||
const Image AbstractTlgReader::read(std::string path) const | ||
{ | ||
std::ifstream ifs(path, std::ifstream::in | std::ifstream::binary); | ||
if (!ifs) | ||
throw std::runtime_error("Can\'t open " + path + " for reading"); | ||
|
||
try | ||
{ | ||
ifs.seekg(0, ifs.beg); | ||
if (!is_magic_valid(ifs)) | ||
throw BadMagicException(); | ||
auto ret = read_raw_data(ifs); | ||
ifs.close(); | ||
return ret; | ||
} | ||
catch (std::exception const &e) | ||
{ | ||
ifs.close(); | ||
throw; | ||
} | ||
} | ||
|
||
const bool AbstractTlgReader::is_magic_valid(std::ifstream &ifs) const | ||
{ | ||
bool result = false; | ||
auto magic_size = get_magic().size(); | ||
char *actual = new char[magic_size]; | ||
try | ||
{ | ||
ifs.seekg(0, ifs.beg); | ||
ifs.read(actual, magic_size); | ||
if (std::strncmp(actual, get_magic().data(), magic_size) != 0) | ||
if (std::strncmp(actual, get_magic().data(), magic_size) == 0) | ||
{ | ||
throw BadMagicException(); | ||
result = true; | ||
} | ||
return read_from_stream(ifs); | ||
} | ||
catch (std::exception const &e) | ||
{ | ||
delete[] actual; | ||
ifs.close(); | ||
throw; | ||
} | ||
delete[] actual; | ||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,26 @@ | ||
#ifndef ABSTRACT_TLG_READER_H_ | ||
#define ABSTRACT_TLG_READER_H_ | ||
#include <cstdint> | ||
#include <fstream> | ||
#include <memory> | ||
#include <string> | ||
#include "Image.h" | ||
|
||
class AbstractTlgReader | ||
{ | ||
friend class Tlg0Reader; | ||
|
||
public: | ||
virtual const std::string get_magic() const = 0; | ||
static std::unique_ptr<const AbstractTlgReader> | ||
choose_reader(std::ifstream &ifs); | ||
|
||
const Image read(std::string path) const; | ||
|
||
protected: | ||
virtual const Image read_from_stream(std::ifstream &stream) const = 0; | ||
private: | ||
virtual const Image read_raw_data(std::ifstream &stream) const = 0; | ||
|
||
virtual const std::string get_magic() const = 0; | ||
|
||
const bool is_magic_valid(std::ifstream &ifs) const; | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#include <cstring> | ||
#include <string> | ||
#include <iostream> | ||
#include <memory> | ||
#include <stdexcept> | ||
#include "Tlg0Reader.h" | ||
#include "Tlg5Reader.h" | ||
#include "Tlg6Reader.h" | ||
|
||
namespace | ||
{ | ||
std::string extract_string(char *&ptr) | ||
{ | ||
int length = 0; | ||
while (*ptr >= '0' && *ptr <= '9') | ||
{ | ||
length *= 10; | ||
length += *ptr++ - '0'; | ||
} | ||
|
||
if (*ptr != ':') | ||
return ""; | ||
ptr ++; | ||
|
||
std::string value; | ||
for (int i = 0; i < length; i ++) | ||
value += *ptr ++; | ||
|
||
return value; | ||
} | ||
|
||
void process_tag_chunk(std::unique_ptr<char> chunk_data, size_t chunk_size) | ||
{ | ||
char *start = chunk_data.get(); | ||
char *ptr = start; | ||
while (ptr < start + chunk_size) | ||
{ | ||
auto key = extract_string(ptr); | ||
ptr ++; | ||
auto value = extract_string(ptr); | ||
ptr ++; | ||
std::cout << "Tag found: " << key << " = " << value << std::endl; | ||
} | ||
} | ||
|
||
void process_chunks(std::ifstream &ifs) | ||
{ | ||
char chunk_name[4]; | ||
while (ifs.read(chunk_name, 4)) | ||
{ | ||
uint32_t chunk_size; | ||
ifs.read((char*) &chunk_size, 4); | ||
|
||
auto chunk_data = std::unique_ptr<char>(new char[chunk_size]); | ||
ifs.read(chunk_data.get(), chunk_size); | ||
if (std::strncmp(chunk_name, "tags", 4) == 0) | ||
{ | ||
process_tag_chunk(std::move(chunk_data), chunk_size); | ||
} | ||
} | ||
} | ||
} | ||
|
||
const std::string Tlg0Reader::get_magic() const | ||
{ | ||
return std::string("\x54\x4c\x47\x30\x2e\x30\x00\x73\x64\x73\x1a", 11); | ||
} | ||
|
||
const Image Tlg0Reader::read_raw_data(std::ifstream &ifs) const | ||
{ | ||
uint32_t raw_data_size; | ||
ifs.read((char*) &raw_data_size, 4); | ||
|
||
auto reader = AbstractTlgReader::choose_reader(ifs); | ||
auto ret = reader->read_raw_data(ifs); | ||
|
||
process_chunks(ifs); | ||
|
||
return ret; | ||
} |
Oops, something went wrong.