阅读新闻

地形教程 - TGA库源代码

[日期:2007-03-31] 来源:  作者: [字体: ]
         
Terrain Tutorial
地形教程

Source Code for the TGA library
TGA库源代码


You may use this library for whatever you want. This library is provide as is, meaning that I won't take any responsability for any damages that you may incur from its usage.
你可以随便怎么使用这个库,但我不承担这个库的bug给你带了的损失。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "tga.h"

// this variable is used for image series
static int savedImages=0;

// load the image header fields. We only keep those that matter!
void tgaLoadHeader(FILE *file, tgaInfo *info) {

  unsigned char cGarbage;
  short int iGarbage;

  fread(&cGarbage, sizeof(unsigned char), 1, file);
  fread(&cGarbage, sizeof(unsigned char), 1, file);

// type must be 2 or 3
  fread(&info->type, sizeof(unsigned char), 1, file);

  fread(&iGarbage, sizeof(short int), 1, file);
  fread(&iGarbage, sizeof(short int), 1, file);
  fread(&cGarbage, sizeof(unsigned char), 1, file);
  fread(&iGarbage, sizeof(short int), 1, file);
  fread(&iGarbage, sizeof(short int), 1, file);

  fread(&info->width, sizeof(short int), 1, file);
  fread(&info->height, sizeof(short int), 1, file);
  fread(&info->pixelDepth, sizeof(unsigned char), 1, file);

  fread(&cGarbage, sizeof(unsigned char), 1, file);
}

// loads the image pixels. You shouldn't call this function
// directly
void tgaLoadImageData(FILE *file, tgaInfo *info) {

  int mode,total,i;
  unsigned char aux;

// mode equal the number of components for each pixel
  mode = info->pixelDepth / 8;
// total is the number of bytes we'll have to read
  total = info->height * info->width * mode;
  
  fread(info->imageData,sizeof(unsigned char),total,file);

// mode=3 or 4 implies that the image is RGB(A). However TGA
// stores it as BGR(A) so we'll have to swap R and B.
  if (mode >= 3)
    for (i=0; i < total; i+= mode) {
      aux = info->imageData[i];
      info->imageData[i] = info->imageData[i+2];
      info->imageData[i+2] = aux;
    }
}  

// this is the function to call when we want to load
// an image
tgaInfo * tgaLoad(char *filename) {
  
  FILE *file;
  tgaInfo *info;
  int mode,total;

// allocate memory for the info struct and check!
  info = (tgaInfo *)malloc(sizeof(tgaInfo));
  if (info == NULL)
    return(NULL);

// open the file for reading (binary mode)
  file = fopen(filename, "rb");
  if (file == NULL) {
    info->status = TGA_ERROR_FILE_OPEN;
    return(info);
  }

// load the header
  tgaLoadHeader(file,info);

// check for errors when loading the header
  if (ferror(file)) {
    info->status = TGA_ERROR_READING_FILE;
    fclose(file);
    return(info);
  }

// check if the image is color indexed
  if (info->type == 1) {
    info->status = TGA_ERROR_INDEXED_COLOR;
    fclose(file);
    return(info);
  }
// check for other types (compressed images)
  if ((info->type != 2) && (info->type !=3)) {
    info->status = TGA_ERROR_COMPRESSED_FILE;
    fclose(file);
    return(info);
  }

// mode equals the number of image components
  mode = info->pixelDepth / 8;
// total is the number of bytes to read
  total = info->height * info->width * mode;
// allocate memory for image pixels
  info->imageData = (unsigned char *)malloc(sizeof(unsigned char) *
                total);

// check to make sure we have the memory required
  if (info->imageData == NULL) {
    info->status = TGA_ERROR_MEMORY;
    fclose(file);
    return(info);
  }
// finally load the image pixels
  tgaLoadImageData(file,info);

// check for errors when reading the pixels
  if (ferror(file)) {
    info->status = TGA_ERROR_READING_FILE;
    fclose(file);
    return(info);
  }
  fclose(file);
  info->status = TGA_OK;
  return(info);
}    

