ilda_dll.zip/ilda.cpp
#define ILDA_EXPORTS
#include "ilda.h"
#include "boost/utility.hpp"
#include "boost/assert.hpp"
#include "boost/shared_ptr.hpp"
#include "boost/shared_array.hpp"
#include "boost/optional.hpp"
#include "boost/foreach.hpp"
#include "boost/function.hpp"
#include "boost/bind.hpp"
#include <stdio.h>
#include <vector>
#include <numeric>
#include <windows.h>
namespace {
void put32bit(char *data, int n){
data[0] = ((char*)&n)[3];
data[1] = ((char*)&n)[2];
data[2] = ((char*)&n)[1];
data[3] = ((char*)&n)[0];
}
void put32bit(char *data, unsigned int n){
put32bit(data, *(int*)&n);
}
void put16bit(char *data, short n){
data[0] = ((char*)&n)[1];
data[1] = ((char*)&n)[0];
}
void put16bit(char *data, unsigned short n){
put16bit(data, *(short*)&n);
}
void put16bit(char *data, int n){
put16bit(data, *(short*)&n);
}
void put16bit(char *data, unsigned int n){
put16bit(data, *(short*)&n);
}
void put8bit(char *data, char n){
*data = n;
}
void put8bit(char *data, unsigned char n){
put8bit(data, *(char*)&n);
}
void put8bit(char *data, int n){
put8bit(data, *(char*)&n);
}
void put8bit(char *data, unsigned int n){
put8bit(data, *(char*)&n);
}
int Read32Bit(const char *data){
int ret;
((char*)&ret)[0] = data[3];
((char*)&ret)[1] = data[2];
((char*)&ret)[2] = data[1];
((char*)&ret)[3] = data[0];
return ret;
}
short Read16Bit(const char *data){
short ret;
((char*)&ret)[0] = data[1];
((char*)&ret)[1] = data[0];
return ret;
}
char Read8Bit(const char *data){
return *data;
}
unsigned int Read32BitU(const char *data) {
int result = Read32Bit(data);
return *(unsigned int*)&result;
}
unsigned short Read16BitU(const char *data) {
short result = Read16Bit(data);
return *(unsigned short*)&result;
}
unsigned char Read8BitU(const char *data) {
char result = Read8Bit(data);
return *(unsigned char*)&result;
}
void MyFClose(FILE *fp) {
if(fp) {
::fclose(fp);
}
}
boost::shared_ptr<FILE> MyFOpen(const char *filename, const char *type) {
return boost::shared_ptr<FILE>(::fopen(filename, type), &MyFClose);
}
} // anonymous
class Color : boost::noncopyable{
public:
Color(unsigned char r, unsigned char g, unsigned char b) :
r(r), g(g), b(b)
{
}
~Color() {
}
static Color *Read(const char *data, unsigned int *length) {
if(data == NULL || length == NULL) {
return NULL;
}
const unsigned char r = Read8BitU(&data[0]);
const unsigned char g = Read8BitU(&data[1]);
const unsigned char b = Read8BitU(&data[2]);
Color * const result = new Color(r, g, b);
*length = result->Size();
return result;
}
static Color *Read(boost::shared_ptr<FILE> fp) {
if(!fp) {
return NULL;
}
std::vector<char> data(Size());
if(::fread(&data.front(), 1, data.size(), fp.get()) != data.size()) {
return NULL;
}
unsigned int read_size;
Color * const result = Read(&data.front(), &read_size);
if(!result || read_size != data.size()) {
return NULL;
}
return result;
}
unsigned char GetRed(void) const {
return r;
}
unsigned char GetGreen(void) const {
return g;
}
unsigned char GetBlue(void) const {
return b;
}
bool Put(char *data, unsigned int *length) const {
if(data == NULL || length == NULL) {
return false;
}
((unsigned char*)data)[0] = r;
((unsigned char*)data)[1] = g;
((unsigned char*)data)[2] = b;
*length = Size();
return true;
}
bool Put(FILE *fp) const {
if(fp == NULL) {
return false;
}
char data[3];
return (puts(data) && (fwrite(data,1,3,fp) == 3));
}
static unsigned int Size() {
return 3;
}
protected:
const unsigned char r;
const unsigned char g;
const unsigned char b;
};
class PaletteHeader : boost::noncopyable {
public:
PaletteHeader(unsigned int format_id, const std::string& name, const std::string& company, unsigned int color_count, unsigned int palette_id, unsigned int scan_head) :
format_id(format_id), name(name), company(company), color_count(color_count), palette_id(palette_id), scan_head(scan_head)
{
BOOST_ASSERT(name.size() <= 8);
BOOST_ASSERT(company.size() <= 8);
}
~PaletteHeader() {
}
static PaletteHeader *Read(const char *data, unsigned int *length) {
if(data == NULL || length == NULL) {
return NULL;
}
//CheckID
if(strncmp(data, "ILDA", 4) != 0) {
char Identity[5];
strncpy(Identity, data, 4);
Identity[4] = '\0';
printf("Not Identity:%s\n", Identity);
return NULL;
}
data += 4;
const unsigned int format_id = Read32BitU(data);
if(format_id != 2 && format_id != 3){
printf("Undefind Format ID:%d\n", format_id);
return NULL;
}
data += 4;
std::string name(data, 8);
data += 8;
std::string company(data, 8);
data += 8;
const unsigned int color_count = Read16BitU(data);
data += 2;
const unsigned int palette_id = Read16BitU(data);
data += 2;
const unsigned short yoyaku = Read16BitU(data);
if(yoyaku != 0){
printf("yoyaku error:%d\n", yoyaku);
return NULL;
}
data += 2;
const unsigned int scan_head = Read8BitU(data);
data += 1;
const unsigned char yoyaku2 = Read8BitU(data);
if(yoyaku2 != 0){
printf("yoyaku2 error:%d\n", yoyaku2);
return NULL;
}
data += 1;
PaletteHeader * const result = new PaletteHeader(format_id, name, company, color_count, palette_id, scan_head);
BOOST_ASSERT(result);
*length = result->Size();
return result;
}
bool Put(char *data, unsigned int *length) const {
if(data == NULL || length == NULL) {
return false;
}
strcpy(data, "ILDA");//ファイル識別子
data += 4;
put32bit(data, format_id);//フォーマットコード(カラーパレッド)
data += 4;
strncpy(data, name.c_str(), 8);//フレーム名
data += 8;
strncpy(data, company.c_str(), 8);//会社名
data += 8;
put16bit(data, color_count);//Total colors
data += 2;
put16bit(data, palette_id);//Palette number
data += 2;
put16bit(data, 0);//予備1
data += 2;
put16bit(data, scan_head);//スキャナーヘッド
data += 1;
put8bit(data, 0);//予備2
*length = Size();
return true;
}
bool Put(FILE *fp) const {
if(fp == NULL) {
return false;
}
std::vector<char> header(Size());
unsigned int head_size;
if(!Put(&header.front(), &head_size) || head_size != header.size() || fwrite(&header.front(), 1, head_size, fp) != head_size){
return false;
}
return true;
}
static unsigned int Size() {
return 32;
}
const unsigned int format_id;
const std::string name;
const std::string company;
const unsigned int color_count;
const unsigned int palette_id;
const unsigned int scan_head;
};
class Palette : boost::noncopyable {
public:
Palette(boost::shared_ptr<PaletteHeader> header, const std::vector<boost::shared_ptr<const Color> >& color_list) :
header(header), color_list(color_list)
{
BOOST_ASSERT(header);
BOOST_FOREACH(boost::shared_ptr<const Color> color, color_list) {
BOOST_ASSERT(color);
}
}
~Palette() {
}
static Palette *Read(const char *data, unsigned int *length) {
if(data == NULL || length == NULL) {
return NULL;
}
unsigned int header_size;
boost::shared_ptr<PaletteHeader> header(PaletteHeader::Read(data, &header_size));
data += header_size;
std::vector<boost::shared_ptr<const Color> > color_list;
for(unsigned int i = 0; i < header->color_count; i++){
unsigned int color_size;
boost::shared_ptr<Color> color(Color::Read(data, &color_size));
if(!color) {
return NULL;
}
data += color_size;
color_list.push_back(color);
}
Palette * const result = new Palette(header, color_list);
BOOST_ASSERT(result);
*length = result->Size();
return result;
}
static Palette *Read(boost::shared_ptr<FILE> fp, std::vector<char> readed_data = std::vector<char>()) {
if(!fp) {
return NULL;
}
boost::shared_ptr<PaletteHeader> header;
{
std::vector<char> data(readed_data);
data.resize(PaletteHeader::Size());
if(data.size() > readed_data.size()) {
const unsigned int read_size = data.size() - readed_data.size();
if(::fread(&data[readed_data.size()], 1, read_size, fp.get()) != read_size) {
return NULL;
}
} else if(data.size() < readed_data.size()) {
int pos = readed_data.size() - data.size();
fseek(fp.get(), pos, SEEK_CUR);
}
unsigned int header_size;
header.reset(PaletteHeader::Read(&data.front(), &header_size));
if(!header || data.size() != header_size) {
return NULL;
}
}
std::vector<boost::shared_ptr<const Color> > color_list;
for(unsigned int i = 0; i < header->color_count; i++){
boost::shared_ptr<Color> color(Color::Read(fp));
if(!color) {
return NULL;
}
color_list.push_back(color);
}
Palette * const result = new Palette(header, color_list);
BOOST_ASSERT(result);
return result;
}
bool Put(char *data, unsigned int *length) const {
if(data == NULL || length == NULL) {
return false;
}
unsigned int head_size;
if(!header->Put(data, &head_size)){
return false;
}
data += head_size;
*length = head_size;
BOOST_FOREACH(boost::shared_ptr<const Color> color, color_list) {
unsigned int color_size;
if(!color->Put(data, &color_size)){
return false;
}
data += color_size;
*length += color_size;
}
return true;
}
bool Put(FILE *fp) const {
if(fp == NULL) {
return false;
}
if(!header->Put(fp)){
return false;
}
BOOST_FOREACH(boost::shared_ptr<const Color> color, color_list) {
if(!color->Put(fp)){
return false;
}
}
return true;
}
unsigned int Size() const {
unsigned int result = header->Size();
BOOST_FOREACH(boost::shared_ptr<const Color> color, color_list) {
result += color->Size();
}
return result;
}
const boost::shared_ptr<PaletteHeader> header;
const std::vector<boost::shared_ptr<const Color> > color_list;
};
class Point : boost::noncopyable {
public:
Point(short x, short y, short z, unsigned char status, unsigned char color_id) :
is_xy_only(false), x(x), y(y), z(z), status(status), color_id(color_id)
{
BOOST_ASSERT((status&0x3F) == 0);
}
Point(short x, short y, unsigned char status, unsigned char color_id) :
is_xy_only(true), x(x), y(y), z(0), status(status), color_id(color_id)
{
BOOST_ASSERT((status&0x3F) == 0);
}
~Point() {
}
static Point *Read(const char *data, unsigned int *length, bool is_xy_only = false) {
if(data == NULL || length == NULL) {
return NULL;
}
const short x = Read16Bit(data);
data += 2;
const short y = Read16Bit(data);
data += 2;
short z;
if(!is_xy_only){
z = Read16Bit(data);
data += 2;
}
const unsigned char status = Read8BitU(data);
if((status&0x3F) != 0) {
printf("invalid status flag %08x\n", status);
return NULL;
}
data += 1;
const unsigned char color_id = Read8BitU(data);
data += 1;
Point *result;
if(is_xy_only) {
result = new Point(x, y, status, color_id);
} else {
result = new Point(x, y, z, status, color_id);
}
BOOST_ASSERT(result);
*length = result->Size();
return result;
}
static Point *Read(boost::shared_ptr<FILE> fp, bool is_xy_only = false) {
if(!fp) {
return NULL;
}
std::vector<char> data(Size(is_xy_only));
if(::fread(&data.front(), 1, data.size(), fp.get()) != data.size()) {
return NULL;
}
unsigned int read_size;
Point * const result = Read(&data.front(), &read_size, is_xy_only);
if(!result || data.size() != read_size) {
return NULL;
}
return result;
}
bool Put(char *data, unsigned int *length) const {
if(data == NULL || length == NULL) {
return false;
}
put16bit(data, x);
data += 2;
put16bit(data, y);
data += 2;
if(!is_xy_only){
put16bit(data, z);
data += 2;
}
put8bit(data, status);
data += 1;
put8bit(data, color_id);
*length = Size();
return true;
}
bool Put(FILE *fp) const {
if(fp == NULL) {
return false;
}
std::vector<char> data(Size());
unsigned int put_size;
if(!Put(&data.front(), &put_size) || put_size != data.size() || fwrite(&data.front(), 1, put_size, fp) != put_size){
return false;
}
return true;
}
unsigned int Size() const {
return Size(is_xy_only);
}
static unsigned int Size(bool is_xy_only) {
return 6 + (is_xy_only ? 0 : 2);
}
const bool is_xy_only;
const short x;
const short y;
const short z;
const unsigned char status;
const unsigned char color_id;
};
class FrameHeader {
public:
FrameHeader(const std::string& name, const std::string& company, unsigned int format_id, unsigned int point_count, unsigned int frame_number, unsigned int all_frame_count, unsigned int scan_head) :
name(name), company(company), format_id(format_id), point_count(point_count), frame_number(frame_number), all_frame_count(all_frame_count), scan_head(scan_head)
{
BOOST_ASSERT(name.size() <= 8);
BOOST_ASSERT(company.size() <= 8);
BOOST_ASSERT(frame_number < all_frame_count);
}
~FrameHeader() {
}
static FrameHeader *Read(const char *data, unsigned int *length) {
if(data == NULL || length == NULL) {
return NULL;
}
//check id
if(strncmp(data, "ILDA", 4) != 0) {
char Identity[5];
strncpy(Identity, data, 4);
Identity[4] = '\0';
printf("Not Identity:%s\n", Identity);
return NULL;
}
data += 4;
const unsigned int format_id = Read32BitU(data);
if(format_id != 0 && format_id != 1){
printf("invalid format_id &d\n", format_id);
return NULL;
}
data += 4;
const std::string name(data, 8);
data += 8;
const std::string company(data, 8);
data += 8;
const unsigned int point_count = Read16BitU(data);
data += 2;
const unsigned int frame_number = Read16BitU(data);
data += 2;
const unsigned int all_frame_count = Read16BitU(data);
data += 2;
const unsigned char scan_head = Read8BitU(data);
data += 1;
const unsigned char yoyaku = Read8BitU(data);
if(yoyaku != 0){
return NULL;
}
data += 1;
FrameHeader * const result = new FrameHeader(name, company, format_id, point_count, frame_number, all_frame_count, scan_head);
BOOST_ASSERT(result);
*length = result->Size();
return result;
}
static unsigned int Size(void) {
return 32;
}
bool Put(char *data, unsigned int *length) const {
if(data == NULL || length == NULL) {
return false;
}
strcpy(data, "ILDA");
data += 4;
put32bit(data, format_id);
data += 4;
strncpy(data, name.c_str(), 8);//フレーム名
data += 8;
strncpy(data, company.c_str(), 8);//会社名
data += 8;
put16bit(data, point_count);//総ポイント数
data += 2;
put16bit(data, frame_number);//フレーム番号
data += 2;
put16bit(data, all_frame_count);//総フレーム数
data += 2;
put8bit(data, scan_head);//スキャナヘッド
data += 1;
put8bit(data, 0);//予約
*length = Size();
return true;
}
const std::string name;
const std::string company;
const unsigned int format_id;
const unsigned int point_count;
const unsigned int frame_number;
const unsigned int all_frame_count;
const unsigned int scan_head;
};
class Frame {
public:
Frame(boost::shared_ptr<const FrameHeader> header, boost::shared_ptr<FILE> fp) :
header(header), fp(fp), point_addr(ftell(fp.get())), point_list(boost::none)
{
BOOST_ASSERT(header);
BOOST_ASSERT(fp);
}
Frame(boost::shared_ptr<const FrameHeader> header, const std::vector<boost::shared_ptr<const Point> >& point_list) :
header(header), point_addr(0), point_list(point_list)
{
BOOST_ASSERT(header);
}
~Frame() {
}
static Frame *Read(const char *data, unsigned int *length) {
if(data == NULL || length == NULL) {
return NULL;
}
unsigned int header_size;
boost::shared_ptr<const FrameHeader> header(FrameHeader::Read(data, &header_size));
if(!header) {
return NULL;
}
const bool is_xy_only = (header->format_id == 1);
std::vector<boost::shared_ptr<const Point> > point_list;
for(unsigned int i = 0; i < header->point_count; i++) {
unsigned int point_size;
boost::shared_ptr<const Point> point(Point::Read(data, &point_size, is_xy_only));
if(!point){
return NULL;
}
data += point_size;
point_list.push_back(point);
}
Frame * const result = new Frame(header, point_list);
BOOST_ASSERT(result);
*length = result->Size();
return result;
}
static Frame *Read(boost::shared_ptr<FILE> fp, const std::vector<char>& readed_data = std::vector<char>()) {
if(!fp) {
return NULL;
}
boost::shared_ptr<const FrameHeader> header;
{
std::vector<char> data(readed_data);
data.resize(FrameHeader::Size());
if(readed_data.size() < data.size()) {
const unsigned int read_size = data.size() - readed_data.size();
if(::fread(&data[readed_data.size()], 1, read_size, fp.get()) != read_size) {
return NULL;
}
} else if(data.size() < readed_data.size()) {
int pos = readed_data.size() - data.size();
fseek(fp.get(), pos, SEEK_CUR);
}
unsigned int header_size;
header.reset(FrameHeader::Read(&data.front(), &header_size));
if(!header || header_size != data.size()) {
return NULL;
}
}
Frame * const result = new Frame(header, fp);
BOOST_ASSERT(result);
const bool is_xy_only = (header->format_id == 1);
::fseek(fp.get(), Point::Size(is_xy_only) * header->point_count, SEEK_CUR);
return result;
}
bool Put(char *data, unsigned int *length) const {
if(data == NULL || length == NULL) {
return false;
}
unsigned int header_size;
if(!header->Put(data, &header_size)){
return false;
}
data += header_size;
BOOST_FOREACH(boost::shared_ptr<const Point> point, GetPointList()) {
unsigned int point_size;
if(!point->Put(data, &point_size)){
return false;
}
data += point_size;
}
*length = Size();
return true;
}
bool Put(FILE *fp) const {
if(fp == NULL) {
return false;
}
std::vector<char> data(FrameHeader::Size());
unsigned int header_size;
if(!header->Put(&data.front(), &header_size) || header_size != data.size() || fwrite(&data.front(), 1, header_size, fp) != header_size){
return false;
}
BOOST_FOREACH(boost::shared_ptr<const Point> point, GetPointList()) {
if(!point->Put(fp)){
return false;
}
}
return true;
}
unsigned int Size() const {
unsigned int result = header->Size();
const bool is_xy_only = (header->format_id == 1);
result += Point::Size(is_xy_only) * header->point_count;
return result;
}
std::vector<boost::shared_ptr<const Point> > GetPointList(void) const {
if(point_list) {
return point_list.get();
}
::fseek(fp.get(), point_addr, SEEK_SET);
const bool is_xy_only = (header->format_id == 1);
std::vector<boost::shared_ptr<const Point> > point_list;
for(unsigned int i = 0; i < header->point_count; i++) {
boost::shared_ptr<const Point> point(Point::Read(fp, is_xy_only));
BOOST_ASSERT(point);
point_list.push_back(point);
}
return point_list;
}
const boost::shared_ptr<const FrameHeader> header;
protected:
const boost::shared_ptr<FILE> fp;
const unsigned int point_addr;
const boost::optional<std::vector<boost::shared_ptr<const Point> > > point_list;
};
class ILDA : boost::noncopyable {
public:
ILDA(const std::vector<boost::shared_ptr<const Palette> >& palette_list, const std::vector<boost::shared_ptr<const Frame> >& frame_list) :
palette_list(palette_list), frame_list(frame_list)
{
BOOST_FOREACH(boost::shared_ptr<const Frame> frame, frame_list) {
BOOST_ASSERT(frame);
}
BOOST_FOREACH(boost::shared_ptr<const Palette> palette, palette_list) {
BOOST_ASSERT(palette);
}
}
~ILDA() {
}
enum ILDA_TYPE {
ILDA_TYPE_FRAME,
ILDA_TYPE_PALETTE,
ILDA_TYPE_UNKNOWN,
ILDA_TYPE_END,
};
static ILDA_TYPE CheckILDA(const char *data) {
if(strcmp(data,"ILDA") != 0) {
return ILDA_TYPE_END;
}
data += 4;
const unsigned int format_id = Read32BitU(data);
data += 4;
switch(format_id){
case 0:
case 1:
return ILDA_TYPE_FRAME;
case 3:{
unsigned int i = 8;
bool flag = true;
while(i < 24){
flag = flag && 0x20 <= data[i] && data[i] <= 0x79;
i++;
}
if(!flag){
break;
}
//先頭16字がASCIIだったら、独自拡張版フォーマットID3だと認識してpaletteを読み込む
}
case 2:
return ILDA_TYPE_PALETTE;
}
return ILDA_TYPE_UNKNOWN;
}
static ILDA *ReadImpl(boost::function<bool (std::vector<boost::shared_ptr<const Palette> > *, std::vector<boost::shared_ptr<const Frame> > *)> read_proc) {
std::vector<boost::shared_ptr<const Palette> > palette_list;
std::vector<boost::shared_ptr<const Frame> > frame_list;
if(!read_proc(&palette_list, &frame_list)) {
return false;
}
ILDA * const result = new ILDA(palette_list, frame_list);
BOOST_ASSERT(result);
return result;
}
static bool MemoryRead(const char *data, std::vector<boost::shared_ptr<const Palette> > *palette_list, std::vector<boost::shared_ptr<const Frame> > *frame_list) {
ILDA_TYPE type;
while((type = CheckILDA(data)) != ILDA_TYPE_END){
switch(type){
case ILDA_TYPE_FRAME: {
unsigned int frame_size;
boost::shared_ptr<const Frame> frame(Frame::Read(data, &frame_size));
if(!frame){
return false;
}
data += frame_size;
frame_list->push_back(frame);
break;
}
case ILDA_TYPE_PALETTE:{
unsigned int palette_size;
boost::shared_ptr<const Palette> palette(Palette::Read(data, &palette_size));
if(!palette){
return false;
}
data += palette_size;
palette_list->push_back(palette);
break;
}
case ILDA_TYPE_UNKNOWN: {
unsigned int length = Read32BitU(data+8);
data += 12 + length;
break;
}
}
}
return true;
}
static bool FileRead(boost::shared_ptr<FILE> fp, std::vector<boost::shared_ptr<const Palette> > *palette_list, std::vector<boost::shared_ptr<const Frame> > *frame_list) {
std::vector<char> data(24);
ILDA_TYPE type;
while(::fread(&data.front(), 1, data.size(), fp.get()) == data.size() && (type = CheckILDA(&data.front())) != ILDA_TYPE_END){
switch(type){
case ILDA_TYPE_FRAME: {
boost::shared_ptr<const Frame> frame(Frame::Read(fp, data));
if(!frame){
return false;
}
frame_list->push_back(frame);
break;
}
case ILDA_TYPE_PALETTE:{
boost::shared_ptr<const Palette> palette(Palette::Read(fp, data));
if(!palette){
return false;
}
palette_list->push_back(palette);
break;
}
case ILDA_TYPE_UNKNOWN: {
unsigned int length = Read32BitU(&data[8]);
unsigned int current = ftell(fp.get());
::fseek(fp.get(), current - 12 + length, SEEK_SET);
break;
}
}
}
return true;
}
static ILDA *Read(const char *data, unsigned int *length) {
ILDA * const result = ReadImpl(boost::bind(&ILDA::MemoryRead, data, _1, _2));
*length = result->Size();
return result;
}
static ILDA *Read(boost::shared_ptr<FILE> fp) {
return ReadImpl(boost::bind(&ILDA::FileRead, fp, _1, _2));
}
static ILDA *Read(const char *filename) {
if(filename == NULL) {
return NULL;
}
boost::shared_ptr<FILE> fp = MyFOpen(filename, "rb");
if(!fp) {
return NULL;
}
return Read(fp);
}
bool Put(char *data, unsigned int *length) const {
if(data == NULL || length == NULL) {
return false;
}
std::vector<boost::shared_ptr<const Frame> >::const_iterator fi = frame_list.begin();
std::vector<boost::shared_ptr<const Palette> >::const_iterator pi = palette_list.begin();
while(fi != frame_list.end() || pi != palette_list.end()){
if(fi != frame_list.end()){
unsigned int frame_size;
if(!(*fi)->Put(data, &frame_size)){
return false;
}
data += frame_size;
++fi;
}
if(pi != palette_list.end()){
unsigned int palette_size;
if(!(*pi)->Put(data, &palette_size)){
return false;
}
data += palette_size;
++pi;
}
}
*length = Size();
return true;
}
bool Put(FILE *fp) const {
if(fp == NULL) {
return false;
}
std::vector<boost::shared_ptr<const Frame> >::const_iterator fi = frame_list.begin();
std::vector<boost::shared_ptr<const Palette> >::const_iterator pi = palette_list.begin();
while(fi != frame_list.end() || pi != palette_list.end()){
if(fi != frame_list.end()){
if(!(*fi)->Put(fp)){
return false;
}
++fi;
}
if(pi != palette_list.end()){
if(!(*pi)->Put(fp)){
return false;
}
++pi;
}
}
return true;
}
int Size() const {
unsigned int result = 0;
BOOST_FOREACH(boost::shared_ptr<const Frame> frame, frame_list) {
result += frame->Size();
}
BOOST_FOREACH(boost::shared_ptr<const Palette> palette, palette_list) {
result += palette->Size();
}
return result;
}
const std::vector<boost::shared_ptr<const Palette> > palette_list;
const std::vector<boost::shared_ptr<const Frame> > frame_list;
};
std::vector<boost::shared_ptr<const ILDA> > ilda_list;
std::vector<struct ILDAPoint> ilda_point_list;
std::vector<unsigned int> ilda_point_count;
void ResizeIldaList(void) {
unsigned int i = 1;
unsigned int size = 0;
BOOST_FOREACH(boost::shared_ptr<const ILDA> ilda, ilda_list) {
if(ilda) {
size = i;
}
i++;
}
if(ilda_list.size() > size) {
ilda_list.resize(size);
}
}
ILDA_API ILDA_HANDLE ILDAOpenHandle(const char *filename) {
if(filename == NULL) {
return ILDA_INVALID_HANDLE;
}
boost::shared_ptr<const ILDA> ilda(ILDA::Read(filename));
if(!ilda) {
return ILDA_INVALID_HANDLE;
}
ilda_list.push_back(ilda);
const ILDA_HANDLE result = ilda_list.size() - 1;
return result;
}
ILDA_API ILDA_ERROR_ID ILDACloseHandle(ILDA_HANDLE handle) {
if(handle >= ilda_list.size() || handle < 0) {
return ILDA_ERROR_INVALID_HANDLE;
}
ilda_list[handle].reset();
ResizeIldaList();
return ILDA_ERROR_SUCCESS;
}
struct SumFramePointCount {
int operator() (const unsigned int value, boost::shared_ptr<const Frame> frame) const {
return value + frame->header->point_count;
}
};
ILDA_ERROR_ID SetILDAPointList(std::vector<boost::shared_ptr<const Frame> >::const_iterator start, std::vector<boost::shared_ptr<const Frame> >::const_iterator end, boost::optional<unsigned int> point_count_max = boost::none) {
unsigned int all_point_count;
if(!point_count_max) {
all_point_count = std::accumulate(start, end, (unsigned int)0, SumFramePointCount());
} else {
const unsigned int frame_count = end - start;
all_point_count = point_count_max.get() * frame_count;
}
ilda_point_list.resize(all_point_count);
std::vector<struct ILDAPoint>::iterator it = ilda_point_list.begin();
std::vector<boost::shared_ptr<const Frame> >::const_iterator frame = start;
while(frame != end) {
unsigned int i = 0;
BOOST_FOREACH(boost::shared_ptr<const Point> point, (*frame)->GetPointList()) {
if(point_count_max && point_count_max.get() == i) {
break;
}
it->x = (point->x + 32768) / 256;
it->y = (point->y + 32768) / 256;
it->blanking = (point->status & 0x40) ? 1 : 0;
++it;
i++;
}
while(point_count_max && point_count_max.get() > i) {
it->x = 128;
it->y = 128;
it->blanking = 0;
++it;
i++;
}
++frame;
}
return ILDA_ERROR_SUCCESS;
}
ILDA_ERROR_ID SetILDAPointCountList(std::vector<boost::shared_ptr<const Frame> >::const_iterator start, std::vector<boost::shared_ptr<const Frame> >::const_iterator end) {
const unsigned int size = end - start;
ilda_point_count.resize(size);
std::vector<unsigned int>::iterator it = ilda_point_count.begin();
std::vector<boost::shared_ptr<const Frame> >::const_iterator frame = start;
while(frame != end) {
*it = (*frame)->header->point_count;
++it;
++frame;
}
return ILDA_ERROR_SUCCESS;
}
ILDA_API ILDA_ERROR_ID GetPointData(ILDA_HANDLE handle, unsigned int first_frame, unsigned int frame_count, struct ILDAPoint **start_ptr, unsigned int **point_count_list, unsigned int *read_frame) {
if(handle >= ilda_list.size() || handle < 0) {
return ILDA_ERROR_INVALID_HANDLE;
}
boost::shared_ptr<const ILDA> ilda = ilda_list[handle];
if(!ilda) {
return ILDA_ERROR_INVALID_HANDLE;
}
if(frame_count == 0 || start_ptr == NULL || point_count_list == NULL || read_frame == NULL) {
return ILDA_ERROR_INVALID_PARAMETER;
}
std::vector<boost::shared_ptr<const Frame> > frame_list = ilda->frame_list;
if(frame_list.size() <= first_frame) {
return ILDA_ERROR_FRAME_OVER;
}
if(frame_list.size() < first_frame + frame_count) {
*read_frame = frame_list.size() - first_frame;
} else {
*read_frame = frame_count;
}
const std::vector<boost::shared_ptr<const Frame> >::const_iterator start = frame_list.begin() + first_frame;
const std::vector<boost::shared_ptr<const Frame> >::const_iterator end = start + *read_frame;
ILDA_ERROR_ID error ;
if(error = SetILDAPointList(start, end)) {
return error;
}
if(error = SetILDAPointCountList(start, end)) {
return error;
}
if(ilda_point_list.empty()) {
*start_ptr = NULL;
} else {
*start_ptr = &ilda_point_list.front();
}
*point_count_list = &ilda_point_count.front();
return ILDA_ERROR_SUCCESS;
}
ILDA_API ILDA_ERROR_ID GetPointData2(ILDA_HANDLE handle, unsigned int first_frame, unsigned int frame_count, unsigned int point_count, struct ILDAPoint **start_ptr, unsigned int *read_frame) {
if(handle >= ilda_list.size() || handle < 0) {
return ILDA_ERROR_INVALID_HANDLE;
}
boost::shared_ptr<const ILDA> ilda = ilda_list[handle];
if(!ilda) {
return ILDA_ERROR_INVALID_HANDLE;
}
if(frame_count == 0 || start_ptr == NULL || read_frame == NULL) {
return ILDA_ERROR_INVALID_PARAMETER;
}
std::vector<boost::shared_ptr<const Frame> > frame_list = ilda->frame_list;
if(frame_list.size() <= first_frame) {
return ILDA_ERROR_FRAME_OVER;
}
if(frame_list.size() < first_frame + frame_count) {
*read_frame = frame_list.size() - first_frame;
} else {
*read_frame = frame_count;
}
const std::vector<boost::shared_ptr<const Frame> >::const_iterator start = frame_list.begin() + first_frame;
const std::vector<boost::shared_ptr<const Frame> >::const_iterator end = start + *read_frame;
ILDA_ERROR_ID error ;
if(error = SetILDAPointList(start, end, point_count)) {
return error;
}
if(ilda_point_list.empty()) {
*start_ptr = NULL;
} else {
*start_ptr = &ilda_point_list.front();
}
return ILDA_ERROR_SUCCESS;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}