⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pixmap.cpp

📁 经典开源游戏glest的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ==============================================================
//	This file is part of Glest Shared Library (www.glest.org)
//
//	Copyright (C) 2001-2008 Marti駉 Figueroa
//
//	You can redistribute this code and/or modify it under 
//	the terms of the GNU General Public License as published 
//	by the Free Software Foundation; either version 2 of the 
//	License, or (at your option) any later version
// ==============================================================

#include "pixmap.h"

#include <stdexcept>
#include <cstdio>
#include <cassert>

#include "util.h"
#include "math_util.h"
#include "random.h"
#include "leak_dumper.h"

using namespace Shared::Util;
using namespace std;

namespace Shared{ namespace Graphics{

using namespace Util;

// =====================================================
//	file structs
// =====================================================

#pragma pack(push, 1)

struct BitmapFileHeader{ 
	uint8 type1; 
	uint8 type2; 
	uint32 size; 
	uint16 reserved1; 
	uint16 reserved2; 
	uint32 offsetBits; 
}; 

struct BitmapInfoHeader{
	uint32 size; 
	int32 width; 
	int32 height; 
	uint16 planes; 
	uint16 bitCount; 
	uint32 compression; 
	uint32 sizeImage; 
	int32 xPelsPerMeter; 
	int32 yPelsPerMeter; 
	uint32 clrUsed; 
	uint32 clrImportant; 
};

struct TargaFileHeader{
	int8 idLength;
	int8 colourMapType;
	int8 dataTypeCode;
	int16 colourMapOrigin;
	int16 colourMapLength;
	int8 colourMapDepth;
	int16 xOrigin;
	int16 yOrigin;
	int16 width;
	int16 height;
	int8 bitsPerPixel;
	int8 imageDescriptor;
};

#pragma pack(pop)

const int tgaUncompressedRgb= 2;
const int tgaUncompressedBw= 3;

// =====================================================
//	class PixmapIoTga
// =====================================================

PixmapIoTga::PixmapIoTga(){
	file= NULL;
}

PixmapIoTga::~PixmapIoTga(){
	if(file!=NULL){
		fclose(file);
	}
}

void PixmapIoTga::openRead(const string &path){
	file= fopen(path.c_str(),"rb"); 
	if (file==NULL){
		throw runtime_error("Can't open TGA file: "+ path);
	}
	
	//read header
	TargaFileHeader fileHeader;
	fread(&fileHeader, sizeof(TargaFileHeader), 1, file);
    
	//check that we can load this tga file
	if(fileHeader.idLength!=0){
		throw runtime_error(path + ": id field is not 0");
	}

	if(fileHeader.dataTypeCode!=tgaUncompressedRgb && fileHeader.dataTypeCode!=tgaUncompressedBw){
		throw runtime_error(path + ": only uncompressed BW and RGB targa images are supported"); 
	}

	//check bits per pixel
	if(fileHeader.bitsPerPixel!=8 && fileHeader.bitsPerPixel!=24 && fileHeader.bitsPerPixel!=32){
		throw runtime_error(path + ": only 8, 24 and 32 bit targa images are supported");
	}

	h= fileHeader.height;
    w= fileHeader.width;
	components= fileHeader.bitsPerPixel/8;
}

void PixmapIoTga::read(uint8 *pixels){
	read(pixels, components);
}

void PixmapIoTga::read(uint8 *pixels, int components){
	for(int i=0; i<h*w*components; i+=components){
		uint8 r, g, b, a, l;

		if(this->components==1){
			fread(&l, 1, 1, file);
			r= l;
			g= l;
			b= l;
			a= 255;
		}
		else{
			fread(&b, 1, 1, file);
			fread(&g, 1, 1, file);
			fread(&r, 1, 1, file);
			if(this->components==4){
				fread(&a, 1, 1, file);
			}
			else{
				a= 255;
			}
			l= (r+g+b)/3;
		}

		switch(components){
		case 1:
			pixels[i]= l;
			break;
		case 3:
			pixels[i]= r;
			pixels[i+1]= g;
			pixels[i+2]= b;
			break;
		case 4:
			pixels[i]= r;
			pixels[i+1]= g;
			pixels[i+2]= b;
			pixels[i+3]= a;
			break;
		}
	}
}

void PixmapIoTga::openWrite(const string &path, int w, int h, int components){
    this->w= w;
	this->h= h;
	this->components= components;

    file= fopen(path.c_str(),"wb"); 
	if (file==NULL){
		throw runtime_error("Can't open TGA file: "+ path);
	}

	TargaFileHeader fileHeader;
	memset(&fileHeader, 0, sizeof(TargaFileHeader));
	fileHeader.dataTypeCode= components==1? tgaUncompressedBw: tgaUncompressedRgb;
	fileHeader.bitsPerPixel= components*8;
	fileHeader.width= w;
	fileHeader.height= h;
	fileHeader.imageDescriptor= components==4? 8: 0;

	fwrite(&fileHeader, sizeof(TargaFileHeader), 1, file);
}

void PixmapIoTga::write(uint8 *pixels){
	if(components==1){
		fwrite(pixels, h*w, 1, file);	
	}
	else{
		for(int i=0; i<h*w*components; i+=components){
			fwrite(&pixels[i+2], 1, 1, file);
			fwrite(&pixels[i+1], 1, 1, file);
			fwrite(&pixels[i], 1, 1, file);
			if(components==4){
				fwrite(&pixels[i+3], 1, 1, file);
			}
		}
	}
}

// =====================================================
//	class PixmapIoBmp
// =====================================================

PixmapIoBmp::PixmapIoBmp(){
	file= NULL;
}

PixmapIoBmp::~PixmapIoBmp(){
	if(file!=NULL){
		fclose(file);
	}
}

void PixmapIoBmp::openRead(const string &path){
    file= fopen(path.c_str(),"rb"); 
	if (file==NULL){
		throw runtime_error("Can't open BMP file: "+ path);
	}

	//read file header
    BitmapFileHeader fileHeader;
    fread(&fileHeader, sizeof(BitmapFileHeader), 1, file);
	if(fileHeader.type1!='B' || fileHeader.type2!='M'){ 
		throw runtime_error(path +" is not a bitmap");
	}
    
	//read info header
	BitmapInfoHeader infoHeader;
	fread(&infoHeader, sizeof(BitmapInfoHeader), 1, file);
	if(infoHeader.bitCount!=24){
        throw runtime_error(path+" is not a 24 bit bitmap");
	}

    h= infoHeader.height;
    w= infoHeader.width;
	components= 3;
}

void PixmapIoBmp::read(uint8 *pixels){
	read(pixels, 3);
}

void PixmapIoBmp::read(uint8 *pixels, int components){
    for(int i=0; i<h*w*components; i+=components){
		uint8 r, g, b;
		fread(&b, 1, 1, file);
		fread(&g, 1, 1, file);
		fread(&r, 1, 1, file);

		switch(components){
		case 1:
			pixels[i]= (r+g+b)/3;
			break;
		case 3:
			pixels[i]= r;
			pixels[i+1]= g;
			pixels[i+2]= b;
			break;
		case 4:
			pixels[i]= r;
			pixels[i+1]= g;
			pixels[i+2]= b;
			pixels[i+3]= 255;
			break;
		}
    }
}

void PixmapIoBmp::openWrite(const string &path, int w, int h, int components){
    this->w= w;
	this->h= h;
	this->components= components;
	
	file= fopen(path.c_str(),"wb"); 
	if (file==NULL){
		throw runtime_error("Can't open BMP file for writting: "+ path);
	}

	BitmapFileHeader fileHeader;
    fileHeader.type1='B';
	fileHeader.type2='M';
	fileHeader.offsetBits=sizeof(BitmapFileHeader)+sizeof(BitmapInfoHeader);
	fileHeader.size=sizeof(BitmapFileHeader)+sizeof(BitmapInfoHeader)+3*h*w;

    fwrite(&fileHeader, sizeof(BitmapFileHeader), 1, file);
    
	//info header
	BitmapInfoHeader infoHeader;
	infoHeader.bitCount=24;
	infoHeader.clrImportant=0;
	infoHeader.clrUsed=0;
	infoHeader.compression=0;
	infoHeader.height= h;
	infoHeader.planes=1;
	infoHeader.size=sizeof(BitmapInfoHeader);
	infoHeader.sizeImage=0;
	infoHeader.width= w;
	infoHeader.xPelsPerMeter= 0;
	infoHeader.yPelsPerMeter= 0;

	fwrite(&infoHeader, sizeof(BitmapInfoHeader), 1, file);
}

void PixmapIoBmp::write(uint8 *pixels){
    for (int i=0; i<h*w*components; i+=components){
        fwrite(&pixels[i+2], 1, 1, file);
		fwrite(&pixels[i+1], 1, 1, file);
		fwrite(&pixels[i], 1, 1, file);
    }
}

// =====================================================
//	class Pixmap1D
// =====================================================


// ===================== PUBLIC ========================

Pixmap1D::Pixmap1D(){
    w= -1;
	components= -1;
    pixels= NULL;
}

Pixmap1D::Pixmap1D(int components){
	init(components);
}

Pixmap1D::Pixmap1D(int w, int components){
	init(w, components);
}

void Pixmap1D::init(int components){
	this->w= -1;
	this->components= components;
	pixels= NULL;
}

void Pixmap1D::init(int w, int components){
	this->w= w;
	this->components= components;
	pixels= new uint8[w*components];
}

Pixmap1D::~Pixmap1D(){
	delete [] pixels;
}

void Pixmap1D::load(const string &path){
	string extension= path.substr(path.find_last_of('.')+1);
	if(extension=="bmp"){
		loadBmp(path);
	}
	else if(extension=="tga"){
		loadTga(path);
	}
	else{
		throw runtime_error("Unknown pixmap extension: "+extension);
	}
}

void Pixmap1D::loadBmp(const string &path){
	
	PixmapIoBmp plb;
	plb.openRead(path);

	//init
	if(plb.getH()==1){
		w= plb.getW();
	}
	else if(plb.getW()==1){
		w= plb.getH();
	}
	else{
		throw runtime_error("One of the texture dimensions must be 1");
	}

	if(components==-1){
		components= 3;
	}
	if(pixels==NULL){
		pixels= new uint8[w*components]; 
	}

	//data
	plb.read(pixels, components);
}

void Pixmap1D::loadTga(const string &path){
	
	PixmapIoTga plt;
	plt.openRead(path);
	
	//init
	if(plt.getH()==1){
		w= plt.getW();
	}
	else if(plt.getW()==1){
		w= plt.getH();
	}
	else{
		throw runtime_error("One of the texture dimensions must be 1");
	}

	int fileComponents= plt.getComponents();

	if(components==-1){
		components= fileComponents;
	}
	if(pixels==NULL){
		pixels= new uint8[w*components]; 
	}

	//read data
	plt.read(pixels, components);
}

// =====================================================
//	class Pixmap2D
// =====================================================

// ===================== PUBLIC ========================

Pixmap2D::Pixmap2D(){
    h= -1;
    w= -1;
	components= -1;
    pixels= NULL;
}

Pixmap2D::Pixmap2D(int components){
	init(components);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -