mirror of
https://github.com/coderkei/akmenu-next.git
synced 2025-06-19 17:35:38 -04:00
130 lines
3.5 KiB
C++
130 lines
3.5 KiB
C++
/*
|
||
bmp15.cpp
|
||
Copyright (C) 2007 Acekard, www.acekard.com
|
||
Copyright (C) 2007-2009 somebody
|
||
Copyright (C) 2009 yellow wood goblin
|
||
|
||
SPDX-License-Identifier: GPL-3.0-or-later
|
||
*/
|
||
|
||
//<2F>
|
||
|
||
#include "bmp15.h"
|
||
#include <list>
|
||
#include <string>
|
||
#include "dbgtool.h"
|
||
|
||
cBMP15::cBMP15() : _width(0), _height(0), _pitch(0), _buffer(NULL) {}
|
||
|
||
cBMP15::cBMP15(u32 width, u32 height) : _width(0), _height(0), _pitch(0), _buffer(NULL) {
|
||
_width = width;
|
||
_height = height;
|
||
_pitch = (width + (width & 1)) << 1;
|
||
// u32 pitch = (((width*16)+31)>>5)<<2; // 通用算法?
|
||
}
|
||
|
||
cBMP15::~cBMP15() {
|
||
// dbg_printf( "cBMP15 %08x destructed\n", this );
|
||
}
|
||
|
||
cBMP15 createBMP15(u32 width, u32 height) {
|
||
cBMP15 bmp(width, height);
|
||
|
||
u32 pitch = bmp.pitch(); // 15bit bmp pitch 算法
|
||
// dbg_printf( "pitch: %d bytes\n", pitch );
|
||
// dbg_printf( "buffer %08x\n", bmp.buffer() );
|
||
|
||
u32 bufferSize = height * pitch;
|
||
if (bufferSize & 3) // 如果 bufferSize 不是按4字节对齐,就把他调整到对齐
|
||
bufferSize += 4 - (bufferSize & 3);
|
||
bmp._buffer = new u32[bufferSize >> 2];
|
||
return bmp;
|
||
}
|
||
|
||
typedef std::pair<std::string, cBMP15> str_bmp_pair;
|
||
typedef std::list<str_bmp_pair> str_bmp_list;
|
||
static str_bmp_list _bmpPool;
|
||
|
||
cBMP15 createBMP15FromMem(void* mem) {
|
||
return cBMP15();
|
||
}
|
||
|
||
cBMP15 createBMP15FromFile(const std::string& filename) {
|
||
// dbg_printf( "createBMP15FromFile (%s)\n", filename );
|
||
|
||
str_bmp_list::iterator it;
|
||
for (it = _bmpPool.begin(); it != _bmpPool.end(); ++it) {
|
||
if (filename == it->first) {
|
||
return it->second;
|
||
}
|
||
}
|
||
|
||
FILE* f = fopen(filename.c_str(), "rb");
|
||
if (NULL == f) {
|
||
dbg_printf("(%s) file does not exist\n", filename.c_str());
|
||
return cBMP15();
|
||
}
|
||
|
||
// 读取文件长度
|
||
fseek(f, 0, SEEK_END);
|
||
int fileSize = ftell(f);
|
||
|
||
if (-1 == fileSize) {
|
||
fclose(f);
|
||
return cBMP15();
|
||
}
|
||
|
||
u16 bmMark = 0;
|
||
fseek(f, 0, SEEK_SET);
|
||
fread(&bmMark, 1, 2, f);
|
||
if (bmMark != 0x4d42) { // 'B' 'M' header
|
||
dbg_printf("not a bmp file\n");
|
||
fclose(f);
|
||
return cBMP15();
|
||
}
|
||
|
||
// 找出bmp高和宽
|
||
u32 width = 0;
|
||
u32 height = 0;
|
||
fseek(f, 0x12, SEEK_SET);
|
||
fread(&width, 1, 4, f);
|
||
fseek(f, 0x16, SEEK_SET);
|
||
fread(&height, 1, 4, f);
|
||
// dbg_printf( "w:%d h:%d\n", width, height );
|
||
|
||
cBMP15 bmp = createBMP15(width, height);
|
||
|
||
u32 bmpDataOffset = 0;
|
||
fseek(f, 0x0a, SEEK_SET);
|
||
fread(&bmpDataOffset, 1, 4, f);
|
||
|
||
long position = bmpDataOffset;
|
||
fseek(f, position, SEEK_SET);
|
||
u16* pbuffer = ((u16*)bmp.buffer()) + (bmp.pitch() >> 1) * height - (bmp.pitch() >> 1);
|
||
|
||
for (u32 i = 0; i < height; ++i) {
|
||
fread(pbuffer, 1, bmp.pitch(), f);
|
||
position += bmp.pitch();
|
||
pbuffer -= bmp.pitch() >> 1;
|
||
fseek(f, position, SEEK_SET);
|
||
}
|
||
fclose(f);
|
||
|
||
pbuffer = (u16*)bmp.buffer();
|
||
for (u32 i = 0; i < height; ++i) {
|
||
for (u32 j = 0; j < (bmp.pitch() >> 1); ++j) {
|
||
u16 pixelColor = pbuffer[i * (bmp.pitch() >> 1) + j];
|
||
pixelColor = ((pixelColor & 0x7C00) >> 10) | ((pixelColor & 0x03E0)) |
|
||
((pixelColor & 0x1F) << 10);
|
||
pbuffer[i * (bmp.pitch() >> 1) + j] = pixelColor | (pixelColor ? BIT(15) : 0);
|
||
// dbg_printf("%d %d\n", j, i );
|
||
}
|
||
}
|
||
|
||
str_bmp_pair bmpPoolItem(std::string(filename), bmp);
|
||
_bmpPool.push_back(bmpPoolItem);
|
||
|
||
// dbg_printf( "load bmp success, %08x\n", bmp.buffer() );
|
||
return bmp;
|
||
}
|