bool UMImage::save(const umstring& filepath, UMImagePtr src, ImageType type) { if (!src) return false; if (!src->is_valid()) return false; std::string filename = umbase::UMStringUtil::utf16_to_utf8(filepath); int result = 0; if (type == eImageTypeBMP_RGB) { UMImage::R8G8B8Buffer img; src->create_r8g8b8_buffer(img); stbi_write_bmp( filename.c_str(), src->width(), src->height(), STBI_rgb, &(*img.begin())); } else if (type == eImageTypeTGA_RGB) { UMImage::R8G8B8Buffer img; src->create_r8g8b8_buffer(img); stbi_write_tga( filename.c_str(), src->width(), src->height(), STBI_rgb, &(*img.begin())); } else if (type == eImageTypeTGA_RGBA) { UMImage::R8G8B8A8Buffer img; src->create_r8g8b8a8_buffer(img); stbi_write_tga( filename.c_str(), src->width(), src->height(), STBI_rgb_alpha, &(*img.begin())); } else if (type == eImageTypePNG_RGBA) { UMImage::R8G8B8A8Buffer img; src->create_r8g8b8a8_buffer(img); stbi_write_png( filename.c_str(), src->width(), src->height(), STBI_rgb_alpha, &(*img.begin()), 0); } return (result == 1); }
void Graphics::ScreenToImage(const std::string &filename, ImageType type) { int w = Platform::GetWidth(), h = Platform::GetHeight(); char *data = new char[w * h * 3]; glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, data); char* tmpline = new char[w*3]; const int linewidth = w * 3; //flip the image for(int y = 0; y < (h/2); y++) { std::copy(data + y * linewidth, data + y * linewidth + linewidth, tmpline); std::copy(data + (h-y) * linewidth, data + (h-y) * linewidth + linewidth, data + y * linewidth); std::copy(tmpline, tmpline + linewidth, data + (h-y) * linewidth); } switch(type) { case IMAGE_PNG: stbi_write_png( filename.data(), w, h, 3, data, w * 3 ); break; case IMAGE_BMP: stbi_write_bmp( filename.data(), w, h, 3, data); break; case IMAGE_TGA: stbi_write_tga( filename.data(), w, h, 3, data); break; } delete tmpline; delete data; }
void Bitmap::write(const string inFullPathname) { if(!stbi_write_tga(inFullPathname.c_str(), width, height, bytesPerPixelFromComponents(format), data)) { throw std::runtime_error("screenshot save failed"); } }
void FrameBufferInterface::saveToFile(const char * _filename, unsigned long int _fbochannel){ // get the channel we're asking for const FrameBufferChannel & channel = frameBufferChannels.at(_fbochannel); unsigned long int bytes = width*height*channel.numChannels; GLubyte * pixels = getPixelData(_fbochannel); unsigned char * pixelsSOIL = (unsigned char *)malloc(bytes * sizeof(unsigned char)); glBindTexture(GL_TEXTURE_2D, frameBufferChannels.at(_fbochannel).id); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); for(unsigned long int i = 0; i < bytes; ++i){ pixelsSOIL[i] = pixels[i]; } std::stringstream ss; ss << "data/images/" << _filename; if(stbi_write_tga(ss.str().c_str(), width, height, channel.numChannels, pixelsSOIL, 1)){ Log::info("FBO \""+ss.str()+"\" saved"); }else{ Log::error("FBO \""+ss.str()+"\" not saved"); } free(pixels); free(pixelsSOIL); }
bool kit::Texture::saveToFile(const std::string&filename) { // Fetch data from GPU unsigned char * data = new unsigned char[(m_resolution.x * m_resolution.y) * 4]; #ifndef KIT_SHITTY_INTEL glGetTextureImage(m_glHandle, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLsizei)(((m_resolution.x * m_resolution.y) * 4) * sizeof(unsigned char)), &data[0]); #else bind(); glGetTexImage(m_type, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); #endif stbi_write_set_flip_vertically_on_save(1); // Write data to disk if(stbi_write_tga(filename.c_str(), m_resolution.x, m_resolution.y, 4, (void*)data) == 0) { KIT_ERR("Failed to write image to file") delete[] data; return false; } delete[] data; return true; }
void Canvas::paintGL() { glClear(GL_COLOR_BUFFER_BIT); if(!ready) return; size_t size; checkCudaErrors(cudaGraphicsMapResources(1, &resource, 0)); checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void**)&img, &size, resource)); if(renderMode == RENDER_MODE_RAYCASTING) { /*glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBegin(GL_QUADS); glColor4f(0.4745f, 0.9294f, 0.8901f, 1.f); glVertex2f(1.f, 1.f); glColor4f(0.4745f, 0.9294f, 0.8901f, 1.f); glVertex2f(-1.f, 1.f); glColor4f(0.9490f, 0.9647f, 0.9803f, 1.f); glVertex2f(-1.f, -1.f); glColor4f(0.9490f, 0.9647f, 0.9803f, 1.f); glVertex2f(1.f, -1.f); glEnd();*/ render_raycasting(img, deviceVolume, transferFunction, camera, volumeReader.GetElementBoundingSphereRadius()); } else { render_pathtracer(img, renderParams); if(renderParams.frameNo == 0) { char* data = new char[WIDTH * HEIGHT * 4]; cudaMemcpy(data, img, sizeof(glm::u8vec4) * WIDTH * HEIGHT, cudaMemcpyDeviceToHost); stbi_write_tga("0.tga", WIDTH, HEIGHT, 4, data); delete []data; } } checkCudaErrors(cudaDeviceSynchronize()); checkCudaErrors(cudaGraphicsUnmapResources(1, &resource, 0)); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo); glDrawPixels(WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glDisable(GL_BLEND); renderParams.frameNo++; }
void CImgWrapper<T>::save(const std::string& fn) const { //imgptr->save(fn.c_str()); std::string ext = fn.substr(fn.size()-4); //std::cerr << "Stuff" << ext; // // int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); // int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); // int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); // int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); if (ext == ".hdr" || ext==".HDR") { cimg_library::CImg<float> imgout = *imgptr; imgout.permute_axes("cxyz"); stbi_write_hdr(fn.c_str(), imgptr->width(), imgptr->height(), imgptr->spectrum(), imgout.data()); } else if ( ext == ".png" || ext == ".PNG" || ext==".bmp" || ext==".BMP" || ext==".jpg" || ext==".JPG" || ext==".JPEG" || ext==".jpeg"|| ext==".tga" || ext==".TGA") { cimg_library::CImg<unsigned char> imgout = *imgptr; imgout.permute_axes("cxyz"); const char* fnc = fn.c_str(); int w = imgptr->width(); int h = imgptr->height(); int c = imgptr->spectrum(); const unsigned char* dt = imgout.data(); switch (ext[1]) { case 'p': case 'P': stbi_write_png(fnc, w, h, c, dt, 0); break; case 'b': case 'B': stbi_write_bmp(fnc, w, h, c, dt); break; case 'j': case 'J': stbi_write_jpg(fnc, w, h, c, dt, 8); break; case 't': case 'T': stbi_write_tga(fnc, w, h, c, dt); break; }; } else { imgptr->save(fn.c_str()); } }
int SOIL_save_image ( const char *filename, int image_type, int width, int height, int channels, const unsigned char *const data ) { int save_result; /* error check */ if( (width < 1) || (height < 1) || (channels < 1) || (channels > 4) || (data == NULL) || (filename == NULL) ) { return 0; } if( image_type == SOIL_SAVE_TYPE_BMP ) { save_result = stbi_write_bmp( filename, width, height, channels, (void*)data ); } else if( image_type == SOIL_SAVE_TYPE_TGA ) { save_result = stbi_write_tga( filename, width, height, channels, (void*)data ); } else if( image_type == SOIL_SAVE_TYPE_DDS ) { save_result = save_image_as_DDS( filename, width, height, channels, (const unsigned char *const)data ); } else { save_result = 0; } if( save_result == 0 ) { result_string_pointer = "Saving the image failed"; } else { result_string_pointer = "Image saved"; } return save_result; }
bool Image::saveAs(const std::string& filename) { if (width>0 && height >0) { if (filename.size() > 3) { // Extract the extension std::string extension = filename.substr(filename.size() - 3); if (toLower(extension) == "bmp") { // BMP format if (stbi_write_bmp(filename.c_str(), width, height, 4, m_data)) return true; } else if (toLower(extension) == "tga") { // TGA format if (stbi_write_tga(filename.c_str(), width, height, 4, m_data)) return true; } else if(toLower(extension) == "png") { // PNG format if (stbi_write_png(filename.c_str(), width, height, 4, m_data, 0)) return true; } else { fprintf(stderr,"Failed to save image, unknown type\n"); return false; } } else { fprintf(stderr,"Failed to save image, can't deduce type\n"); return false; } } else { fprintf(stderr,"Failed to save image, empty image\n"); return false; } return true; }
int image_ImageData_save(image_ImageData *dst, const char* format, const char* filename) { int succeded = 0; if (strncmp(format, "png", 3) == 0) succeded = stbi_write_png(filename, dst->w, dst->h, dst->c, (const float*)dst->pixels, 0); else if (strncmp(format, "bmp", 3) == 0) succeded = stbi_write_bmp(filename, dst->w, dst->h, dst->c, (const float*)dst->surface); else if (strncmp(format, "tga", 3) == 0) succeded = stbi_write_tga(filename, dst->w, dst->h, dst->c, (const float*)dst->pixels); else if (strncmp(format, "hdr", 3) == 0) succeded = stbi_write_hdr(filename, dst->w, dst->h, dst->c, (const float*)dst->surface); else printf("%s %s %s \n", "Error, format:", format, " is not avalabile.Only png,bmp,tga and hdr image formats are possible"); if(succeded != 0) return 1; else { printf("%s %s \n", "Error: failed to save imageData: ", filename); return 0; } }
void ImageTargetFileStbImage::finalize() { if( mExtension == "png" ) { if( ! stbi_write_png( mFilePath.string().c_str(), (int)mWidth, (int)mHeight, mNumComponents, mData.get(), (int)mRowBytes ) ) throw ImageIoExceptionFailedWrite(); } else if( mExtension == "bmp" ) { if( ! stbi_write_bmp( mFilePath.string().c_str(), (int)mWidth, (int)mHeight, mNumComponents, mData.get() ) ) throw ImageIoExceptionFailedWrite(); } else if( mExtension == "tga" ) { if( ! stbi_write_tga( mFilePath.string().c_str(), (int)mWidth, (int)mHeight, mNumComponents, mData.get() ) ) throw ImageIoExceptionFailedWrite(); } else if( mExtension == "hdr" ) { if( ! stbi_write_hdr( mFilePath.string().c_str(), (int)mWidth, (int)mHeight, mNumComponents, (const float*)mData.get() ) ) throw ImageIoExceptionFailedWrite(); } }
bool kit::Texture::saveToFile(std::string filename) { // Fetch data from GPU unsigned char * data = new unsigned char[(this->m_resolution.x * this->m_resolution.y) * 4]; KIT_GL(glGetTextureImage(this->m_glHandle, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLsizei)(((this->m_resolution.x * this->m_resolution.y) * 4) * sizeof(unsigned char)), &data[0])); stbi_write_set_flip_vertically_on_save(1); // Write data to disk if(stbi_write_tga(filename.c_str(), this->m_resolution.x, this->m_resolution.y, 4, (void*)data) == 0) { KIT_ERR("Failed to write image to file") delete[] data; return false; } delete[] data; return true; }
bool Image::SaveTGA(const String& fileName) { FileSystem* fileSystem = GetSubsystem<FileSystem>(); if (fileSystem && !fileSystem->CheckAccess(GetPath(fileName))) { LOGERROR("Access denied to " + fileName); return false; } if (IsCompressed()) { LOGERROR("Can not save compressed image to TGA"); return false; } if (data_) return stbi_write_tga(fileName.CString(), width_, height_, components_, data_.Get()) != 0; else return false; }
bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height) { // Make sure the image is not empty if (!pixels.empty() && width && height) { // Deduce the image type from its extension if (filename.size() > 3) { // Extract the extension std::string extension = filename.substr(filename.size() - 3); if (toLower(extension) == "bmp") { // BMP format if (stbi_write_bmp(filename.c_str(), width, height, 4, &pixels[0])) return true; } else if (toLower(extension) == "tga") { // TGA format if (stbi_write_tga(filename.c_str(), width, height, 4, &pixels[0])) return true; } else if(toLower(extension) == "png") { // PNG format if (stbi_write_png(filename.c_str(), width, height, 4, &pixels[0], 0)) return true; } else if (toLower(extension) == "jpg") { // JPG format if (writeJpg(filename, pixels, width, height)) return true; } } } err() << "Failed to save image \"" << filename << "\"" << std::endl; return false; }
void Gosu::saveImageFile(const Gosu::Bitmap& bitmap, const std::wstring& filename) { int ok; std::string utf8 = Gosu::wstringToUTF8(filename); if (isExtension(filename.c_str(), L"bmp")) { ok = stbi_write_bmp(utf8.c_str(), bitmap.width(), bitmap.height(), 4, bitmap.data()); } else if (isExtension(filename.c_str(), L"tga")) { ok = stbi_write_tga(utf8.c_str(), bitmap.width(), bitmap.height(), 4, bitmap.data()); } else { ok = stbi_write_png(utf8.c_str(), bitmap.width(), bitmap.height(), 4, bitmap.data(), 0); } if (ok == 0) throw std::runtime_error("Could not save image data to file: " + utf8); }
bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, const Vector2u& size) { // Make sure the image is not empty if (!pixels.empty() && (size.x > 0) && (size.y > 0)) { // Deduce the image type from its extension // Extract the extension const std::size_t dot = filename.find_last_of('.'); const std::string extension = dot != std::string::npos ? toLower(filename.substr(dot + 1)) : ""; if (extension == "bmp") { // BMP format if (stbi_write_bmp(filename.c_str(), size.x, size.y, 4, &pixels[0])) return true; } else if (extension == "tga") { // TGA format if (stbi_write_tga(filename.c_str(), size.x, size.y, 4, &pixels[0])) return true; } else if (extension == "png") { // PNG format if (stbi_write_png(filename.c_str(), size.x, size.y, 4, &pixels[0], 0)) return true; } else if (extension == "jpg" || extension == "jpeg") { // JPG format if (writeJpg(filename, pixels, size.x, size.y)) return true; } } err() << "Failed to save image \"" << filename << "\"" << std::endl; return false; }
///\todo is there a write error message too? bool writeImage(const LDRImage& img, const std::string& filename) { if(!img) { throw std::runtime_error("Image::Write called on incomplete image"); } std::string extension = filename.substr(filename.length()-4, 4); int width =img.getDimensions()[1]; int height=img.getDimensions()[2]; int channels=img.getDimensions()[0]; //special case branching... mostly becuase jpeg doens't write with this writer. This allows autodetection of the extension regardless though. if(extension == ".png") { return stbi_write_png(filename.c_str(), width, height, channels, img.dataPtr(), width*channels); } else if(extension==".bmp") { return stbi_write_bmp(filename.c_str(), width, height, channels, img.dataPtr()); } else if(extension == ".tga") { return stbi_write_tga(filename.c_str(), width, height, channels, img.dataPtr()); } else { throw std::runtime_error("Unimplemented extension for image writer"); } return false; }
void CNormalGenerator::SaveToFile(const tchar *pszFilename) { if (!pszFilename) return; tstring sFilename = pszFilename; tvector<Color> aclrTexels; aclrTexels.resize(m_iNormal2Width*m_iNormal2Height); for (size_t i = 0; i < aclrTexels.size(); i++) aclrTexels[i] = m_avecNormal2Texels[i]; if (sFilename.endswith(".png")) stbi_write_png(sFilename.c_str(), m_iNormal2Width, m_iNormal2Height, 3, aclrTexels.data(), 0); else if (sFilename.endswith(".tga")) stbi_write_tga(sFilename.c_str(), m_iNormal2Width, m_iNormal2Height, 3, aclrTexels.data()); else if (sFilename.endswith(".bmp")) stbi_write_bmp(sFilename.c_str(), m_iNormal2Width, m_iNormal2Height, 3, aclrTexels.data()); else TUnimplemented(); }
void BitmapData::save(const char* path) const { const char* ext = strrchr(path, '.'); if (ext == NULL) { lmLogError(gGFXLogGroup, "No extension in path %s. Unable to detect file format.", path); return; } if (stricmp(ext, ".bmp") == 0) { if (stbi_write_bmp(path, w, h, DATA_BPP, data) != 1) { lmLogError(gGFXLogGroup, "Unable to write image %s", path); } return; } if (stricmp(ext, ".png") == 0) { if (stbi_write_png(path, w, h, DATA_BPP, data, w * DATA_BPP) != 1) { lmLogError(gGFXLogGroup, "Unable to write image %s", path); } return; } if (stricmp(ext, ".tga") == 0) { if (stbi_write_tga(path, w, h, DATA_BPP, data) != 1) { lmLogError(gGFXLogGroup, "Unable to write image %s", path); } return; } lmLogError(gGFXLogGroup, "Unsupported image extension in path %s.", path); }
void RadLMap::writeRaw(const fstl::string & folder) { fstl::string fname = folder; if (fname[fname.length() - 1] != '/') fname += "/"; //fname += fstl::string(id()) + " - " + fstl::string(width()) + "x" + fstl::string(height()) + ".raw"; fname += fstl::string(id()) + " - " + fstl::string(width()) + "x" + fstl::string(height()) + ".tga"; unsigned char buffer[width() * height() * 3]; int i = 0; for (unsigned int j = 0; j < width() * height(); ++j) { buffer[i++] = static_cast<unsigned char>(data()[j].b()); buffer[i++] = static_cast<unsigned char>(data()[j].g()); buffer[i++] = static_cast<unsigned char>(data()[j].r()); } stbi_write_tga(fname.asArray(), width(), height(), 3, (const void *) buffer); /* FILE *fp = fopen(fname.asArray(), "wb"); if (fp) { for (unsigned int j = 0; j < width() * height(); ++j) { unsigned int r = static_cast<unsigned int>(data()[j].r()); unsigned int g = static_cast<unsigned int>(data()[j].g()); unsigned int b = static_cast<unsigned int>(data()[j].b()); fwrite(&r, 1, 1, fp); fwrite(&g, 1, 1, fp); fwrite(&b, 1, 1, fp); } fclose(fp); } */ }
// Test JPEG file decompression using jpgd.h static int test_jpgd(const char *pSrc_filename, const char *pDst_filename) { // Load the source JPEG image. const int req_comps = 3; // request RGB image int width = 0, height = 0, actual_comps = 0; timer tm; tm.start(); uint8 *pImage_data = jpgd::decompress_jpeg_image_from_file(pSrc_filename, &width, &height, &actual_comps, req_comps); tm.stop(); if (!pImage_data) { log_printf("Failed loading JPEG file \"%s\"!\n", pSrc_filename); return EXIT_FAILURE; } log_printf("Source JPEG file: \"%s\", image resolution: %ix%i, actual comps: %i\n", pSrc_filename, width, height, actual_comps); log_printf("Decompression time: %3.3fms\n", tm.get_elapsed_ms()); if (!stbi_write_tga(pDst_filename, width, height, req_comps, pImage_data)) { log_printf("Failed writing image to file \"%s\"!\n", pDst_filename); free(pImage_data); return EXIT_FAILURE; } log_printf("Wrote decompressed image to TGA file \"%s\"\n", pDst_filename); log_printf("Success.\n"); free(pImage_data); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { float *data; float *dest; unsigned char *data_ub; /* ubyte data */ int w, h, n; /* with, height, n-components*/ int i, size; set_working_dir(argv); /* read and convert image */ { float uctof = 1.0f / 255.0f; /* read */ data_ub = stbi_load(ABS_TOP_SRCDIR "/examples/image/dataset/lena.tga", &w, &h, &n, 0); if (! data_ub) { printf("unable to read image\n"); return EXIT_FAILURE; } /* allocate memory */ size = w * h; data = malloc(size * sizeof(float)); dest = malloc(size * sizeof(float)); /* convert to float */ if (n == 1) /* already greyscale */ for (i = 0; i < size; i++) data[i] = (float)data_ub[i] * uctof; else if(n >= 3) /* convert to greyscale */ for (i = 0; i < size; i++) data[i] = (data_ub[i*n]*0.2f + data_ub[i*n + 1]*0.7f + data_ub[i*n + 2]*0.1f) * uctof; } /* gaussian */ { p_gauss3x3_f32(data, dest, h, w); float_to_ubyte(data_ub, dest, size); stbi_write_tga("../dataset/lena_gaussian.tga", w, h, 1, data_ub); } /* harris */ { float *tmp = malloc(size * 3 * sizeof(float)); p_harris3x3_f32(data, dest, tmp, h, w); free(tmp); float_to_ubyte(data_ub, dest, size); stbi_write_tga("../dataset/lena_harris.tga", w-4, h-4, 1, data_ub); } /* sobel */ { p_sobel3x3_f32(data, dest, h, w); float_to_ubyte(data_ub, dest, size); stbi_write_tga("../dataset/lena_sobel.tga", w, h, 1, data_ub); } /* scharr */ { p_scharr3x3_f32(data, dest, h, w); float_to_ubyte(data_ub, dest, size); stbi_write_tga("../dataset/lena_scharr.tga", w, h, 1, data_ub); } /* prewitt */ { p_prewitt3x3_f32(data, dest, h, w); float_to_ubyte(data_ub, dest, size); stbi_write_tga("../dataset/lena_prewitt.tga", w, h, 1, data_ub); } /* box */ { p_box3x3_f32(data, dest, h, w); float_to_ubyte(data_ub, dest, size); stbi_write_tga("../dataset/lena_box.tga", w-2, h-2, 1, data_ub); } /* median */ { p_median3x3_f32(data, dest, h, w); float_to_ubyte(data_ub, dest, size); stbi_write_tga("../dataset/lena_median.tga", w-2, h-2, 1, data_ub); } free(dest); free(data); stbi_image_free(data_ub); return EXIT_SUCCESS; }
bool Image::save(core::FileSystem::Ptr fs, const std::string &filename) { if (type != TextureType::Texture2D) return false; unsigned int components = 0; if (format == TextureFormat::R8) components = 1; else if (format == TextureFormat::RG8) components = 2; else if (format == TextureFormat::RGBA8) components = 4; if (components == 0) return false; std::string extension = tolower(filename.substr(filename.rfind("."))); if (extension == ".png") { core::File::Ptr file = fs->open(filename, core::FileAccess::Write, true); if (!file) return false; unsigned int stride = TextureFormat::getSize(format, width, 1, 1); if (!stbi_write_png(file, width, height, components, imagedata, stride)) return false; } else if (extension == ".tga") { core::File::Ptr file = fs->open(filename, core::FileAccess::Write, true); if (!file) return false; if (!stbi_write_tga(file, width, height, components, imagedata)) return false; } else if (extension == ".bmp") { core::File::Ptr file = fs->open(filename, core::FileAccess::Write, true); if (!file) return false; if (!stbi_write_bmp(file, width, height, components, imagedata)) return false; } else { return false; } return true; }
screenshotArray[3 * screenshotIndex(x, _height - 1 - y) + i]; screenshotArrayFlipped[3 * screenshotIndex(x, _height - 1 - y) + i] = screenshotArray[3 * screenshotIndex(x, y) + i]; } #if MFluidSolver_USE_TBB } } } ); #else } } #endif // Write int result = stbi_write_tga(outString.c_str(), _width, _height, 3, screenshotArrayFlipped.data()); if (manual) { if (result != 0) { // Success #if MFluidSolver_LOG_LEVEL <= MFluidSolver_LOG_INFO std::cout << "INFO: Wrote rendered image to: " << outString << std::endl; #endif } else { // Failure #if MFluidSolver_LOG_LEVEL <= MFluidSolver_LOG_ERROR std::cout << "ERROR: Failed to write rendered image to: " << outString << std::endl; #endif } } }
int dump_tex(int argc, const char * argv[]) { TexFile tex; FileStream inStream; FileStream outStream; if (!inStream.open(argv[0], "rb")) { printf("Error input file %s\n", argv[0]); return 1; } /* if (!outStream.open(argv[1], "wb")) { printf("Error output file %s\n", argv[1]); return 1; }*/ if (!tex.read(&inStream)) { printf("Error input file %s\n", argv[0]); return 1; } // Dump the raw rgb unsigned int size = tex.mHeader.size * tex.mHeader.size * 4; unsigned char *outputData = (unsigned char *)malloc(size); int result = 0; int actualSize = 0; const char *fmt = "UNKN"; bool hasMips = tex.mHeader.flags & 0x20; if (tex.mHeader.unknown0[1] == 11 || tex.mHeader.unknown0[1] == 13) // PVRTC { unsigned int bytes = PVRTDecompressPVRTC(tex.mData, 0, tex.mHeader.size, tex.mHeader.size, outputData); result = stbi_write_tga(argv[1], tex.mHeader.size, tex.mHeader.size, STBI_rgb_alpha, outputData); fmt = "PVRTC"; actualSize = ( std::max((int)tex.mHeader.size, 8) * std::max((int)tex.mHeader.size, 8) * 4 + 7) / 8; } else if (tex.mHeader.unknown0[1] == 1) // RGBA { memcpy(outputData, tex.mData, tex.mHeader.size*tex.mHeader.size*4); //result = stbi_write_tga(argv[1], tex.mHeader.size, tex.mHeader.size, STBI_rgb_alpha, outputData); fmt = "RGBA"; actualSize = tex.mHeader.size*tex.mHeader.size*4; } else if (tex.mHeader.unknown0[1] == 0) // RGB { memcpy(outputData, tex.mData, tex.mHeader.size*tex.mHeader.size*3); //result = stbi_write_tga(argv[1], tex.mHeader.size, tex.mHeader.size, STBI_rgb, outputData); fmt = "RGB "; actualSize = tex.mHeader.size*tex.mHeader.size*3; } else if (tex.mHeader.unknown0[1] == 6) // RGBA5551 { unsigned short *in = (unsigned short*)tex.mData; unsigned char *out = outputData; for (int i=0; i<tex.mHeader.size*tex.mHeader.size; i++) { unsigned short alpha_mask = 0x800; unsigned short red_mask = 0x7C00; unsigned short green_mask = 0x3E0; unsigned short blue_mask = 0x1F; unsigned short inv = *in; inv >>= 1; *out++ = (inv & blue_mask) << 3; *out++ = ((inv & green_mask) >> 5) << 3; *out++ = ((inv & red_mask) >> 10) << 3; *out++ = (*in & 0x1) ? 255 : 0; in++; } //result = stbi_write_tga(argv[1], tex.mHeader.size, tex.mHeader.size, STBI_rgb_alpha, outputData); fmt = "5551"; actualSize = tex.mHeader.size*tex.mHeader.size*2; }
int main(int argc, char **argv) { int w,h; //test_ycbcr(); #if 0 // test hdr asserts for (h=0; h < 100; h += 2) for (w=0; w < 200; ++w) hdr_data[h][w][0] = (float) rand(), hdr_data[h][w][1] = (float) rand(), hdr_data[h][w][2] = (float) rand(); stbi_write_hdr("output/test.hdr", 200,200,3,hdr_data[0][0]); #endif if (argc > 1) { int i, n; for (i=1; i < argc; ++i) { int res; int w2,h2,n2; unsigned char *data; printf("%s\n", argv[i]); res = stbi_info(argv[1], &w2, &h2, &n2); data = stbi_load(argv[i], &w, &h, &n, 4); if (data) free(data); else printf("Failed &n\n"); data = stbi_load(argv[i], &w, &h, 0, 1); if (data) free(data); else printf("Failed 1\n"); data = stbi_load(argv[i], &w, &h, 0, 2); if (data) free(data); else printf("Failed 2\n"); data = stbi_load(argv[i], &w, &h, 0, 3); if (data) free(data); else printf("Failed 3\n"); data = stbi_load(argv[i], &w, &h, &n, 4); assert(data); assert(w == w2 && h == h2 && n == n2); assert(res); if (data) { char fname[512]; stb_splitpath(fname, argv[i], STB_FILE); stbi_write_png(stb_sprintf("output/%s.png", fname), w, h, 4, data, w*4); stbi_write_bmp(stb_sprintf("output/%s.bmp", fname), w, h, 4, data); stbi_write_tga(stb_sprintf("output/%s.tga", fname), w, h, 4, data); stbi_write_png_to_func(dummy_write,0, w, h, 4, data, w*4); stbi_write_bmp_to_func(dummy_write,0, w, h, 4, data); stbi_write_tga_to_func(dummy_write,0, w, h, 4, data); free(data); } else printf("FAILED 4\n"); } } else { int i, nope=0; #ifdef PNGSUITE_PRIMARY char **files = stb_readdir_files("pngsuite/primary"); #else char **files = stb_readdir_files("images"); #endif for (i=0; i < stb_arr_len(files); ++i) { int n; char **failed = NULL; unsigned char *data; printf("."); //printf("%s\n", files[i]); data = stbi_load(files[i], &w, &h, &n, 0); if (data) free(data); else stb_arr_push(failed, "&n"); data = stbi_load(files[i], &w, &h, 0, 1); if (data) free(data); else stb_arr_push(failed, "1"); data = stbi_load(files[i], &w, &h, 0, 2); if (data) free(data); else stb_arr_push(failed, "2"); data = stbi_load(files[i], &w, &h, 0, 3); if (data) free(data); else stb_arr_push(failed, "3"); data = stbi_load(files[i], &w, &h, 0, 4); if (data) ; else stb_arr_push(failed, "4"); if (data) { char fname[512]; #ifdef PNGSUITE_PRIMARY int w2,h2; unsigned char *data2; stb_splitpath(fname, files[i], STB_FILE_EXT); data2 = stbi_load(stb_sprintf("pngsuite/primary_check/%s", fname), &w2, &h2, 0, 4); if (!data2) printf("FAILED: couldn't load 'pngsuite/primary_check/%s\n", fname); else { if (w != w2 || h != w2 || 0 != memcmp(data, data2, w*h*4)) { int x,y,c; if (w == w2 && h == h2) for (y=0; y < h; ++y) for (x=0; x < w; ++x) for (c=0; c < 4; ++c) assert(data[y*w*4+x*4+c] == data2[y*w*4+x*4+c]); printf("FAILED: %s loaded but didn't match PRIMARY_check 32-bit version\n", files[i]); } free(data2); } #else stb_splitpath(fname, files[i], STB_FILE); stbi_write_png(stb_sprintf("output/%s.png", fname), w, h, 4, data, w*4); #endif free(data); } if (failed) { int j; printf("FAILED: "); for (j=0; j < stb_arr_len(failed); ++j) printf("%s ", failed[j]); printf(" -- %s\n", files[i]); } } printf("Tested %d files.\n", i); } return 0; }
font * ttf_write_tga (char *name, int32_t pointsize) { uint32_t rmask, gmask, bmask, amask; double glyph_per_row; char filename[200]; SDL_Surface *dst; uint32_t height; uint32_t width; double maxx; double maxy[TTF_GLYPH_MAX]; uint32_t c; int x; int y; double h; font *f; snprintf(filename, sizeof(filename), "%s_pointsize%u.tga", name, pointsize); if (tex_find(filename)) { return (0); } /* * x glyphs horizontally and y vertically. */ glyph_per_row = 16; f = ttf_new(name, pointsize, TTF_STYLE_NORMAL); if (!f) { ERR("could not create font %s", name); } maxx = 0; memset(maxy, 0, sizeof(maxy)); /* * Find the largest font glyph pointsize. */ x = 0; y = 0; height = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { if (f->tex[c].image) { maxx = max(maxx, f->tex[c].image->w); maxy[y] = max(maxy[y], f->tex[c].image->h); } if (++x >= glyph_per_row) { x = 0; height += maxy[y]; y++; } } if (!maxx) { ERR("no glyphs in font %s", name); } width = glyph_per_row * maxx; if (MULTIPLE_BITS(width)) { width = nextpoweroftwo(width); } height += 40; if (MULTIPLE_BITS(height)) { height = nextpoweroftwo(height); } /* * Make a large surface for all glyphs. */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif dst = SDL_CreateRGBSurface(0, width, height, 32, rmask, gmask, bmask, amask); if (!dst) { ERR("no surface created for size %dx%d font %s", width, height, name); } newptr(dst, "SDL_CreateRGBSurface"); /* * Blit each glyph to the large surface. */ x = 0; y = 0; h = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { if (f->tex[c].image) { SDL_Rect dstrect = { maxx * x, h, maxx, maxy[y] }; SDL_BlitSurface(f->tex[c].image, 0, dst, &dstrect); } if (++x >= glyph_per_row) { x = 0; h += maxy[y]; y++; } } /* * Convert the black border smoothing that ttf adds into alpha. */ { double x; double y; for (x = 0; x < dst->w; x++) { for (y = 0; y < dst->h; y++) { color c; c = getPixel(dst, x, y); if ((c.a == 255) && (c.r == 255) && (c.g == 255) && (c.b == 255)) { /* * Do nothing. */ } else if ((c.a == 0) && (c.r == 0) && (c.g == 0) && (c.b == 0)) { /* * Do nothing. */ } else { /* * Convery gray to white with alpha. */ c.a = (c.r + c.g + c.b) / 3; c.r = 255; c.g = 255; c.b = 255; } putPixel(dst, x, y, c); } } } #define MAX_TEXTURE_HEIGHT 4096 if (dst->h > MAX_TEXTURE_HEIGHT) { ERR("ttf is too large"); } uint8_t filled_pixel_row[MAX_TEXTURE_HEIGHT] = {0}; /* * What the hell am I doing here? The ttf library returns incorrect * boounds for the top and bottom of glyphs, so I'm looking for a line of * no pixels above and below each glyph so I can really find the texture * bounds of a glyph. This allows squeezing of text together. */ { int x; int y; for (y = 0; y < dst->h; y++) { for (x = 0; x < dst->w; x++) { color c; c = getPixel(dst, x, y); if (c.r || c.g || c.b || c.a) { filled_pixel_row[y] = true; break; } } } } /* * Work our the tex co-ords for each glyph in the large tex. */ x = 0; y = 0; h = 0; int d1_max = 0; int d2_max = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { { int y = (h + (h + f->glyphs[c].height)) / 2; int miny = y; int maxy = y; for (;;) { if (!filled_pixel_row[miny]) { break; } miny--; if (miny <= 0) { break; } } for (;;) { if (!filled_pixel_row[maxy]) { break; } maxy++; if (maxy >= MAX_TEXTURE_HEIGHT - 1) { break; } } int d1 = y - miny; if (d1 > d1_max) { d1_max = d1; } int d2 = maxy - y; if (d2 > d2_max) { d2_max = d2; } } if (++x >= glyph_per_row) { x = 0; h += maxy[y]; y++; } } x = 0; y = 0; h = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { f->glyphs[c].texMinX = (double)(x * maxx) / (double)dst->w; f->glyphs[c].texMaxX = (double)((x * maxx) + f->glyphs[c].width) / (double)dst->w; { int y = (h + (h + f->glyphs[c].height)) / 2; int y1 = y - d1_max; int y2 = y + d2_max; if (y1 < 0) { y1 = 0; } f->glyphs[c].texMinY = (double)(y1) / (double)dst->h; f->glyphs[c].texMaxY = (double)(y2) / (double)dst->h; } if (++x >= glyph_per_row) { x = 0; h += maxy[y]; y++; } } SDL_LockSurface(dst); stbi_write_tga(filename, dst->w, dst->h, STBI_rgb_alpha, dst->pixels); SDL_UnlockSurface(dst); texp tex; tex = tex_from_surface(dst, filename, filename); if (!tex) { ERR("could not convert %s to tex", filename); } /* * Work our the tex co-ords for each glyph in the large tex. */ x = 0; y = 0; h = 0; for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { f->tex[c].image = dst; f->tex[c].tex = tex_get_gl_binding(tex); } /* * Save the glyph data. */ snprintf(filename, sizeof(filename), "%s_pointsize%u.data", name, pointsize); FILE *out = fopen(filename, "w"); fwrite(f->glyphs, sizeof(f->glyphs), 1, out); fclose(out); printf("wrote %s\n",filename); return (f); }
int main(int arg_c, char* ppArgs[]) { printf("jpge/jpgd example app\n"); // Parse command line. bool run_exhausive_test = false; bool test_memory_compression = false; bool optimize_huffman_tables = false; int subsampling = -1; char output_filename[256] = ""; bool use_jpgd = true; bool test_jpgd_decompression = false; int arg_index = 1; while ((arg_index < arg_c) && (ppArgs[arg_index][0] == '-')) { switch (tolower(ppArgs[arg_index][1])) { case 'd': test_jpgd_decompression = true; break; case 'g': strcpy_s(s_log_filename, sizeof(s_log_filename), &ppArgs[arg_index][2]); break; case 'x': run_exhausive_test = true; break; case 'm': test_memory_compression = true; break; case 'o': optimize_huffman_tables = true; break; case 'l': if (strcasecmp(&ppArgs[arg_index][1], "luma") == 0) subsampling = jpge::Y_ONLY; else { log_printf("Unrecognized option: %s\n", ppArgs[arg_index]); return EXIT_FAILURE; } break; case 'h': if (strcasecmp(&ppArgs[arg_index][1], "h1v1") == 0) subsampling = jpge::H1V1; else if (strcasecmp(&ppArgs[arg_index][1], "h2v1") == 0) subsampling = jpge::H2V1; else if (strcasecmp(&ppArgs[arg_index][1], "h2v2") == 0) subsampling = jpge::H2V2; else { log_printf("Unrecognized subsampling: %s\n", ppArgs[arg_index]); return EXIT_FAILURE; } break; case 'w': { strcpy_s(output_filename, sizeof(output_filename), &ppArgs[arg_index][2]); break; } case 's': { use_jpgd = false; break; } default: log_printf("Unrecognized option: %s\n", ppArgs[arg_index]); return EXIT_FAILURE; } arg_index++; } if (run_exhausive_test) { if ((arg_c - arg_index) < 1) { log_printf("Not enough parameters (expected source file)\n"); return print_usage(); } const char* pSrc_filename = ppArgs[arg_index++]; return exhausive_compression_test(pSrc_filename, use_jpgd); } else if (test_jpgd_decompression) { if ((arg_c - arg_index) < 2) { log_printf("Not enough parameters (expected source and destination files)\n"); return print_usage(); } const char* pSrc_filename = ppArgs[arg_index++]; const char* pDst_filename = ppArgs[arg_index++]; return test_jpgd(pSrc_filename, pDst_filename); } // Test jpge if ((arg_c - arg_index) < 3) { log_printf("Not enough parameters (expected source file, dest file, quality factor to follow options)\n"); return print_usage(); } const char* pSrc_filename = ppArgs[arg_index++]; const char* pDst_filename = ppArgs[arg_index++]; int quality_factor = atoi(ppArgs[arg_index++]); if ((quality_factor < 1) || (quality_factor > 100)) { log_printf("Quality factor must range from 1-100!\n"); return EXIT_FAILURE; } // Load the source image. const int req_comps = 3; // request RGB image int width = 0, height = 0, actual_comps = 0; uint8 *pImage_data = stbi_load(pSrc_filename, &width, &height, &actual_comps, req_comps); if (!pImage_data) { log_printf("Failed loading file \"%s\"!\n", pSrc_filename); return EXIT_FAILURE; } log_printf("Source file: \"%s\", image resolution: %ix%i, actual comps: %i\n", pSrc_filename, width, height, actual_comps); // Fill in the compression parameter structure. jpge::params params; params.m_quality = quality_factor; params.m_subsampling = (subsampling < 0) ? ((actual_comps == 1) ? jpge::Y_ONLY : jpge::H2V2) : static_cast<jpge::subsampling_t>(subsampling); params.m_two_pass_flag = optimize_huffman_tables; log_printf("Writing JPEG image to file: %s\n", pDst_filename); timer tm; // Now create the JPEG file. if (test_memory_compression) { int buf_size = width * height * 3; // allocate a buffer that's hopefully big enough (this is way overkill for jpeg) if (buf_size < 1024) buf_size = 1024; void *pBuf = malloc(buf_size); tm.start(); if (!jpge::compress_image_to_jpeg_file_in_memory(pBuf, buf_size, width, height, req_comps, pImage_data, params)) { log_printf("Failed creating JPEG data!\n"); return EXIT_FAILURE; } tm.stop(); FILE *pFile = fopen(pDst_filename, "wb"); if (!pFile) { log_printf("Failed creating file \"%s\"!\n", pDst_filename); return EXIT_FAILURE; } if (fwrite(pBuf, buf_size, 1, pFile) != 1) { log_printf("Failed writing to output file!\n"); return EXIT_FAILURE; } if (fclose(pFile) == EOF) { log_printf("Failed writing to output file!\n"); return EXIT_FAILURE; } } else { tm.start(); if (!jpge::compress_image_to_jpeg_file(pDst_filename, width, height, req_comps, pImage_data, params)) { log_printf("Failed writing to output file!\n"); return EXIT_FAILURE; } tm.stop(); } double total_comp_time = tm.get_elapsed_ms(); const uint comp_file_size = get_file_size(pDst_filename); const uint total_pixels = width * height; log_printf("Compressed file size: %u, bits/pixel: %3.3f\n", comp_file_size, (comp_file_size * 8.0f) / total_pixels); // Now try loading the JPEG file using jpgd or stbi_image's JPEG decompressor. int uncomp_width = 0, uncomp_height = 0, uncomp_actual_comps = 0, uncomp_req_comps = 3; tm.start(); uint8 *pUncomp_image_data; if (use_jpgd) pUncomp_image_data = jpgd::decompress_jpeg_image_from_file(pDst_filename, &uncomp_width, &uncomp_height, &uncomp_actual_comps, uncomp_req_comps); else pUncomp_image_data = stbi_load(pDst_filename, &uncomp_width, &uncomp_height, &uncomp_actual_comps, uncomp_req_comps); double total_uncomp_time = tm.get_elapsed_ms(); if (!pUncomp_image_data) { log_printf("Failed loading compressed image file \"%s\"!\n", pDst_filename); return EXIT_FAILURE; } log_printf("Compression time: %3.3fms, Decompression time: %3.3fms\n", total_comp_time, total_uncomp_time); // Write uncompressed image. if (output_filename[0]) stbi_write_tga(output_filename, uncomp_width, uncomp_height, uncomp_req_comps, pUncomp_image_data); if ((uncomp_width != width) || (uncomp_height != height)) { log_printf("Loaded JPEG file has a different resolution than the original file!\n"); return EXIT_FAILURE; } // Diff the original and compressed images. image_compare_results results; image_compare(results, width, height, pImage_data, req_comps, pUncomp_image_data, uncomp_req_comps, (params.m_subsampling == jpge::Y_ONLY) || (actual_comps == 1) || (uncomp_actual_comps == 1)); log_printf("Error Max: %f, Mean: %f, Mean^2: %f, RMSE: %f, PSNR: %f\n", results.max_err, results.mean, results.mean_squared, results.root_mean_squared, results.peak_snr); log_printf("Success.\n"); return EXIT_SUCCESS; }
int write_tga(char const *filename, int x, int y, int comp, Array<unsigned char> bytes, unsigned int byteOffset, unsigned int byteLength) { return stbi_write_tga(filename, x, y, comp, &bytes[0] + byteOffset); }
int main(int arg_c, char** arg_v) { if (arg_c != 5) { printf("Usage: input_image output_image.tga width height\n"); return EXIT_FAILURE; } const char* pSrc_filename = arg_v[1]; const char* pDst_filename = arg_v[2]; const int dst_width = atoi(arg_v[3]); const int dst_height = atoi(arg_v[4]); if ((std::min(dst_width, dst_height) < 1) || (std::max(dst_width, dst_height) > RESAMPLER_MAX_DIMENSION)) { printf("Invalid output width/height!\n"); return EXIT_FAILURE; } printf("Loading image: %s\n", pSrc_filename); int src_width, src_height, n; unsigned char* pSrc_image = stbi_load(pSrc_filename, &src_width, &src_height, &n, 0); if (!pSrc_image) { printf("Failed loading image!\n"); return EXIT_FAILURE; } printf("Resolution: %ux%u, Channels: %u\n", src_width, src_height, n); const int max_components = 4; if ((std::max(src_width, src_height) > RESAMPLER_MAX_DIMENSION) || (n > max_components)) { printf("Image is too large!\n"); return EXIT_FAILURE; } // Partial gamma correction looks better on mips. Set to 1.0 to disable gamma correction. const float source_gamma = 1.75f; // Filter scale - values < 1.0 cause aliasing, but create sharper looking mips. const float filter_scale = 1.0f;//.75f; const char* pFilter = "blackman";//RESAMPLER_DEFAULT_FILTER; float srgb_to_linear[256]; for (int i = 0; i < 256; ++i) srgb_to_linear[i] = (float)pow(i * 1.0f/255.0f, source_gamma); const int linear_to_srgb_table_size = 4096; unsigned char linear_to_srgb[linear_to_srgb_table_size]; const float inv_linear_to_srgb_table_size = 1.0f / linear_to_srgb_table_size; const float inv_source_gamma = 1.0f / source_gamma; for (int i = 0; i < linear_to_srgb_table_size; ++i) { int k = (int)(255.0f * pow(i * inv_linear_to_srgb_table_size, inv_source_gamma) + .5f); if (k < 0) k = 0; else if (k > 255) k = 255; linear_to_srgb[i] = (unsigned char)k; } Resampler* resamplers[max_components]; std::vector<float> samples[max_components]; // Now create a Resampler instance for each component to process. The first instance will create new contributor tables, which are shared by the resamplers // used for the other components (a memory and slight cache efficiency optimization). resamplers[0] = new Resampler(src_width, src_height, dst_width, dst_height, Resampler::BOUNDARY_CLAMP, 0.0f, 1.0f, pFilter, NULL, NULL, filter_scale, filter_scale); samples[0].resize(src_width); for (int i = 1; i < n; i++) { resamplers[i] = new Resampler(src_width, src_height, dst_width, dst_height, Resampler::BOUNDARY_CLAMP, 0.0f, 1.0f, pFilter, resamplers[0]->get_clist_x(), resamplers[0]->get_clist_y(), filter_scale, filter_scale); samples[i].resize(src_width); } std::vector<unsigned char> dst_image(dst_width * n * dst_height); const int src_pitch = src_width * n; const int dst_pitch = dst_width * n; int dst_y = 0; printf("Resampling to %ux%u\n", dst_width, dst_height); for (int src_y = 0; src_y < src_height; src_y++) { const unsigned char* pSrc = &pSrc_image[src_y * src_pitch]; for (int x = 0; x < src_width; x++) { for (int c = 0; c < n; c++) { if ((c == 3) || ((n == 2) && (c == 1))) samples[c][x] = *pSrc++ * (1.0f/255.0f); else samples[c][x] = srgb_to_linear[*pSrc++]; } } for (int c = 0; c < n; c++) { if (!resamplers[c]->put_line(&samples[c][0])) { printf("Out of memory!\n"); return EXIT_FAILURE; } } for ( ; ; ) { int comp_index; for (comp_index = 0; comp_index < n; comp_index++) { const float* pOutput_samples = resamplers[comp_index]->get_line(); if (!pOutput_samples) break; const bool alpha_channel = (comp_index == 3) || ((n == 2) && (comp_index == 1)); assert(dst_y < dst_height); unsigned char* pDst = &dst_image[dst_y * dst_pitch + comp_index]; for (int x = 0; x < dst_width; x++) { if (alpha_channel) { int c = (int)(255.0f * pOutput_samples[x] + .5f); if (c < 0) c = 0; else if (c > 255) c = 255; *pDst = (unsigned char)c; } else { int j = (int)(linear_to_srgb_table_size * pOutput_samples[x] + .5f); if (j < 0) j = 0; else if (j >= linear_to_srgb_table_size) j = linear_to_srgb_table_size - 1; *pDst = linear_to_srgb[j]; } pDst += n; } } if (comp_index < n) break; dst_y++; } } printf("Writing TGA file: %s\n", pDst_filename); if (!stbi_write_tga(pDst_filename, dst_width, dst_height, n, &dst_image[0])) { printf("Failed writing output image!\n"); return EXIT_FAILURE; } stbi_image_free(pSrc_image); // Delete the resamplers. for (int i = 0; i < n; i++) delete resamplers[i]; return EXIT_SUCCESS; }