static const std::string getConfigCurrentSpinner(const std::string &key) { std::string value = "spinner"; std::ifstream in(eEnv::resolve("${sysconfdir}/enigma2/settings").c_str()); if (in.good()) { do { std::string line; std::getline(in, line); size_t size = key.size(); if (line.compare(0, size, key)== 0) { value = line.substr(size + 1); replace(value, "skin.xml", "spinner"); break; } } while (in.good()); in.close(); } // if value is empty, means no config.skin.primary_skin exist in settings file, so return just default spinner ( /usr/share/enigma2/spinner ) if (value.empty()) return value; // if value is NOT empty, means config.skin.primary_skin exist in settings file, so return SCOPE_CURRENT_SKIN + "/spinner" ( /usr/share/enigma2/MYSKIN/spinner ) BUT check if /usr/share/enigma2/MYSKIN/spinner/wait1.png exist std::string png_location = "/usr/share/enigma2/" + value + "/wait1.png"; std::ifstream png(png_location.c_str()); if (png.good()) { png.close(); return value; // if value is NOT empty, means config.skin.primary_skin exist in settings file, so return SCOPE_CURRENT_SKIN + "/spinner" ( /usr/share/enigma2/MYSKIN/spinner/wait1.png exist ) } else return "spinner"; // if value is NOT empty, means config.skin.primary_skin exist in settings file, so return "spinner" ( /usr/share/enigma2/MYSKIN/spinner/wait1.png DOES NOT exist ) }
/** * Extract block colors from given terrain.png file */ bool extractColors(const char* file) { PngReader png(file); if (!png.isValidImage()) return false; if (png.getWidth() != png.getHeight() // Quadratic || (png.getWidth() / 16) * 16 != png.getWidth() // Has to be multiple of 16 || png.getBitsPerChannel() != 8 // 8 bits per channel, 32bpp in total || png.getColorType() != PngReader::RGBA) return false; uint8_t *imgData = png.getImageData(); // Load em up for (int i = 0; i < 256; i++) { if (i == TORCH) { continue; // Keep those yellow for now } int r, g, b, a, n; // i i s g t u o l v n if (getTileRGBA(imgData, png.getWidth() / 16, i, r, g, b, a, n)) { const bool flag = (colors[i][PALPHA] == 254); if (i == FENCE) { r = clamp(r + 10); g = clamp(g + 10); b = clamp(b + 10); } SETCOLORNOISE(i, r, g, b, a, n); if (flag) { colors[i][PALPHA] = 254; // If you don't like this, dump texture pack to txt file and modify that one } } } return true; }
CL_PixelBuffer CL_PNGProvider::load(CL_IODevice &iodev) { CL_PNGProvider_Impl png(iodev); CL_PixelBuffer pbuff(png.width, png.height, png.sized_format, png.palette, png.get_data()); pbuff.set_colorkey(png.uses_src_colorkey(), png.get_src_colorkey()); return pbuff; }
int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_struct_ptr_t<CellPngDecDataCtrlParam> dataCtrlParam, mem_struct_ptr_t<CellPngDecDataOutInfo> dataOutInfo) { dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP; ID sub_handle_id_data; if(!cellPngDec.CheckId(subHandle, sub_handle_id_data)) return CELL_PNGDEC_ERROR_FATAL; auto subHandle_data = (CellPngDecSubHandle*)sub_handle_id_data.m_data; const u32& fd = subHandle_data->fd; const u64& fileSize = subHandle_data->fileSize; const CellPngDecOutParam& current_outParam = subHandle_data->outParam; //Copy the PNG file to a buffer MemoryAllocator<unsigned char> png(fileSize); MemoryAllocator<u64> pos, nread; cellFsLseek(fd, 0, CELL_SEEK_SET, pos); cellFsRead(fd, png.GetAddr(), png.GetSize(), nread); //Decode PNG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; std::shared_ptr<unsigned char> image(stbi_load_from_memory(png, fileSize, &width, &height, &actual_components, 4)); if (!image) return CELL_PNGDEC_ERROR_STREAM_FORMAT; uint image_size = width * height; switch(current_outParam.outputColorSpace) { case CELL_PNGDEC_RGB: case CELL_PNGDEC_RGBA: image_size *= current_outParam.outputColorSpace == CELL_PNGDEC_RGBA ? 4 : 3; memcpy(data, image.get(), image_size); break; case CELL_PNGDEC_ARGB: image_size *= 4; for(uint i = 0; i < image_size; i+=4) { data += image.get()[i+3]; data += image.get()[i+0]; data += image.get()[i+1]; data += image.get()[i+2]; } break; case CELL_PNGDEC_GRAYSCALE: case CELL_PNGDEC_PALETTE: case CELL_PNGDEC_GRAYSCALE_ALPHA: cellPngDec.Error("cellPngDecDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE()); break; default: return CELL_PNGDEC_ERROR_ARG; } dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_FINISH; return CELL_OK; }
void NPC::create_npc(NPCAnimation type, const std::string& filename, int animation_speed, bool one_shot, ZipReader *zip) throw (Exception) { PNG png(filename, zip); tiles[DirectionRight][type] = create_tile(png, animation_speed, one_shot, false); png.flip_h(); tiles[DirectionLeft][type] = create_tile(png, animation_speed, one_shot, true); }
CL_PixelBuffer CL_PNGProvider::load( const CL_String &filename, const CL_VirtualDirectory &directory) { CL_PNGProvider_Impl png(filename, directory); CL_PixelBuffer pbuff(png.width, png.height, png.sized_format, png.palette, png.get_data()); pbuff.set_colorkey(png.uses_src_colorkey(), png.get_src_colorkey()); return pbuff; }
void MidpointDisplacement::to_png( const std::string &file ) const { pngwriter png( 1024, 1024, 0, file.c_str() ); for ( unsigned int i = 0; i < m_data.size(); i++ ) { png.plot( m_data[ i ].m_x, m_data[ i ].m_y, 1.0, 0.0, 0.0 ); } png.close(); }
// load one or more files, print an ascii representation // and write a blurred version to out.png int main(int argc, char* argv[]){ for(int i=1; i < argc; i++){ PNG png(argv[i]); png.display(); png.blur<uint32_t>(5); png.write("out.png"); } }
fz_error * fz_processpredict(fz_filter *filter, fz_buffer *in, fz_buffer *out) { fz_predict *dec = (fz_predict*)filter; int ispng = dec->predictor >= 10; int predictor; while (1) { if (in->rp + dec->stride + (!dec->encode && ispng) > in->wp) { if (in->eof) return fz_iodone; return fz_ioneedin; } if (out->wp + dec->stride + (dec->encode && ispng) > out->ep) return fz_ioneedout; if (dec->predictor == 1) { none(dec, in->rp, out->wp); } else if (dec->predictor == 2) { if (dec->bpc != 8) memset(out->wp, 0, dec->stride); tiff(dec, in->rp, out->wp); } else { if (dec->encode) { predictor = dec->predictor - 10; if (predictor < 0 || predictor > 4) predictor = 1; *out->wp ++ = predictor; } else { predictor = *in->rp++; } png(dec, in->rp, out->wp, predictor); } if (dec->ref) memcpy(dec->ref, out->wp, dec->stride); in->rp += dec->stride; out->wp += dec->stride; } }
int main(int argc, char *argv[]) { int width, height; char *end; FILE *io_in, *io_out; io_in = stdin; io_out = stdout; if (argc < 3) { fprintf(stderr, "Usage: %s WIDTH HEIGHT [file] [file]\n", argv[0]); return 1; } if (argc > 3) { io_in = fopen(argv[3], "r"); if (!io_in) { fprintf(stderr, "Unable to open source file.\n"); return 1; } } if (argc > 4) { io_out = fopen(argv[4], "w"); if (!io_out) { fprintf(stderr, "Unable to open destination file.\n"); return 1; } } width = strtoul(argv[1], &end, 10); if (*end) { fprintf(stderr, "Error: Invalid width.\n"); return 1; } height = strtoul(argv[2], &end, 10); if (*end) { fprintf(stderr, "Error: Invalid height.\n"); return 1; } if (looks_like_png(io_in)) { png(io_in, io_out, width, height); } else { jpeg(io_in, io_out, width, height); } fclose(io_in); fclose(io_out); return 0; }
Font::Font(Subsystem& subsystem, const std::string& filename, ZipReader *zip) throw (KeyValueException, FontException) : Properties(filename + ".font", zip), subsystem(subsystem) { try { PNG png(filename + ".png", zip); /* setup font operations */ FontOperations fo; if (zip) { fo.handle = zip; fo.open = &fo_zip_open; fo.read = &fo_zip_read; fo.close = &fo_zip_close; } else { fo.handle = 0; fo.open = &fo_file_open; fo.read = &fo_file_read; fo.close = &fo_file_close; } std::string font_description = filename + ".fds"; fo.open(fo, font_description); char header[4]; fo.read(fo, header, sizeof(header)); if (memcmp(header, "FNT1", 4)) { throw FontException("wrong font file " + font_description); } fo.read(fo, &font_height, sizeof font_height); font_height = ntohl(font_height) * 2; spacing = atoi(get_value("spacing").c_str()); font_char_t font; for (int i = 0; i < NumOfChars; i++) { fo.read(fo, &font, sizeof font); font.origin_x = ntohl(font.origin_x); font.origin_y = ntohl(font.origin_y); font.width = ntohl(font.width); font.height = ntohl(font.height); TileGraphic *tg = subsystem.create_tilegraphic(font.width, font.height); tg->punch_out_tile(png, font.origin_x, font.origin_y, false); tiles[i] = new Tile(tg, false, Tile::TileTypeNonblocking, 0, false, 0.0f); fw[i] = font.width; fh[i] = font.height; } } catch (const Exception& e) { throw FontException(e.what()); } }
bool C4Surface::SavePNG(const char *szFilename, bool fSaveAlpha, bool fSaveOverlayOnly, bool use_background_thread) { // Lock - WARNING - maybe locking primary surface here... if (!Lock()) return false; // create png file std::unique_ptr<CPNGFile> png(new CPNGFile()); if (!png->Create(Wdt, Hgt, fSaveAlpha)) { Unlock(); return false; } // reset overlay if desired C4Surface *pMainSfcBackup = NULL; if (fSaveOverlayOnly) { pMainSfcBackup=pMainSfc; pMainSfc=NULL; } #ifndef USE_CONSOLE if (fPrimary) { // Take shortcut. FIXME: Check Endian for (int y = 0; y < Hgt; ++y) glReadPixels(0, Hgt - y - 1, Wdt, 1, fSaveAlpha ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, png->GetRow(y)); } else #endif { // write pixel values for (int y=0; y<Hgt; ++y) for (int x=0; x<Wdt; ++x) { DWORD dwClr = GetPixDw(x, y, false); png->SetPix(x, y, dwClr); } } // reset overlay if (fSaveOverlayOnly) pMainSfc=pMainSfcBackup; // Unlock Unlock(); // save png - either directly or delayed in a background thread if desired if (use_background_thread) { CPNGFile::ScheduleSaving(png.release(), szFilename); } else { if (!png->Save(szFilename)) return false; } // Success return true; }
std::pair<float*,std::pair<unsigned int,unsigned int>> readPNG( std::string const _filename ) { pngwriter png( 1, 1, 0, "tmp.png" ); png.readfromfile( _filename.c_str( ) ); int x = png.getwidth( ); int y = png.getheight( ); /* check if pngwriter could load image. This is not cool, because * this disables use of real PNGs of size 1x1 but the algorithm * wouldn't work on those anyway. The problem is, that pngwriter * doesn't return an error, it just prints to stderr :S */ if ( x == 1 or y == 1 ) { assert("Couldn't open PNG file! Path and permissions correct?"); return { NULL, { 0, 0 } }; } float* mem = new float[x * y]; for( auto i = 0; i < y; i++ ) { for( auto j = 0; j < x; j++ ) { mem[(i * x) + j] = (float) png.read( i, j, 1 ) / 65535; } } png.close( ); # ifdef IMRESH_DEBUG if( remove( "tmp.png" ) != 0 ) { perror( "imresh::io::readInFuncs::readPNG(): Error deleting temporary file" ); } else { std::cout << "imresh::io::readInFuncs::readPNG(): Successfully read file." << std::endl; } # else remove( "tmp.png" ); # endif return { mem, { x, y } }; }
Label::Label(screen_context_t context, int x, int y, unsigned width, unsigned height, int alpha, char *imageFile) : m_x(x), m_y(y), m_width(width), m_height(height), m_window(0) { FILE *file = 0; if (imageFile) { file = fopen(imageFile, "rb"); } if (file) { PNGReader png(file, imageFile, context); if (png.doRead()) { m_window = LabelWindow::create(context, width, height, alpha); m_window->draw(png); } } }
void operator() (uint32_t currentStep, DBox data, Space dataSize) { std::stringstream step; step << std::setw(6) << std::setfill('0') << currentStep; std::string filename("gol_" + step.str() + ".png"); pngwriter png(dataSize.x(), dataSize.y(), 0, filename.c_str()); png.setcompressionlevel(9); for (int y = 0; y < dataSize.y(); ++y) { for (int x = 0; x < dataSize.x(); ++x) { float p = data[y ][x ]; png.plot(x + 1, dataSize.y() - y, p, p, p); } } png.close(); }
int main() { int i; int y; pngwriter png(300,300,0,"test.png"); for(i = 1; i ≤ 300;i++) { y = 150+100*sin((double)i*9/300.0); png.plot(i,y, 0.0, 0.0, 1.0); } png.close(); return 0; }
static const std::string getConfigCurrentSpinner(const std::string &key) { std::string value = ""; std::ifstream in(eEnv::resolve("${sysconfdir}/enigma2/settings").c_str()); if (in.good()) { do { std::string line; std::getline(in, line); size_t size = key.size(); if (line.compare(0, size, key)== 0) { value = line.substr(size + 1); size_t end_pos = value.find("skin.xml"); if (end_pos != std::string::npos) { value = value.substr(0, end_pos); } break; } } while (in.good()); in.close(); } // no config.skin.primary_skin found -> Use default one if (value.empty()) value = "GigabluePax/"; // return SCOPE_CURRENT_SKIN ( /usr/share/enigma2/MYSKIN/skin_default/spinner ) BUT check if /usr/share/enigma2/MYSKIN/skin_default/spinner/wait1.png exist std::string png_location = "/usr/share/enigma2/" + value + "skin_default/spinner/wait1.png"; std::ifstream png(png_location.c_str()); if (png.good()) { png.close(); return value; // /usr/share/enigma2/MYSKIN/skin_default/spinner/wait1.png exists ) } else { return ""; // No spinner found -> use "" ( /usr/share/enigma2/skin_default/spinner/wait1.png ) } }
bool Control::loadFromPNG(const char *filename) { FILE *file = fopen(filename, "rb"); if (!file) { fprintf(stderr, "Unable to open file %s\n", filename); return false; } PNGReader png(file, m_context); if (!png.doRead()) return false; m_srcWidth = png.m_width; m_srcHeight = png.m_height; m_pixmap = png.m_pixmap; png.m_pixmap = 0; m_buffer = png.m_buffer; png.m_buffer = 0; // int rc; // { // int format = SCREEN_FORMAT_RGBA8888; // int size[2] = {png.m_width, png.m_height}; // // rc = screen_create_pixmap(&m_pixmap, m_context); // FIXME: Check failure // rc = screen_set_pixmap_property_iv(m_pixmap, SCREEN_PROPERTY_FORMAT, &format); // rc = screen_set_pixmap_property_iv(m_pixmap, SCREEN_PROPERTY_BUFFER_SIZE, size); // rc = screen_create_pixmap_buffer(m_pixmap); // // unsigned char *realPixels; // int realStride; // rc = screen_get_pixmap_property_pv(m_pixmap, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)&m_buffer); // rc = screen_get_buffer_property_pv(m_buffer, SCREEN_PROPERTY_POINTER, (void **)&realPixels); // rc = screen_get_buffer_property_iv(m_buffer, SCREEN_PROPERTY_STRIDE, &realStride); // memcpy(realPixels, png.m_data, realStride * m_srcHeight); // } return true; }
void Animation::create_tile(const std::string& filename, ZipReader *zip) throw (Exception) { try { int tile_type_val = atoi(get_value("tile_type").c_str()); Tile::TileType tile_type = static_cast<Tile::TileType>(tile_type_val); bool background = (atoi(get_value("background").c_str()) == 0 ? false : true); bool one_shot = (atoi(get_value("one_shot").c_str()) != 0 ? true : false); PNG png(filename, zip); const int& png_width = png.get_width(); const int& png_height = png.get_height(); int tiley = 0; int tilex = 0; /* create all pictures consecutively for this tile */ TileGraphic *tg = subsystem.create_tilegraphic(tile_width, tile_height); while (tiley < png_height) { /* store current picture in the graphics layer */ tg->punch_out_tile(png, tilex, tiley, false); /* advance to next tile */ tilex += tile_width; if (tilex >= png_width) { tilex = 0; tiley += tile_height; } } /* create tile with its pictures */ tile = new Tile(tg, background, tile_type, animation_speed, one_shot, 0.0f); } catch (const Exception&) { cleanup(); throw; } }
_INITIALIZE_EASYLOGGINGPP void renderMapToFile(const World::Overview& map, const std::string& filename) { Png::PngData pngData; pngData.width = map.width(); pngData.height = map.height(); pngData.title = "Map"; Png::Png png(filename, pngData); LOG(DEBUG) << "Starting rows"; for (uint16_t y = 0; y < pngData.height; ++y) { std::vector<Png::RGB> row; for (uint16_t x = 0; x < pngData.width; ++x) { auto height = map.at(x, y).height(); if (height > 0) { row.push_back({0, 100, 0}); } else { row.push_back({0, 0, 100}); } } png.writeRow(row); } LOG(DEBUG) << "Finished rows"; }
void CameraSensor::saveImage(std::string fileName, std::string fileExtension) { INFO("Saving image %s", fileName.c_str()); if (fileExtension == "pbi") { TransportFile *transport = new TransportFile(fileName.c_str()); if (transport->open()) { //sendImageData(transport, false, false); de::fumanoids::message::Image pbImage; de::fumanoids::message::ImageData *pbRawImage = pbImage.add_imagedata(); image->getImageData(pbRawImage); std::string data; pbImage.SerializeToString(&data); uint32_t dataSize = data.size(); transport->write((const uint8_t*)data.c_str(), dataSize); transport->close(); } delete transport; } else { png::image< png::rgb_pixel > png(image->getImageWidth(), image->getImageHeight()); for (size_t x = 0; x < png.get_width(); ++x) { for (size_t y = 0; y < png.get_height(); ++y) { uint8_t r, g, b; ((IMAGETYPE*)image)->getPixelAsRGB(x, y, &r, &g, &b); png[y][x] = png::rgb_pixel(r, g, b); } } try { png.write(fileName); } catch (...) { } } }
int main(int iArgC, char *cArgV[]) { #ifdef __GLIBCXX__ // Set a better exception handler std::set_terminate(__gnu_cxx::__verbose_terminate_handler); #endif // Disable stdin/printf/etc. sync for a speed boost std::ios_base::sync_with_stdio(false); // Declare the supported options. po::options_description poOptions("Options"); poOptions.add_options() ("type,t", po::value<std::string>(), "specify the output file format") ; po::options_description poHidden("Hidden parameters"); poHidden.add_options() ("in", ".png to read") ("out", "output palette filename") ("help", "produce help message") ; po::options_description poVisible(""); poVisible.add(poOptions); po::options_description poComplete("Parameters"); poComplete.add(poOptions).add(poHidden); po::variables_map mpArgs; std::string srcFile, dstFile; std::string strType; try { po::parsed_options pa = po::parse_command_line(iArgC, cArgV, poComplete); // Parse the global command line options for (std::vector<po::option>::iterator i = pa.options.begin(); i != pa.options.end(); i++) { if (i->string_key.empty()) { // If we've already got an archive filename, complain that a second one // was given (probably a typo.) if (!dstFile.empty()) { std::cerr << "Error: unexpected extra parameter (multiple output " "filenames given?!)" << std::endl; return 1; } assert(i->value.size() > 0); // can't have no values with no name! if (srcFile.empty()) srcFile = i->value[0]; else dstFile = i->value[0]; } else if (i->string_key.compare("help") == 0) { std::cout << "Copyright (C) 2010 Adam Nielsen <*****@*****.**>\n" "This program comes with ABSOLUTELY NO WARRANTY. This is free software,\n" "and you are welcome to change and redistribute it under certain conditions;\n" "see <http://www.gnu.org/licenses/> for details.\n" "\n" "Utility to manipulate image palettes used by games.\n" "Build date " __DATE__ " " __TIME__ << "\n" "\n" "Usage: " PROGNAME " <input>.png -t <output-type> <output-filename>\n" << poVisible << "\n" << std::endl; return 0; } else if ( (i->string_key.compare("t") == 0) || (i->string_key.compare("type") == 0) ) { if (i->value.size() == 0) { std::cerr << PROGNAME ": --type (-t) requires a parameter." << std::endl; return 1; } strType = i->value[0]; } } if (srcFile.empty()) { std::cerr << "Error: no input .png filename given" << std::endl; return 1; } if (dstFile.empty()) { std::cerr << "Error: no output filename given" << std::endl; return 1; } if (strType.empty()) { std::cerr << "Error: no output format type (-t) given" << std::endl; return 1; } // Get the format handler for this file format gg::ManagerPtr pManager(gg::getManager()); gg::ImageTypePtr palType(pManager->getImageTypeByCode(strType)); if (!palType) { std::cerr << "Unknown file type given to -t/--type: " << strType << std::endl; return 1; } std::cout << "Extracting palette from " << srcFile << " to " << dstFile << " as type " << strType << std::endl; png::image<png::index_pixel> png( srcFile, png::require_color_space<png::index_pixel>() ); stream::file_sptr outStream(new stream::file()); try { outStream->create(dstFile.c_str()); } catch (const stream::open_error& e) { std::cerr << PROGNAME ": Unable to create " << dstFile << ": " << e.what() << std::endl; return 2; } camoto::SuppData dummy; gg::ImagePtr palOut = palType->create(outStream, dummy); gg::PaletteTablePtr pal(new gg::PaletteTable()); png::palette pngPal = png.get_palette(); for (png::palette::iterator i = pngPal.begin(); i != pngPal.end(); i++) { gg::PaletteEntry p; p.red = i->red; p.green = i->green; p.blue = i->blue; pal->push_back(p); } palOut->setPalette(pal); } catch (const po::unknown_option& e) { std::cerr << PROGNAME ": " << e.what() << ". Use --help for help." << std::endl; return 1; } catch (const po::invalid_command_line_syntax& e) { std::cerr << PROGNAME ": " << e.what() << ". Use --help for help." << std::endl; return 1; } return 0; }
int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_ptr_t<CellPngDecDataCtrlParam> dataCtrlParam, mem_ptr_t<CellPngDecDataOutInfo> dataOutInfo) { if (!data.IsGood() || !dataCtrlParam.IsGood() || !dataOutInfo.IsGood()) return CELL_PNGDEC_ERROR_ARG; dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_STOP; CellPngDecSubHandle* subHandle_data; if(!cellPngDec.CheckId(subHandle, subHandle_data)) return CELL_PNGDEC_ERROR_FATAL; const u32& fd = subHandle_data->fd; const u64& fileSize = subHandle_data->fileSize; const CellPngDecOutParam& current_outParam = subHandle_data->outParam; //Copy the PNG file to a buffer MemoryAllocator<unsigned char> png(fileSize); MemoryAllocator<u64> pos, nread; switch(subHandle_data->src.srcSelect.ToLE()) { case CELL_PNGDEC_BUFFER: Memory.Copy(png.GetAddr(), subHandle_data->src.streamPtr.ToLE(), png.GetSize()); break; case CELL_PNGDEC_FILE: cellFsLseek(fd, 0, CELL_SEEK_SET, pos.GetAddr()); cellFsRead(fd, png.GetAddr(), png.GetSize(), nread.GetAddr()); break; } //Decode PNG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; auto image = std::unique_ptr<unsigned char,decltype(&::free)> ( stbi_load_from_memory(png.GetPtr(), fileSize, &width, &height, &actual_components, 4), &::free ); if (!image) return CELL_PNGDEC_ERROR_STREAM_FORMAT; uint image_size = width * height; switch((u32)current_outParam.outputColorSpace) { case CELL_PNGDEC_RGB: case CELL_PNGDEC_RGBA: { const char nComponents = (CELL_PNGDEC_RGBA ? 4 : 3); image_size *= nComponents; if (dataCtrlParam->outputBytesPerLine > width * nComponents) //check if we need padding { //TODO: find out if we can't do padding without an extra copy char *output = (char *) malloc(dataCtrlParam->outputBytesPerLine*height); for (int i = 0; i < height; i++) { memcpy(&output[i*dataCtrlParam->outputBytesPerLine], &image.get()[width*nComponents*i], width*nComponents); } Memory.CopyFromReal(data.GetAddr(), output, dataCtrlParam->outputBytesPerLine*height); free(output); } else { Memory.CopyFromReal(data.GetAddr(), image.get(), image_size); } } break; case CELL_PNGDEC_ARGB: { const char nComponents = 4; image_size *= nComponents; if (dataCtrlParam->outputBytesPerLine > width * nComponents) //check if we need padding { //TODO: find out if we can't do padding without an extra copy char *output = (char *) malloc(dataCtrlParam->outputBytesPerLine*height); for (int i = 0; i < height; i++) { for (int j = 0; j < width * nComponents; j += nComponents){ output[i*dataCtrlParam->outputBytesPerLine + j ] = image.get()[i*width * nComponents + j + 3]; output[i*dataCtrlParam->outputBytesPerLine + j + 1] = image.get()[i*width * nComponents + j + 0]; output[i*dataCtrlParam->outputBytesPerLine + j + 2] = image.get()[i*width * nComponents + j + 1]; output[i*dataCtrlParam->outputBytesPerLine + j + 3] = image.get()[i*width * nComponents + j + 2]; } } Memory.CopyFromReal(data.GetAddr(), output, dataCtrlParam->outputBytesPerLine*height); free(output); } else { for (uint i = 0; i < image_size; i += nComponents) { data += image.get()[i + 3]; data += image.get()[i + 0]; data += image.get()[i + 1]; data += image.get()[i + 2]; } } } break; case CELL_PNGDEC_GRAYSCALE: case CELL_PNGDEC_PALETTE: case CELL_PNGDEC_GRAYSCALE_ALPHA: cellPngDec.Error("cellPngDecDecodeData: Unsupported color space (%d)", current_outParam.outputColorSpace.ToLE()); break; default: return CELL_PNGDEC_ERROR_ARG; } dataOutInfo->status = CELL_PNGDEC_DEC_STATUS_FINISH; return CELL_OK; }
bool PNGImage::load_from_file(const char* path) { uint8_t header[8]; // 8 is the maximum size that can be checked // open file and test for it being a png FILE *fp = fopen(path, "rb"); if (!fp) { printf("[read_png_file] File %s could not be opened for reading", path); return false; } ScopedCloseFile scope_close(fp); fread(header, 1, 8, fp); if (png_sig_cmp(header, 0, 8)) { printf("[read_png_file] File %s is not recognized as a PNG file", path); return false; } // initialize stuff _png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); if (!_png_ptr) { printf("[read_png_file] png_create_read_struct failed"); return false; } _info_ptr = png_create_info_struct(png(_png_ptr)); if (!_info_ptr) { printf("[read_png_file] png_create_info_struct failed"); return false; } if (setjmp(png_jmpbuf(png(_png_ptr)))) { printf("[read_png_file] Error during init_io"); return false; } png_init_io(png(_png_ptr), fp); png_set_sig_bytes(png(_png_ptr), 8); png_read_info(png(_png_ptr), png_info(_info_ptr)); _size.width = png_get_image_width(png(_png_ptr), png_info(_info_ptr)); _size.height = png_get_image_height(png(_png_ptr), png_info(_info_ptr)); png_byte color_type = png_get_color_type(png(_png_ptr), png_info(_info_ptr)); int bit_depth = png_get_bit_depth(png(_png_ptr), png_info(_info_ptr)); // let's just support 8bits per channel for now if (bit_depth == 16) { png_set_strip_16(png(_png_ptr)); } if (bit_depth < 8) { png_set_packing(png(_png_ptr)); } // fill alpha channel with 255 if absent if (color_type == PNG_COLOR_TYPE_RGB){ png_set_filler(png(_png_ptr), 255, PNG_FILLER_BEFORE); } int number_of_passes = png_set_interlace_handling(png(_png_ptr)); png_read_update_info(png(_png_ptr), png_info(_info_ptr)); // read file if (setjmp(png_jmpbuf(png(_png_ptr)))) { printf("[read_png_file] Error during read_image"); return false; } _rows = (png_bytep*) malloc(sizeof(png_bytep) * _size.height); for (int y = 0; y < _size.height; y++) { _rows[y] = (png_byte*) malloc(png_get_rowbytes(png(_png_ptr),png_info(_info_ptr))); } png_read_image(png(_png_ptr), _rows); return true; }
bool C4GraphicsSystem::DoSaveScreenshot(bool fSaveAll, const char *szFilename, float fSaveAllZoom) { // Fullscreen only if (Application.isEditor) return false; // back surface must be present if (!FullScreen.pSurface) return false; // save landscape if (fSaveAll) { // Create full map screenshots at zoom 2x. Fractional zooms (like 1.7x) should work but might cause some trouble at screen borders. float zoom = fSaveAllZoom; // get viewport to draw in C4Viewport *pVP=::Viewports.GetFirstViewport(); if (!pVP) return false; // create image large enough to hold the landscape std::unique_ptr<CPNGFile> png(new CPNGFile()); int32_t lWdt = GBackWdt * zoom, lHgt = GBackHgt * zoom; if (!png->Create(lWdt, lHgt, false)) return false; // get backbuffer size int32_t bkWdt=C4GUI::GetScreenWdt(), bkHgt=C4GUI::GetScreenHgt(); if (!bkWdt || !bkHgt) return false; // facet for blitting C4TargetFacet bkFct; // mark background to be redrawn InvalidateBg(); // draw on one big viewport pVP->SetOutputSize(0,0,0,0, bkWdt, bkHgt); // backup and clear sky parallaxity int32_t iParX=::Landscape.Sky.ParX; ::Landscape.Sky.ParX=10; int32_t iParY=::Landscape.Sky.ParY; ::Landscape.Sky.ParY=10; // backup and clear viewport borders FLOAT_RECT vp_borders = { pVP->BorderLeft, pVP->BorderRight, pVP->BorderTop, pVP->BorderBottom }; pVP->BorderLeft = pVP->BorderRight = pVP->BorderTop = pVP->BorderBottom = 0.0f; // temporarily change viewport player int32_t iVpPlr=pVP->Player; pVP->Player=NO_OWNER; // blit all tiles needed for (int32_t iY=0; iY<lHgt; iY+=bkHgt) for (int32_t iX=0; iX<lWdt; iX+=bkWdt) { // get max width/height int32_t bkWdt2=bkWdt,bkHgt2=bkHgt; if (iX+bkWdt2>lWdt) bkWdt2-=iX+bkWdt2-lWdt; if (iY+bkHgt2>lHgt) bkHgt2-=iY+bkHgt2-lHgt; // update facet bkFct.Set(FullScreen.pSurface, 0, 0, ceil(float(bkWdt2)/zoom), ceil(float(bkHgt2)/zoom), iX/zoom, iY/zoom, zoom, 0, 0); // draw there pVP->Draw(bkFct, true, false); // render FullScreen.pSurface->PageFlip(); FullScreen.pSurface->PageFlip(); // get output (locking primary!) if (FullScreen.pSurface->Lock()) { // transfer each pixel - slooow... for (int32_t iY2 = 0; iY2 < bkHgt2; ++iY2) #ifndef USE_CONSOLE glReadPixels(0, FullScreen.pSurface->Hgt - iY2 - 1, bkWdt2, 1, GL_BGR, GL_UNSIGNED_BYTE, reinterpret_cast<BYTE *>(png->GetRow(iY + iY2)) + iX * 3); #else for (int32_t iX2=0; iX2<bkWdt2; ++iX2) png->SetPix(iX+iX2, iY+iY2, FullScreen.pSurface->GetPixDw(iX2, iY2, false)); #endif // done; unlock FullScreen.pSurface->Unlock(); // This can take a long time and we would like to pump messages // However, we're currently hogging the primary surface and horrible things might happen if we do that, including initiation of another screenshot // The only thing that can be safely run is music (sound could play but that would just make them out of sync of the game) ::Application.MusicSystem.Execute(true); } } // restore viewport player pVP->Player=iVpPlr; // restore viewport borders pVP->BorderLeft = vp_borders.left; pVP->BorderTop = vp_borders.top; pVP->BorderRight = vp_borders.right; pVP->BorderBottom = vp_borders.bottom; // restore parallaxity ::Landscape.Sky.ParX=iParX; ::Landscape.Sky.ParY=iParY; // restore viewport size ::Viewports.RecalculateViewports(); // save! CPNGFile::ScheduleSaving(png.release(), szFilename); return true; } // Save primary surface in background thread return FullScreen.pSurface->SavePNG(szFilename, false, false, true); }
/** * Convert the given map into a PNG file on disk, by rendering the map as it * would appear in the game. * * @param map * Map file to export. * * @param allTilesets * Collection of tilesets to use when rendering the map. * * @param destFile * Filename of destination (including ".png") * * @throw stream::error on error */ void map2dToPng(const gm::Map2D& map, const gm::TilesetCollection& allTilesets, const std::string& destFile) { gg::Point outSize = map.mapSize(); // in pixels gg::Point globalTileSize = map.tileSize(); outSize.x *= globalTileSize.x; outSize.y *= globalTileSize.y; png::image<png::index_pixel> png(outSize.x, outSize.y); std::shared_ptr<const gg::Palette> srcPal; gg::ColourDepth depth = gg::ColourDepth::VGA; // default, should never be used for (auto& i : allTilesets) { depth = i.second->colourDepth(); if (i.second->caps() & gg::Tileset::Caps::HasPalette) { srcPal = i.second->palette(); break; } } int forceXP = -1; png::palette pngPal; png::tRNS pngTNS; int palOffset; auto transparentIndex = preparePalette(depth, srcPal.get(), &pngPal, &pngTNS, &palOffset, forceXP); png.set_palette(pngPal); if (pngTNS.size() > 0) png.set_tRNS(pngTNS); // Get the map background auto bg = map.background(allTilesets); switch (bg.att) { case gm::Map2D::Background::Attachment::NoBackground: { for (unsigned int y = 0; y < outSize.y; y++) { for (unsigned int x = 0; x < outSize.x; x++) { png[y][x] = transparentIndex; } } break; } case gm::Map2D::Background::Attachment::SingleColour: { // Find the background colour in the palette. This won't find transparent // colours, but that's what NoBackground is for. png::index_pixel clr(0); unsigned int palIndex = 0; for (auto& i : pngPal) { if ( (bg.clr.red == i.red) && (bg.clr.green == i.green) && (bg.clr.blue == i.blue) ) { clr = palIndex; break; } palIndex++; } for (unsigned int y = 0; y < outSize.y; y++) { for (unsigned int x = 0; x < outSize.x; x++) { png[y][x] = clr; } } break; } // TODO - case gm::Map2D::Background::Attachment::SingleImageCentred: case gm::Map2D::Background::Attachment::SingleImageTiled: { auto tilePixels = bg.img->convert(); auto tileMask = bg.img->convert_mask(); auto tileSize = bg.img->dimensions(); for (unsigned int y = 0; y < outSize.y; y++) { for (unsigned int x = 0; x < outSize.x; x++) { auto pos = (y % tileSize.y) * tileSize.x + (x % tileSize.x); png[y][x] = png::index_pixel( (tileMask[pos] & (int)gg::Image::Mask::Transparent) ? transparentIndex : (tilePixels[pos] + palOffset) ); } } break; } } for (auto& layer : map.layers()) { // Figure out the layer size (in tiles) and the tile size gg::Point layerSize, tileSize; getLayerDims(map, *layer, &layerSize, &tileSize); // Prepare tileset std::vector<CachedTile> cache; // Run through all items in the layer and render them one by one for (auto& t : layer->items()) { CachedTile thisTile; unsigned int tileCode = t.code; // Find the cached tile bool found = false; for (auto& ct : cache) { if (ct.code == tileCode) { thisTile = ct; found = true; break; } } if (!found) { // Tile hasn't been cached yet, load it from the tileset gm::Map2D::Layer::ImageFromCodeInfo imgType; try { imgType = layer->imageFromCode(t, allTilesets); } catch (const std::exception& e) { std::cerr << "Error loading image: " << e.what() << std::endl; imgType.type = gm::Map2D::Layer::ImageFromCodeInfo::ImageType::Unknown; } switch (imgType.type) { case gm::Map2D::Layer::ImageFromCodeInfo::ImageType::Supplied: assert(imgType.img); thisTile.data = imgType.img->convert(); thisTile.mask = imgType.img->convert_mask(); thisTile.dims = imgType.img->dimensions(); thisTile.code = tileCode; break; case gm::Map2D::Layer::ImageFromCodeInfo::ImageType::Blank: thisTile.dims = {0, 0}; break; case gm::Map2D::Layer::ImageFromCodeInfo::ImageType::NumImageTypes: // Avoid compiler warning about unhandled enum assert(false); // fall through case gm::Map2D::Layer::ImageFromCodeInfo::ImageType::Unknown: case gm::Map2D::Layer::ImageFromCodeInfo::ImageType::HexDigit: case gm::Map2D::Layer::ImageFromCodeInfo::ImageType::Interactive: // Display nothing, but could be changed to a question mark thisTile.dims = {0, 0}; break; } cache.push_back(thisTile); } if ((thisTile.dims.x == 0) || (thisTile.dims.y == 0)) continue; // no image // Draw tile onto png unsigned int tnsSize = pngTNS.size(); unsigned int offX = t.pos.x * tileSize.x; unsigned int offY = t.pos.y * tileSize.y; for (unsigned int tY = 0; tY < thisTile.dims.y; tY++) { unsigned int pngY = offY+tY; if (pngY >= outSize.y) break; // don't write past image edge for (unsigned int tX = 0; tX < thisTile.dims.x; tX++) { unsigned int pngX = offX+tX; if (pngX >= outSize.x) break; // don't write past image edge auto pos = tY * thisTile.dims.x + tX; // Only write opaque pixels if ((thisTile.mask[pos] & (int)gg::Image::Mask::Transparent) == 0) { unsigned int pix = thisTile.data[pos] + palOffset; // Also skip pixels if they are using palette transparency if ((pix >= tnsSize) || (pngTNS[pix] > 0)) { png[pngY][pngX] = png::index_pixel(pix); } } // else let higher layers see through to lower ones } } } // else layer is empty } png.write(destFile); return; }
s32 pngDecodeData(PPUThread& ppu, PHandle handle, PStream stream, vm::ptr<u8> data, PDataControlParam data_control_param, PDataOutInfo data_out_info, PCbControlDisp cb_control_disp = vm::null, PDispParam disp_param = vm::null) { if (cb_control_disp || disp_param) { throw EXCEPTION("Partial image decoding is not supported"); } // Indicate, that the PNG decoding is stopped/failed. This is incase, we return an error code in the middle of decoding data_out_info->status = CELL_PNGDEC_DEC_STATUS_STOP; // Possibilities for decoding in different sizes aren't tested, so if anyone finds any of these cases, we'll know about it. if (stream->info.imageWidth != stream->out_param.outputWidth) { throw EXCEPTION("Image width doesn't match output width! (%d/%d)", stream->out_param.outputWidth, stream->info.imageWidth); } if (stream->info.imageHeight != stream->out_param.outputHeight) { throw EXCEPTION("Image width doesn't match output height! (%d/%d)", stream->out_param.outputHeight, stream->info.imageHeight); } // Get the amount of output bytes per line const u32 bytes_per_line = data_control_param->outputBytesPerLine; // Whether to recaculate bytes per row bool recalculate_bytes_per_row = false; // Check if the game is expecting the number of bytes per line to be lower, than the actual bytes per line on the image. (Arkedo Pixel for example) // In such case we strip the bit depth to be lower. if ((bytes_per_line < stream->out_param.outputWidthByte) && stream->out_param.outputBitDepth != 8) { // Check if the packing is really 1 byte per 1 pixel if (stream->packing != CELL_PNGDEC_1BYTE_PER_1PIXEL) { throw EXCEPTION("Unexpected packing value! (%d)", stream->packing); } // Scale 16 bit depth down to 8 bit depth. PS3 uses png_set_strip_16, since png_set_scale_16 wasn't available back then. png_set_strip_16(stream->png_ptr); recalculate_bytes_per_row = true; } // Check if the outputWidthByte is smaller than the intended output length of a line. For example an image might be in RGB, but we need to output 4 components, so we need to perform alpha padding. else if (stream->out_param.outputWidthByte < (stream->out_param.outputWidth * stream->out_param.outputComponents)) { // If fixed alpha is not specified in such a case, the default value for the alpha is 0xFF (255) if (!stream->fixed_alpha) { stream->fixed_alpha_colour = 0xFF; } // We need to fill alpha (before or after, depending on the output colour format) using the fixed alpha value passed by the game. png_set_add_alpha(stream->png_ptr, stream->fixed_alpha_colour, stream->out_param.outputColorSpace == CELL_PNGDEC_RGBA ? PNG_FILLER_AFTER : PNG_FILLER_BEFORE); recalculate_bytes_per_row = true; } // We decode as RGBA, so we need to swap the alpha else if (stream->out_param.outputColorSpace == CELL_PNGDEC_ARGB) { // Swap the alpha channel for the ARGB output format, if the padding isn't needed png_set_swap_alpha(stream->png_ptr); } // Sometimes games pass in a RBG/RGBA image and want it as grayscale else if ((stream->out_param.outputColorSpace == CELL_PNGDEC_GRAYSCALE_ALPHA || stream->out_param.outputColorSpace == CELL_PNGDEC_GRAYSCALE) && (stream->info.colorSpace == CELL_PNGDEC_RGB || stream->info.colorSpace == CELL_PNGDEC_RGBA)) { // Tell libpng to convert it to grayscale png_set_rgb_to_gray(stream->png_ptr, PNG_ERROR_ACTION_NONE, PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); recalculate_bytes_per_row = true; } if (recalculate_bytes_per_row) { // Update the info structure png_read_update_info(stream->png_ptr, stream->info_ptr); // Recalculate the bytes per row stream->out_param.outputWidthByte = png_get_rowbytes(stream->png_ptr, stream->info_ptr); } // Calculate the image size u32 image_size = stream->out_param.outputWidthByte * stream->out_param.outputHeight; // Buffer for storing the image std::vector<u8> png(image_size); // Make an unique pointer for the row pointers std::vector<u8*> row_pointers(stream->out_param.outputHeight); // Allocate memory for rows for (u32 y = 0; y < stream->out_param.outputHeight; y++) { row_pointers[y] = &png[y * stream->out_param.outputWidthByte]; } // Decode the image png_read_image(stream->png_ptr, row_pointers.data()); // Check if the image needs to be flipped const bool flip = stream->out_param.outputMode == CELL_PNGDEC_BOTTOM_TO_TOP; // Copy the result to the output buffer switch (stream->out_param.outputColorSpace) { case CELL_PNGDEC_RGB: case CELL_PNGDEC_RGBA: case CELL_PNGDEC_ARGB: case CELL_PNGDEC_GRAYSCALE_ALPHA: { // Check if we need to flip the image or need to leave empty bytes at the end of a line if ((bytes_per_line > stream->out_param.outputWidthByte) || flip) { // Get how many bytes per line we need to output - bytesPerLine is total amount of bytes per line, rest is unused and the game can do as it pleases. const u32 line_size = std::min(bytes_per_line, stream->out_param.outputWidth * 4); // If the game wants more bytes per line to be output, than the image has, then we simply copy what we have for each line, // and continue on the next line, thus leaving empty bytes at the end of the line. for (u32 i = 0; i < stream->out_param.outputHeight; i++) { const u32 dst = i * bytes_per_line; const u32 src = stream->out_param.outputWidth * 4 * (flip ? stream->out_param.outputHeight - i - 1 : i); memcpy(&data[dst], &png[src], line_size); } } else { // We can simply copy the output to the data pointer specified by the game, since we already do alpha channel transformations in libpng, if needed memcpy(data.get_ptr(), png.data(), image_size); } break; } default: throw EXCEPTION("Unsupported color space (%d)", stream->out_param.outputColorSpace); } // Get the number of iTXt, tEXt and zTXt chunks s32 text_chunks = 0; png_get_text(stream->png_ptr, stream->info_ptr, nullptr, &text_chunks); // Set the chunk information and the previously obtained number of text chunks data_out_info->numText = (u32)text_chunks; data_out_info->chunkInformation = pngDecGetChunkInformation(stream, true); data_out_info->numUnknownChunk = 0; // TODO: Get this somehow. Does anything even use or need this? // Indicate that the decoding succeeded data_out_info->status = CELL_PNGDEC_DEC_STATUS_FINISH; return CELL_OK; }
void Tileset::create_tile(const std::string& filename, ZipReader *zip) throw (Exception) { try { PNG png(filename, zip); const int& png_width = png.get_width(); const int& png_height = png.get_height(); int tileno = 0; int tiley = 0; int tilex = 0; char kvb[128]; while (true) { /* get tile properties */ sprintf(kvb, "frames%d", tileno); int frames = atoi(get_value(kvb).c_str()); if (!frames) frames = 1; sprintf(kvb, "tiletype%d", tileno); int tile_type_val = atoi(get_value(kvb).c_str()); Tile::TileType tile_type = static_cast<Tile::TileType>(tile_type_val); sprintf(kvb, "background%d", tileno); bool background = true; if (get_value(kvb).length()) { background = (atoi(get_value(kvb).c_str()) == 0 ? false : true); } sprintf(kvb, "animation_speed%d", tileno); int animation_speed = atoi(get_value(kvb).c_str()); if (!animation_speed) { animation_speed = 45; } sprintf(kvb, "friction%d", tileno); double friction = atof(get_value(kvb).c_str()); if (friction > -Epsilon && friction < Epsilon) { friction = 0.05f; } sprintf(kvb, "light_blocking%d", tileno); bool light_blocking = false; if (get_value(kvb).length()) { light_blocking = (atoi(get_value(kvb).c_str()) != 0 ? true : false); } /* create all pictures consecutively for this tile */ TileGraphic *tg = subsystem.create_tilegraphic(tile_width, tile_height); while (frames && tiley < png_height) { /* store current picture in the graphics layer */ tg->punch_out_tile(png, tilex, tiley, false); /* advance to next tile */ frames--; tilex += tile_width; if (tilex >= png_width) { tilex = 0; tiley += tile_height; } } /* create tile with its pictures */ Tile *tile = new Tile(tg, background, tile_type, animation_speed, false, friction); tile->set_light_blocking(light_blocking); tiles.push_back(tile); sz = static_cast<int>(tiles.size()); /* test if all pics in tileset are grabbed */ if (tiley >= png_height) { break; } /* increment tileno */ tileno++; } } catch (const Exception&) { cleanup(); throw; } }