OberMeister
Смотри base64 encoding.
dudenator
эээ... а причем тут это.
OberMeister
Там занимаются ровно тем же самым. Конвертируют переменные разной битовой длины друг в друга.
Я сделал у ся в аллокаторе вместо тучи булов , тучу бит масок..
Создал клас у которого 2 метода. Гет и Сет.
И каждый в 2-х варианта
1: устанавливает/возврашает 1 бит на позицыи Н
2: устанавливает/возврашает М битов с Н позицы Н
Если надо реализацыя могу поискать..
зачем что то изобретать, если с++ то есть bitset
http://www.cplusplus.com/reference/stl/bitset/
я, будучи студентом, реализоввывал такую же задачу (подсматривая в исходники какого то из архиваторов)
сорри за "много букв" :)
//bitio_f.h #ifndef _BITIO_FILE_H_ #define _BITIO_FILE_H_ #include <stdio.h> #define READ_MODE 0 #define WRITE_MODE 1 class BitIOFile { private: int mode; FILE *f; int BitNumber; long long BitBuffer; // 8 byte public: BitIOFile(); ~BitIOFile( ); int create( char *filename); int open( char *filename); void put( long b, unsigned char n = 1); // n - count, n <= 32 long get( unsigned char n = 1); // n - count, n <= 32 void flush( ); void close( ); }; #endif //bitio_f.cpp #include <assert.h> #include "bitio_f.h" static unsigned bitmask[] = { 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff }; BitIOFile::BitIOFile( ) { assert( sizeof( long long) == 8); BitNumber = BitBuffer = 0; f = NULL; } BitIOFile::~BitIOFile( ) { close( ); } int BitIOFile::create( char *filename) { if ( f) close( ); mode = WRITE_MODE; f = fopen( filename, "wb+"); BitNumber = BitBuffer = 0; if ( !f) return 0; return 1; } int BitIOFile::open( char *filename) { if ( f) close( ); mode = READ_MODE; f = fopen( filename, "rb"); BitNumber = BitBuffer = 0; if ( !f) return 0; return 1; } void BitIOFile::put( long b, unsigned char n /*=1*/) { assert( n <= 32 && f); while( BitNumber >= 8) { fputc( BitBuffer & 0xff, f); BitNumber -= 8; BitBuffer >>= 8; } BitBuffer |= ( b & bitmask[n]) << BitNumber; BitNumber += n; } long BitIOFile::get( unsigned char n /*=1*/) { assert( n <= 32 && f); register long b; while( BitNumber < n) { BitBuffer |= ( long)fgetc( f) << BitNumber; BitNumber += 8; } b = BitBuffer & bitmask[n]; BitNumber -= n; BitBuffer >>= n; return b; } void BitIOFile::flush( ) { assert( f); if ( mode == READ_MODE) return; while( BitNumber > 0) { fputc( BitBuffer & 0xff, f); BitNumber -= 8; BitBuffer >>= 8; } } void BitIOFile::close( ) { if ( f) { flush( ); fclose( f); f = NULL; } } //test.cpp #include <stdio.h> #include "bitio_f.h" int main( ) { int i, j; BitIOFile f; //create & write f.create( "test.bin"); for ( i = 0; i < 10; ++i) f.put( i, 12); f.close( ); //open & read f.open( "test.bin"); for ( i = 0; i < 10; ++i) { j = f.get( 12); printf( "%d\n", j); } f.close( ); return 0; }
Оператор ведь можно сделать как-то так:
bool& operator[](int index);?
Тогда вроде бы можно будет устанавливать значения? Или тут как со static_cast?
Если совсем нефиг делать можно нахимичить 1 хрень..
Создать клас который хранит индекс бита, указатель на битмаску и Бул
Потом приблизительно так
struct bitclass
{
void* _ptr;
uint _pos;
bool status;
bitclass(void* ptr,uint pos): _ptr(ptr), _pos(pos) {};
~bitclass() { *((long long*)_ptr) |= status==1?0x1:0 << pos; };
bitclass& operator =(bool value) { status = value; return *this; };
};
bitclass& operator[](uint pos)
{
// mask - our bitmask.. for ex. int;
return bitclass(&mask,pos);
};
как оно работает!!!
конструктор - думаю все ясно!
деструктор - самое веселое, после ретурна в той строке кода где был вызов переменная будет сушиствовать и может менять значение, само пресвоение значения будет срабатівать именно в деструкторе!!!
Код написал только что на коленке.. на компил не провирял, но знаю что идея работает)
Сегодня утром написал то что нужно...
void bitwrite(short n,int numbit) { unsigned int byte,bit; if( n > ( 1<<numbit)) return; for( int i = 0; i < numbit; i++) { byte = ( i+pos_write) / 8; bit = ( i+pos_write) % 8; //printf("%i %i = %i\n",byte,bit,!!(n&(1<<i))); // debug buffer[byte] |= !!( n&( 1<<i)) ? ( 1<<bit) : 0; } pos_write += numbit; } short bitread( int numbit) { unsigned int byte,bit; short out = 0; for( int i = 0; i < numbit; i++) { byte = ( i+pos_read) / 8; bit = ( i+pos_read) % 8; out |= !!( buffer[byte]&( 1<<bit)) ? ( 1<<i) : 0; } pos_read += numbit; return out; }
Всем спасибо!
2OberMeister
видно тебе это для компресии
видел решения без извратов, и выглядят норм, но не знаю подойдет тебе или нет. Основанны на паттерне потока, ты кидаешь туда инт и колличество валидных байт, и так же достаешь. а внутри тупо длинный буфер, можно даже вектор int, чтобы память за тебя рулилась, и тупо сдвигами, но тут без произвольного доступа, именно записал, и считал, аккурат серелизация.
my.name
>видно тебе это для компресии
Именно. допустим мне нужна переменная с размером 512, придется взять short (16 бит) или же взять 9 бит.
>но не знаю подойдет тебе или нет.
Просто не хочу копать глубоко, может задумка и не оправдается.
Если тебе нужна просто переменная, то бери int, и не задумывайся даже про её размер, пока она одна никто и не заметит эти полтора байта экономии.
А если тебе надо упаковать стопицот записей в наименьший объём, тогда начинай морочить себе голову с битовыми полями и алгоритмами сжатия.
Просто напиши функцию, которая сожмет массив интов до желаемого размера (оставив от каждого элемента столько бит, сколько тебе хочется).
И еще напиши функцию для разжимания.
Вот и все.
Сложные классы, перегруженные операторы и имитация переменных с неродным количеством битов в байте - нахрен не надо.
kvakvs
Конишуа
Все уже решено!
При первых тестах все заработало с первого раза, обычно так не бывает :)
ЗЫ. Результат первых тестов: на максимальном качестве - сжатие в ~2 раза, опять же % сжатия зависит от сложности рисунка.
OberMeister
> ЗЫ. Результат первых тестов: на максимальном качестве - сжатие в ~2 раза, опять же % сжатия зависит от сложности рисунка.
Без указания типа рисунка нельзя ничего сказать, но если это принтскрин виндовских окошек или рыготня в Пеинте из нескольких нажатий, то это не результат :)
Тема в архиве.