Files
PhysX4.1/kaplademo/source/demoFramework/BmpFile.cpp
2025-11-28 23:13:44 +05:30

211 lines
6.0 KiB
C++

//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
#include <stdio.h>
#include <stdlib.h>
#include "BmpFile.h"
static bool isBigEndian() { int i = 1; return *((char*)&i)==0; }
static unsigned short endianSwap(unsigned short nValue)
{
return (((nValue>> 8)) | (nValue << 8));
}
static unsigned int endianSwap(unsigned int i)
{
unsigned char b1, b2, b3, b4;
b1 = i & 255;
b2 = ( i >> 8 ) & 255;
b3 = ( i>>16 ) & 255;
b4 = ( i>>24 ) & 255;
return ((unsigned int)b1 << 24) + ((unsigned int)b2 << 16) + ((unsigned int)b3 << 8) + b4;
}
// -------------------------------------------------------------------
#pragma pack(1)
struct BMPHEADER {
unsigned short Type;
unsigned int Size;
unsigned short Reserved1;
unsigned short Reserved2;
unsigned int OffBits;
};
// Only Win3.0 BMPINFO (see later for OS/2)
struct BMPINFO {
unsigned int Size;
unsigned int Width;
unsigned int Height;
unsigned short Planes;
unsigned short BitCount;
unsigned int Compression;
unsigned int SizeImage;
unsigned int XPelsPerMeter;
unsigned int YPelsPerMeter;
unsigned int ClrUsed;
unsigned int ClrImportant;
};
#pragma pack()
// Compression Type
#define BI_RGB 0L
#define BI_RLE8 1L
#define BI_RLE4 2L
// -------------------------------------------------------------------
BmpLoaderBuffer::BmpLoaderBuffer()
{
mWidth = 0;
mHeight = 0;
mRGB = NULL;
}
// -------------------------------------------------------------------
BmpLoaderBuffer::~BmpLoaderBuffer()
{
if (mRGB) free(mRGB);
}
// -------------------------------------------------------------------
bool BmpLoaderBuffer::loadFile(const char *filename)
{
if (mRGB) {
free(mRGB);
mRGB = NULL;
}
mWidth = 0;
mHeight = 0;
FILE *f = fopen(filename, "rb");
if (!f)
return false;
size_t num;
BMPHEADER header;
num = fread(&header, sizeof(BMPHEADER), 1, f);
if(isBigEndian()) header.Type = endianSwap(header.Type);
if (num != 1) { fclose(f); return false; }
if (header.Type != 'MB') { fclose(f); return false; }
BMPINFO info;
num = fread(&info, sizeof(BMPINFO), 1, f);
if (num != 1) { fclose(f); return false; }
if(isBigEndian()) info.Size = endianSwap(info.Size);
if(isBigEndian()) info.BitCount = endianSwap(info.BitCount);
if(isBigEndian()) info.Compression = endianSwap(info.Compression);
if(isBigEndian()) info.Width = endianSwap(info.Width);
if(isBigEndian()) info.Height = endianSwap(info.Height);
if (info.Size != sizeof(BMPINFO)) { fclose(f); return false; }
if (info.BitCount != 24) { fclose(f); return false; }
if (info.Compression != BI_RGB) { fclose(f); return false; }
mWidth = info.Width;
mHeight = info.Height;
mRGB = (unsigned char*)malloc(mWidth * mHeight * 3);
int lineLen = (((info.Width * (info.BitCount>>3)) + 3)>>2)<<2;
unsigned char *line = (unsigned char *)malloc(lineLen);
for(int i = info.Height-1; i >= 0; i--) {
num = fread(line, lineLen, 1, f);
if (num != 1) { fclose(f); return false; }
unsigned char *src = line;
unsigned char *dest = mRGB + i*info.Width*3;
for(unsigned int j = 0; j < info.Width; j++) {
unsigned char r,g,b;
b = *src++; g = *src++; r = *src++;
*dest++ = r; *dest++ = g; *dest++ = b;
}
}
free(line);
fclose(f);
return true;
}
// -------------------------------------------------------------------
bool saveBmpRBG(const char *filename, int width, int height, void *data)
{
FILE *f = fopen(filename, "wb");
if (!f) return false;
// todo : works on pcs only, swap correctly if big endian
BMPHEADER header;
header.Type = 'MB';
header.Size = sizeof(BMPINFO);
header.Reserved1 = 0;
header.Reserved2 = 0;
header.OffBits = sizeof(BMPHEADER) + sizeof(BMPINFO);
fwrite(&header, sizeof(BMPHEADER), 1, f);
BMPINFO info;
info.Size = sizeof(BMPINFO);
info.Width = width;
info.Height = height;
info.Planes = 1;
info.BitCount = 24;
info.Compression = BI_RGB;
info.XPelsPerMeter = 4000;
info.YPelsPerMeter = 4000;
info.ClrUsed = 0;
info.ClrImportant = 0;
fwrite(&info, sizeof(info), 1, f);
// padded to multiple of 4
int lineLen = (((info.Width * (info.BitCount>>3)) + 3)>>2)<<2;
info.SizeImage = lineLen * height;
unsigned char *line = (unsigned char *)malloc(lineLen);
for(int i = 0; i < height; i++) {
unsigned char *src = (unsigned char*)data + i*width*3;
unsigned char *dest = line;
for(int j = 0; j < width; j++) {
unsigned char r,g,b;
r = *src++; g = *src++; b = *src++;
*dest++ = b; *dest++ = g; *dest++ = r;
}
for (int j = 3*width; j < lineLen; j++)
*dest++ = 0;
fwrite(line, lineLen, 1, f);
}
free(line);
fclose(f);
return true;
}