time_t plGetFileModifiedTime(const char *path) { struct stat sAttributes; if (stat(path, &sAttributes) == -1) { plSetError("Failed to get modification time!\n"); return 0; } return sAttributes.st_mtime; }
/* Checks whether a file has been modified or not. */ bool plIsFileModified(time_t oldtime, const char *path) { if (!oldtime) { plSetError("Invalid time, skipping check!\n"); return false; } struct stat sAttributes; if (stat(path, &sAttributes) == -1) { plSetError("Failed to get file stats!\n"); return false; } if (sAttributes.st_mtime > oldtime) return true; return false; }
PLresult _plLoadPPMImage(FILE *fin, PLImage *out) { plSetErrorFunction("_plLoadPPMImage"); char header[PPM_HEADER_SIZE]; memset(&header, 0, sizeof(header)); fgets(header, PPM_HEADER_SIZE, fin); if (strncmp(header, "P6", 2)) { plSetError("Unsupported PPM type!\n"); return PL_RESULT_FILEVERSION; } int i = 0, d; unsigned int w = 0, h = 0; while (i < 3) { fgets(header, PPM_HEADER_SIZE, fin); if (header[0] == '#') continue; if (i == 0) i += sscanf(header, "%d %d %d", &w, &h, &d); else if (i == 1) i += sscanf(header, "%d %d", &h, &d); else if (i == 2) i += sscanf(header, "%d", &d); } memset(out, 0, sizeof(PLImage)); out->size = w * h * 3; out->data = new PLbyte*[1]; out->data[0] = new PLbyte[out->size]; fread(out->data[0], sizeof(uint8_t), out->size, fin); out->width = w; out->height = h; out->format = PL_IMAGEFORMAT_RGB8; return PL_RESULT_SUCCESS; }
PLresult _plLoadVTFImage(FILE *fin, PLImage *out) { plFunctionStart(); VTFHeader header; memset(&header, 0, sizeof(VTFHeader)); #define VTF_VERSION(maj, min) ((maj == header.version[1] && min <= header.version[0]) || maj < header.version[0]) if (fread(&header, sizeof(VTFHeader), 1, fin) != 1) { return PL_RESULT_FILEREAD; } else if (VTF_VERSION(7, 5)) { return PL_RESULT_FILEVERSION; } else if (!plIsValidImageSize(header.width, header.height)) { return PL_RESULT_IMAGERESOLUTION; } else { if(header.lowresimageformat != VTF_FORMAT_DXT1) { plSetError("Invalid texture format for lowresimage in VTF"); return PL_RESULT_IMAGEFORMAT; } if ((header.lowresimagewidth > 16) || (header.lowresimageheight > 16) || (header.lowresimagewidth > header.width) || (header.lowresimageheight > header.height)) { return PL_RESULT_IMAGERESOLUTION; } } // todo, use the headersize flag so we can load this more intelligently! VTFHeader72 header2; if (header.version[1] >= 2) { memset(&header2, 0, sizeof(VTFHeader72)); if (fread(&header2, sizeof(VTFHeader72), 1, fin) != 1) return PL_RESULT_FILEREAD; } VTFHeader73 header3; if (header.version[1] >= 3) { memset(&header3, 0, sizeof(VTFHeader73)); if (fread(&header3, sizeof(VTFHeader73), 1, fin) != 1) return PL_RESULT_FILEREAD; } memset(out, 0, sizeof(PLImage)); out->width = header.width; out->height = header.height; _plConvertVTFFormat(out, header.highresimageformat); out->levels = 1; out->data = (PLbyte**)calloc(1, sizeof(PLbyte*)); /* if (header.version[1] >= 3) { for (PLuint i = 0; i < header3.numresources; i++) { // todo, support for later VTF versions. } } else */ { PLuint faces = 1; if(header.flags & VTF_FLAG_ENVMAP) { faces = 6; } // VTF's typically include a tiny thumbnail image at the start, which we'll skip. fseek(fin, header.lowresimagewidth * header.lowresimageheight / 2, SEEK_CUR); for (PLuint mipmap = 0; mipmap < header.mipmaps; ++mipmap) { for(PLuint frame = 0; frame < header.frames; ++frame) { for(PLuint face = 0, mipw = 1, miph = 1; face < faces; ++face) { // We'll just skip the smaller mipmaps for now, can generate these later. mipw *= (PLuint)pow(2, mipmap); //(out->width * (mipmap + 1)) / header.mipmaps; miph *= (PLuint)pow(2, mipmap); //(out->height * (mipmap + 1)) / header.mipmaps; PLuint mipsize = _plGetImageSize(out->format, mipw, miph); if(mipmap == (header.mipmaps - 1)) { out->data[0] = (PLbyte*)calloc(mipsize, sizeof(PLbyte)); if (fread(out->data[0], sizeof(PLbyte), mipsize, fin) != mipsize) { _plFreeImage(out); return PL_RESULT_FILEREAD; } } else { fseek(fin, mipsize, SEEK_CUR); } if(feof(fin)) { perror(PL_FUNCTION); break; } } } } } return PL_RESULT_SUCCESS; }