// converts RGB to greyscale
void tgaRGBtogreyscale(tgaInfo *info) {

  int mode,i,j;

  unsigned char *newImageData;

// if the image is already greyscale do nothing
  if (info->pixelDepth == 8)
    return;

// compute the number of actual components
  mode = info->pixelDepth / 8;

// allocate an array for the new image data
  newImageData = (unsigned char *)malloc(sizeof(unsigned char) *
            info->height * info->width);
  if (newImageData == NULL) {
    return;
  }

// convert pixels: greyscale = o.30 * R + 0.59 * G + 0.11 * B
  for (i = 0,j = 0; j < info->width * info->height; i +=mode, j++)
    newImageData[j] =  
      (unsigned char)(0.30 * info->imageData[i] +
          0.59 * info->imageData[i+1] +
          0.11 * info->imageData[i+2]);

//free old image data
  free(info->imageData);

// reassign pixelDepth and type according to the new image type
  info->pixelDepth = 8;
  info->type = 3;
// reassing imageData to the new array.
  info->imageData = newImageData;
}

// takes a screen shot and saves it to a TGA image
int tgaGrabScreenSeries(char *filename, int xmin,int ymin, int xmax, int ymax) {
  
  int w, h;
  unsigned char *imageData;

// compute width and heidth of the image
  w = xmax - xmin;
  h = ymax - ymin;

// allocate memory for the pixels
  imageData = (unsigned char *)malloc(sizeof(unsigned char) * w * h * 4);

// read the pixels from the frame buffer
  glReadPixels(xmin,ymin,xmax,ymax,GL_RGBA,GL_UNSIGNED_BYTE, (GLvoid *)imageData);

// save the image
  return(tgaSaveSeries(filename,w,h,32,imageData));
}

// saves an array of pixels as a TGA image
int tgaSave(  char     *filename,
    short int  width,
    short int  height,
    unsigned char  pixelDepth,
    unsigned char  *imageData) {

  unsigned char cGarbage = 0, type,mode,aux;
  short int iGarbage = 0;
  int i;
  FILE *file;

// open file and check for errors
  file = fopen(filename, "wb");
  if (file == NULL) {
    return(TGA_ERROR_FILE_OPEN);
  }

// compute image type: 2 for RGB(A), 3 for greyscale
  mode = pixelDepth / 8;
  if ((pixelDepth == 24) || (pixelDepth == 32))
    type = 2;
  else
    type = 3;

// write the header
  fwrite(&cGarbage, sizeof(unsigned char), 1, file);
  fwrite(&cGarbage, sizeof(unsigned char), 1, file);

  fwrite(&type, sizeof(unsigned char), 1, file);

  fwrite(&iGarbage, sizeof(short int), 1, file);
  fwrite(&iGarbage, sizeof(short int), 1, file);
  fwrite(&cGarbage, sizeof(unsigned char), 1, file);
  fwrite(&iGarbage, sizeof(short int), 1, file);
  fwrite(&iGarbage, sizeof(short int), 1, file);

  fwrite(&width, sizeof(short int), 1, file);
  fwrite(&height, sizeof(short int), 1, file);
  fwrite(&pixelDepth, sizeof(unsigned char), 1, file);

  fwrite(&cGarbage, sizeof(unsigned char), 1, file);

// convert the image data from RGB(a) to BGR(A)
  if (mode >= 3)
  for (i=0; i < width * height * mode ; i+= mode) {
    aux = imageData[i];
    imageData[i] = imageData[i+2];
    imageData[i+2] = aux;
  }

// save the image data
  fwrite(imageData, sizeof(unsigned char),
      width * height * mode, file);
  fclose(file);
// release the memory
  free(imageData);

  return(TGA_OK);
}

// saves a series of files with names "filenameX.tga"
int tgaSaveSeries(char    *filename,
       short int    width,
       short int    height,
       unsigned char  pixelDepth,
       unsigned char  *imageData) {
  
  char *newFilename;
  int status;
  
// compute the new filename by adding the
// series number and the extension
  newFilename = (char *)malloc(sizeof(char) * strlen(filename)+8);

  sprintf(newFilename,"%s%d.tga",filename,savedImages);
  
// save the image
  status = tgaSave(newFilename,width,height,pixelDepth,imageData);
  
//increase the counter
  if (status == TGA_OK)
    savedImages++;
  free(newFilename);
  return(status);
}

// releases the memory used for the image
void tgaDestroy(tgaInfo *info) {

  if (info != NULL) {
    if (info->imageData != NULL)
      free(info->imageData);
    free(info);
  }
}


阅读:
录入:admin

评论 】 【 推荐 】 【 打印
上一篇:关于在 VB 中实现最短路径搜索的简单解决方案
下一篇:欧拉角转换四元数代码
相关新闻      
本文评论       全部评论
发表评论
字数
姓名:

  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款