Попытка найти высоту и ширину bmp-файла приводит к противоречивым результатам при обработке

#java #bit-manipulation #processing #bmp

Вопрос:

Я пытаюсь вручную нарисовать пиксели, которые я прочитал в файле .bmp.

Эта информация хранится в заголовке BMP. ширина изображения (4 байта — от 0x12 до 0x15), высота изображения (4 байта — от 0x16 до 0x19) и смещение для необработанных данных пикселей (4 байта — от 0xa до 0xd). Чтобы найти ширину и высоту, я использую это:

 byte[] bytes = loadBytes("ImageFile.bmp");
imageWidth =  ((bytes[0x12]) | (bytes[0x13])<<8 | (bytes[0x14])<<16 | (bytes[0x15])<<24) ;
imageHeight = ((bytes[0x16]) | (bytes[0x17])<<8 | (bytes[0x18])<<16 | (bytes[0x19])<<24) ;
offset = (bytes[0xa]) | (bytes[0xb])<<8 | (bytes[0xc])<<16 | (bytes[0xd])<<24;
size(imageWidth,imageHeight);  
 

после этого я получаю точные результаты: ширина изображения-600, высота изображения-780.

но для меньшего изображения bmp, 250×250, после того же вычисления я получаю ответ в дополнении 2: ширина изображения -6, а высота изображения -6.

это преобразование странно для меня,потому что, когда я просматриваю шестнадцатеричные данные с помощью notepad , я получаю:

 fa 00 00 00 fa 00 00 00  
 

они взяты из байтов 0x12 — 0x19.
они не хранятся в виде значений со знаком. Так почему же я читаю их как таковые?

И есть ли единственный способ получить фактические значения без знака независимо от фактического размера?

Спасибо!

Комментарии:

1. Вам нужно будет сделать их long . например long imageWidth = ((bytes[0x12]) | (bytes[0x13])<<8 | (bytes[0x14])<<16 | (bytes[0x15])<<24)) amp; 0xFFFFFFFFL; , напрашивается вопрос: почему вы делаете это «вручную»?

2. Вам также нужно будет «отменить подпись» каждого байта, но ниже будет проще:

3. Я хотел избежать использования long, потому что функция размера занимает 2 дюйма, поэтому мне пришлось бы их переделать. Причина, по которой я делаю это вручную, заключается в том, что это часть проекта сжатия для курса. Моя цель-сжать файл .bmp и иметь возможность отображать сжатое изображение без сохранения его на диске. Поэтому мне приходится рисовать его вручную

Ответ №1:

Смотрите мои комментарии выше о том, как сделать это трудным способом. Это намного проще:

 ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
bb.position(0x12);
int width = bb.getInt();
int height = bb.getInt();
 

Трудный путь:

 long imageWidth = bytes[0x12] amp; 0xFF | (bytes[0x13] amp; 0xFF) << 8 | (bytes[0x14] << 16) amp; 0xFF | (bytes[0x15] << 24) amp; 0xFF;
long imageHeight = bytes[0x16] amp; 0xFF | (bytes[0x17] amp; 0xFF) << 8 | (bytes[0x18] amp; 0xFF) << 16 | (bytes[0x19] amp; 0xFF) << 24;
 

Комментарии:

1. Это отлично сработало 🙂 Я использовал его, чтобы без особых усилий получить всю необходимую мне информацию из файла. Большое спасибо!

2. Без проблем. Я проделал нелегкий путь. Я не думаю, что это маловероятно, что размер может превышать Integer.MAX_VALUE , поэтому использование long , вероятно, не требуется