示例#1
0
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 )
} 
示例#2
0
/**
 * 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;
}
示例#3
0
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;
}
示例#4
0
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;
}
示例#5
0
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);
}
示例#6
0
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;
}
示例#7
0
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();
}
示例#8
0
文件: pngtest.cpp 项目: crust/pngpp
// 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;
    }
}
示例#10
0
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;
}
示例#11
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());
    }

}
示例#12
0
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;
}
示例#13
0
        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 } };
        }
示例#14
0
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);
		}
	}
}
示例#15
0
        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;
}
示例#17
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 )
	}
}
示例#18
0
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;
}
示例#19
0
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;
    }
}
示例#20
0
_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";
}
示例#21
0
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 (...) {

		}
	}
}
示例#22
0
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;
}
示例#23
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;
}
示例#24
0
文件: png.cpp 项目: nical/vodk
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);
}
示例#26
0
/**
 * 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;
}
示例#27
0
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;
}
示例#28
0
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;
    }
}