void opengl_texture::load_TGA() { std::ifstream file( name + type, std::ios::binary ); file.unsetf( std::ios::skipws ); // Read the header of the TGA, compare it with the known headers for compressed and uncompressed TGAs unsigned char tgaheader[ 18 ]; file.read( (char *)tgaheader, sizeof( unsigned char ) * 18 ); while( tgaheader[ 0 ] > 0 ) { --tgaheader[ 0 ]; unsigned char temp; file.read( (char *)&temp, sizeof( unsigned char ) ); } data_width = tgaheader[ 13 ] * 256 + tgaheader[ 12 ]; data_height = tgaheader[ 15 ] * 256 + tgaheader[ 14 ]; int const bytesperpixel = tgaheader[ 16 ] / 8; // check whether width, height an BitsPerPixel are valid if( ( data_width <= 0 ) || ( data_height <= 0 ) || ( ( bytesperpixel != 1 ) && ( bytesperpixel != 3 ) && ( bytesperpixel != 4 ) ) ) { data_state = resource_state::failed; return; } // allocate the data buffer int const datasize = data_width * data_height * 4; data.resize(datasize); // call the appropriate loader-routine if( tgaheader[ 2 ] == 2 ) { // uncompressed TGA if( bytesperpixel == 4 ) { // read the data directly file.read( reinterpret_cast<char*>( &data[0] ), datasize ); } else { // rgb or greyscale image, expand to bgra unsigned char buffer[ 4 ] = { 255, 255, 255, 255 }; // alpha channel will be white unsigned int *datapointer = (unsigned int*)&data[0]; unsigned int *bufferpointer = (unsigned int*)&buffer[ 0 ]; int const pixelcount = data_width * data_height; for( int i = 0; i < pixelcount; ++i ) { file.read( (char *)&buffer[ 0 ], sizeof( unsigned char ) * bytesperpixel ); if( bytesperpixel == 1 ) { // expand greyscale data buffer[ 1 ] = buffer[ 0 ]; buffer[ 2 ] = buffer[ 0 ]; } // copy all four values in one operation ( *datapointer ) = ( *bufferpointer ); ++datapointer; } } } else if( tgaheader[ 2 ] == 10 ) { // compressed TGA int currentpixel = 0; unsigned char buffer[ 4 ] = { 255, 255, 255, 255 }; const int pixelcount = data_width * data_height; unsigned int *datapointer = (unsigned int *)&data[0]; unsigned int *bufferpointer = (unsigned int *)&buffer[ 0 ]; do { unsigned char chunkheader = 0; file.read( (char *)&chunkheader, sizeof( unsigned char ) ); if( (chunkheader & 0x80 ) == 0 ) { // if the high bit is not set, it means it is the number of RAW color packets, plus 1 for( int i = 0; i <= chunkheader; ++i ) { file.read( (char *)&buffer[ 0 ], bytesperpixel ); if( bytesperpixel == 1 ) { // expand greyscale data buffer[ 1 ] = buffer[ 0 ]; buffer[ 2 ] = buffer[ 0 ]; } // copy all four values in one operation ( *datapointer ) = ( *bufferpointer ); ++datapointer; ++currentpixel; } } else { // rle chunk, the color supplied afterwards is reapeated header + 1 times (not including the highest bit) chunkheader &= ~0x80; // read the current color file.read( (char *)&buffer[ 0 ], bytesperpixel ); if( bytesperpixel == 1 ) { // expand greyscale data buffer[ 1 ] = buffer[ 0 ]; buffer[ 2 ] = buffer[ 0 ]; } // copy the color into the image data as many times as dictated for( int i = 0; i <= chunkheader; ++i ) { ( *datapointer ) = ( *bufferpointer ); ++datapointer; ++currentpixel; } } } while( currentpixel < pixelcount ); } else { // unrecognized TGA sub-type data_state = resource_state::failed; return; } if( ( tgaheader[ 17 ] & 0x20 ) != 0 ) { // normally origin is bottom-left // if byte 17 bit 5 is set, it is top-left and needs flip flip_vertical(); } downsize( GL_BGRA ); if( ( data_width > Global.iMaxTextureSize ) || ( data_height > Global.iMaxTextureSize ) ) { // for non-square textures there's currently possibility the scaling routine will have to abort // before it gets all work done data_state = resource_state::failed; return; } // TODO: add horizontal/vertical data flip, based on the descriptor (18th) header byte // fill remaining data info data_mapcount = 1; data_format = GL_BGRA; data_components = ( bytesperpixel == 4 ? GL_RGBA : GL_RGB ); data_state = resource_state::good; return; }
int main(int argc,char *argv[]) { //Handles user input, to get file names and command if(argc<4 || argc>6) { printf("Incorrect number of arguments\n"); printf("Number of arguments: %d\n",argc); exit(1); } const char *input_filename=argv[1]; printf("Inputfile: %s\n",input_filename); const char *output_filename=argv[2]; printf("Outputfile: %s\n",output_filename); char garbage[2]; int command; int radius=3; if(1!=sscanf(argv[3],"%d%1s",&command,garbage) || command<0 || command>10) { printf("Incorrect command\n"); exit(1); } if(((command==0) && argc==5 && 1!=sscanf(argv[4],"%d%1s",&radius,garbage)) || radius<1) { printf("Incorrect radius value\n"); exit(1); } //Create filters and images Filter *filters=initialize_filters(radius); Image *input_image=decode(input_filename); printf("Width: %d, height: %d\n",input_image->width,input_image->height); Image *output_image=generate_output(input_image); uint8_t *in_red=input_image->red_channel; uint8_t *in_blue=input_image->blue_channel; uint8_t *in_green=input_image->green_channel; uint8_t *in_alpha=input_image->alpha_channel; uint8_t *out_red=output_image->red_channel; uint8_t *out_blue=output_image->blue_channel; uint8_t *out_green=output_image->green_channel; uint8_t *out_alpha=output_image->alpha_channel; int height=input_image->height; int width=input_image->width; //Run chosen command to call functions from functions.c switch(command) { case(0): { convolve_image(in_red,in_green,in_blue,in_alpha,out_red,out_green,out_blue, out_alpha,filters[0].filter,filters[0].radius,width,height); encode(output_filename,output_image); break; } case(1): { convolve_image(in_red,in_green,in_blue,in_alpha,out_red,out_green,out_blue, out_alpha,filters[1].filter,filters[1].radius,width,height); encode(output_filename,output_image); break; } case(2): { convolve_image(in_red,in_green,in_blue,in_alpha,out_red,out_green,out_blue, out_alpha,filters[2].filter,filters[2].radius,width,height); encode(output_filename,output_image); break; } case(3): { convolve_image(in_red,in_green,in_blue,in_alpha,out_red,out_green,out_blue, out_alpha,filters[3].filter,filters[3].radius,width,height); encode(output_filename,output_image); break; } case(4): { convolve_image(in_red,in_green,in_blue,in_alpha,out_red,out_green,out_blue, out_alpha,filters[4].filter,filters[4].radius,width,height); encode(output_filename,output_image); break; } case(5): { convolve_image(in_red,in_green,in_blue,in_alpha,out_red,out_green,out_blue, out_alpha,filters[5].filter,filters[5].radius,width,height); encode(output_filename,output_image); break; } case(6): { convert_to_gray(in_red,in_green,in_blue,in_alpha,out_red,out_green,out_blue, out_alpha,gmonomult,width,height); encode(output_filename,output_image); break; } case(7): { flip_vertical(in_red,in_green,in_blue,in_alpha,out_red,out_green,out_blue, out_alpha,width,height); encode(output_filename,output_image); break; } case(8): { color_threshold(in_red,in_green,in_blue,in_alpha,out_red,out_green,out_blue, out_alpha,width,height,10,150,10); encode(output_filename,output_image); break; } default: exit(1); } free((double*)filters[0].filter); free(filters); free_image(input_image); free_image(output_image); return 0; }