Хочу из 24 bit конвертнуть в 1-bit, т.е чтобы было всего 2 цвета - белый и черный.
Т.е сначала нужно создать палитру из 2 цветов - черного и белого, а потом для каждого пикселя определить - к какому из этих двух цветов он относится.
Палитру и перевод пикселей я сделал - я даже двумя способами попробовал -
через grayscale и через среднюю яркость пикселя, но для 1 битовых изображений это вроде как неважно.
Проблема то не в этом - а в том, как мне после всех этих хитрых манипуляций записать изображение.
Т.е если я все верно понял - в таком черно-белом изображении хранятся только индексы палитры - т.е в моем случае 1 или 0 .
Но после трех значений R G B следует еще и значение для прозрачности, где обычно хранится 0.
т.е если моя палитра -
00 00 00 00 FF FF FF 00
и первый пиксель белый - то его индекс 1 , а если черный - то 0
т.е как я думал это должно выглядеть -
for (int i=0;i<BMInfoHeader.Height;i++)
for (int j=0;j<BMInfoHeader.Width;j++)
{
if (currbit>=7)//собрали байт
{
fwrite(&one_byte,1,1,f);//записали его
one_byte=0;//обнулили его
currbit=0;//обнулили счетчик для сдвига
}
if (Rgbtriple[i][j].Blue>100) //если больше опред. значения
{
one_byte|=(1<<currbit);//записываем 1
currbit++;
}
else currbit++;//иначе - 0 (т.е просто сдвигаем вправо)
}
fwrite(&one_byte,1,1,f);//дописываю последний байт
fclose(f);
Но это выдает нечто такое -
Оригинал -
Что я делаю не так?
UPD
Изменил на >=8 , теперь уже ближе к истине , но все равно эти лесенки мне не нравятся..
Вот код загрузки изображения -
int Image::loadimage(char *filename)
{
FILE *f;
int imageIdx=0; //image index counter
fopen_s(&f,filename,"rb");//открываем файл
if (f == NULL) return 0;//если не смогли открыть - вызвращаем код ошибки - 0
fread(&BMFileHeader, sizeof(BMFileHeader),1,f);//считали заголовок
if (BMFileHeader.Type !=0x4D42)//проверили - точно ли формат .bmp
{
fclose(f);
return 0;
}
fread(&BMInfoHeader, sizeof(BMInfoHeader),1,f); //считали информацию об изображении
//this->info();//вывели информацию
if (BMInfoHeader.BitCount == 1 || BMInfoHeader.BitCount==4 || BMInfoHeader.BitCount==8)//проверка на палитровое изображение
{
loadpaletteimg(f);
return 0;
}
fseek(f, BMFileHeader.OffsetBits, SEEK_SET); //переместили указатель в нужное место
if (BMInfoHeader.BitCount==24)
{
Rgbtriple=new RGBTRIPLE*[BMInfoHeader.Height];
Rgbquad=0;
for (int i = 0; i < BMInfoHeader.Height; i++)//построчно
{
Rgbtriple[i]=new RGBTRIPLE[BMInfoHeader.Width];
fread(Rgbtriple[i], sizeof(RGBTRIPLE), BMInfoHeader.Width, f);
}
if(Rgbtriple) cout<<"Изображение успешно загружено!"<<endl;
}
if (BMInfoHeader.BitCount==16)
{
Rgbquad=new RGBQUAD*[BMInfoHeader.Height];
Rgbtriple=0;
for (int i = 0; i < BMInfoHeader.Height; i++)//построчно
{
Rgbquad[i]=new RGBQUAD[BMInfoHeader.Width];
fread(Rgbquad[i], sizeof(RGBQUAD), BMInfoHeader.Width, f);
}
if(Rgbquad) cout<<"Изображение успешно загружено!"<<endl;
}
else return 0;
fclose(f);
return 1;
}
А как мне узнать, что строка не кратна 4 байтам ? Я же вроде побитово записываю...
UPD 2
Вот это работает ! =)
byte one_byte=0;
int currbit=0;
byte mask=0X80;
for (int i=0;i<BMInfoHeader.Height;i++)
for (int j=0;j<BMInfoHeader.Width;j++)
{
if (currbit>=8)//собрали байт
{
fwrite(&one_byte,1,1,f);//записали его
one_byte=0;
currbit=0;
}
if (Rgbtriple[i][j].Blue>100)
{
one_byte|=(mask>>currbit);
currbit++;
}
else currbit++;
}
fwrite(&one_byte,1,1,f);//дописываю последний байт
fclose(f);
}