#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
, вероятно, не требуется