/* * texparse.cpp by Jeromy Walsh * * Copyright (C) 2002 PlaneShift Team (info@planeshift.it, * http://www.planeshift.it) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ // Crystal Space Include Files #include #include #include #include #include #include #include #include #include #include // Planeshift Include Files #include #include #include "texparse.h" // System Include Files #include CS_IMPLEMENT_APPLICATION // The global pointer to simple psTxPrtParse *parser; psTxPrtParse::psTxPrtParse() { object_reg = NULL; colormask = NULL; region = NULL; outname = NULL; filename = NULL; race = NULL; scanlines = NULL; cmdOptions = 0; } psTxPrtParse::~psTxPrtParse() { if (colormask) { delete [] colormask; colormask = NULL;} if (region) { delete [] region; region = NULL;} if (outname) { delete [] outname; outname = NULL;} if (filename) { delete [] filename; filename = NULL;} if (race) { delete [] race; race = NULL;} if (scanlines) { delete [] scanlines; scanlines = NULL;} } int psTxPrtParse::VerifyCmdLine() { // Gain access to the command line iCommandLineParser* cmdline = dynamic_cast(object_reg->Get("iCommandLineParser")); // Check if they asked for help if (cmdline->GetOption("help")) return 5; // Check if a filename was provided if (!cmdline->GetName()) return 1; // Get the translated path csRef xname = VFS->ExpandPath( cmdline->GetName() ); // Add the VFS "/this" extension to the front filename = new char[strlen("/this/") + strlen((const char*)xname->GetData() ) ]; strcpy(filename, "/this"); strcat(filename, (const char*)xname->GetData() ); // Check if the file exists as the VFS sees it if ( !VFS->Exists(filename) ) return 2; fprintf(stdout, "Reading from VFS file: %s\n", filename); // Create output name, this will end in xml...hopefully outname = new char[strlen(filename) + 1] ; strcpy(outname, filename); outname[strlen(filename)-3] = outname[strlen(filename)]; strcat(outname, "xml"); fprintf(stdout, "Outputting XML to VFS file: %s\n", outname); // Check for a race flag if ( !cmdline->GetOption("race") ) return 3; // Check if there is just a race flag with no value assigned else if ( !strcmp(cmdline->GetOption("race"), "") ) return 4; // assign the value of the race option to application class race = new char[strlen(cmdline->GetOption("race") ) +1]; strcpy(race, cmdline->GetOption("race")); // Begin checking for options. colormask = new csRGBcolor[cmdOptions]; region = new psImageRegion[cmdOptions]; scanlines = new int[cmdOptions]; int marker = 0; char bodyparts[][10] = {"nose", "eyes", "chin", "hair"}; // Iterate through body part array, and check for matching parts and wellformed colorrefs for (int options = 0; options < 4; options++) { if (cmdline->GetOption(bodyparts[options]) ) { if (strlen(cmdline->GetOption( bodyparts[options] )) == 6) { colormask[marker] = TransColor(cmdline->GetOption( bodyparts[options] ) ); region[marker].race = race; region[marker].part = bodyparts[options]; marker++; } else return 6; } } // If the marker does not match the cmdOptions, then there are either too many or // too few options if (marker != cmdOptions) return 6; return 0; } csRGBcolor psTxPrtParse::TransColor(char const *arg) { int color[5] = {0}; // iterate through the 3 bytes, seperating and summing // into 3 colors. for (int i = 0; i < 5; i+=2) { // check if the first character is a letter or number if (isalpha(arg[i]) ) color[i] = 16 * (int)(tolower(arg[i] - 87) ); else color[i] = 16 * (arg[i] - 48); // check if the second character is a letter or a number if (isalpha(arg[i+1]) ) color[i] += (int)(tolower(arg[i+1] - 87) ); else color[i] += (arg[i+1] - 48); } // Create a csRGBcolor object from the values obtained. csRGBcolor rgbcolor(color[0], color[2], color[4]); return rgbcolor; } bool psTxPrtParse::Initialize(int argc, const char* const argv[]) { // Get the number of command line arguments, then subtract 3 due to // appname, filename, and race flag...the rest should be regions to parse cmdOptions = argc - 3; // Initialize the environment and register an object registry object_reg = csInitializer::CreateEnvironment(argc, argv); if (!object_reg) return false; // Request important plugins if (!csInitializer::RequestPlugins(object_reg, CS_REQUEST_VFS, CS_REQUEST_IMAGELOADER, CS_REQUEST_END)) { csReport(object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.simple", "Can't initialize plugins!"); return false; } // Obtain an interface to the Virtual File System VFS = CS_QUERY_REGISTRY(object_reg, iVFS); if (!VFS) { csReport(object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.texpartparse", "No iVFS plugin!"); return false; } // Obtain an interface to the iImageIO image loading class ImageLoader = CS_QUERY_REGISTRY(object_reg, iImageIO); if (!ImageLoader) { csReport(object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.texpartparse", "No iImageIO plugin!"); return false; } // Output information to the console csReport(object_reg, CS_REPORTER_SEVERITY_NOTIFY, "crystalspace.application.texpartparse", "\n<>==Texture Part Parser Version 0.1==<>"); // Now parse/verify the cmd line to make sure everything is available int value = 0; if ( (value = VerifyCmdLine()) ) { switch(value) { case 1: fprintf(stderr, "texpartparse: Error - No file name provided!\n"); break; case 2: fprintf(stderr, "texpartparse: Error - File is either corrupt or does not exist!\n"); break; case 3: fprintf(stderr, "texpartparse: Error - No race provided!\n"); break; case 4: fprintf(stderr, "texpartparse: Error - Please specify which race this is!\n"); break; case 5: break; case 6: fprintf(stderr, "texpartparse: Error - Poorly formed colorref(s)!\n"); break; } PrintUsage(); return false; } else fprintf(stdout, "Regions to parse: %d\n", cmdOptions); return true; } void psTxPrtParse::WriteFile() { csString output; char tempString[80]; psScanline *myline; // Print oppening Race element sprintf(tempString, " \n", race); output.Append(tempString); // For each region declared, iterate through and print the scanlines for (int i=0; i < cmdOptions; i++) { // Print oppening region element sprintf(tempString, " \n", region[i].part.GetData()); output.Append(tempString); int p = 0; for (int j = 0; j < scanlines[i]; j++) { myline = region[i].GetLine(p); ++p; // Print scanline sprintf(tempString, " \n", myline->x1, myline->x2, myline->y); output.Append(tempString); } // Print closing element sprintf(tempString, " \n"); output.Append(tempString); } // Print closing Race element sprintf(tempString, " \n"); output.Append(tempString); // Now try and write that all to the output file if (!VFS->WriteFile(outname, output, strlen(output)) ) fprintf(stderr, "Error - Could not write to file %s!\n", outname); } void psTxPrtParse::PrintUsage() { fprintf(stdout, "\nUsage: texparse -=... -race= filename\n\n"); fprintf(stdout, "Note: filename should NOT be a VFS path. Use real-world paths.\n"); fprintf(stdout, "Provide as many unique part/colorref pairs as you like.\n"); fprintf(stdout, "Example: >texparse -nose=ff0000 -race=elf basicelf.png\n\n"); } void psTxPrtParse::Start() { // Print out some messages fprintf(stdout, "Race: %s\n", race); // Load the image csRef image = LoadImage(filename, CS_IMGFMT_TRUECOLOR); // Determine image height fprintf(stdout, "Checking texture height..."); int height = image->GetHeight(); fprintf(stdout, "%d\n", height); // Determine image width fprintf(stdout, "Checking texture width..."); int width = image->GetWidth(); fprintf(stdout, "%d\n", width); // Create csRGBpixels csRGBpixel *destpix = (csRGBpixel *)image->GetImageData(); int x1=0; long index = 0; psScanline *scanline; for (int c = 0; c < cmdOptions; c++) { scanlines[c] = 0; // Iterate down each row for (int i = 0; i < height; i++) { // Iterate over each column for (int j = 0; j < width; j++) { // calculate linear array index index = j + (i * width); // Check and see if there is a matching color if (destpix[index] == colormask[c]) { // We matched, check previous color if this is not beginning if (j != 0) { // Check to see if this is beginning of scanline if (destpix[index-1] != destpix[index]) x1 = j; } else x1 = j; } // No color match, lets check if we just ended a scanlins else { if (j != 0) { if (destpix[index-1] == colormask[c]) { scanline = new psScanline(x1, j, i); region[c].AddScanline(scanline); scanlines[c]++; } } } } } fprintf(stdout, "Found %d scanlines for the %s\n", scanlines[c], region[c].part.GetData()); } WriteFile(); } csPtr psTxPrtParse::LoadImage(const char* name, int Format) { // Check if we have a pointer to the ImageLoader plugin if (!ImageLoader) return NULL; // Check if we were passed an invalid format if (Format & CS_IMGFMT_INVALID) { Format = CS_IMGFMT_TRUECOLOR; } // Create an image file and buffer // Then read the file into the buffer csRef ifile; csRef buf = VFS->ReadFile(name); // Check to see if for some reason the buffer was not // created or is empty if (!buf || !buf->GetSize() ) { fprintf(stderr, "Could not open image file '%s' on VFS!", name); } else { // Load the image into the image class based on the given // format ifile = ImageLoader->Load(buf, Format); if (!ifile) fprintf(stderr, "Could not load image '%s'. Unknown format or wrong extension!", name); } // Check if the image class was not created correctly if (!ifile) { ifile = csCreateXORPatternImage(32, 32, 5); } // Give the image a VFS compatible name. csRef xname = VFS->ExpandPath(name); ifile->SetName(**xname); ifile->IncRef (); return csPtr (ifile); } /*---------------* * Main function *---------------*/ int main(int argc, char* argv[]) { parser = new psTxPrtParse(); char str[1000]; if ( parser->Initialize(argc, argv) ) parser->Start(); else fgets(str,1000,stdin); // save for Destroy call below iObjectRegistry *obj_reg = parser->object_reg; delete parser; csInitializer::DestroyApplication(obj_reg); return 0; }