当前位置: 首页>>代码示例>>C++>>正文


C++ ImageOutput::write_image方法代码示例

本文整理汇总了C++中ImageOutput::write_image方法的典型用法代码示例。如果您正苦于以下问题:C++ ImageOutput::write_image方法的具体用法?C++ ImageOutput::write_image怎么用?C++ ImageOutput::write_image使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在ImageOutput的用法示例。


在下文中一共展示了ImageOutput::write_image方法的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: writeImage

/**
 * @brief Write imgage.
 * @details Write compostied image to the file system.
 */
void writeImage() {

  // Transfer to something OpenImageIO understands
     oiioPixels.resize(newWidth*newHeight*4*sizeof(float));

     for (int row = 0; row < newHeight; row++)
         for (int col = 0; col < newWidth; col++){
          oiioPixels[(row*newWidth+col)*4 + 0] = warppedPixels[row][col].r;
          oiioPixels[(row*newWidth+col)*4 + 1] = warppedPixels[row][col].g;
          oiioPixels[(row*newWidth+col)*4 + 2] = warppedPixels[row][col].b;
          oiioPixels[(row*newWidth+col)*4 + 3] = warppedPixels[row][col].a;
        }

  // Create output image
    ImageOutput *out = ImageOutput::create(outImage);

    // Error handeling
    if (!out) {
        printf("Error writing image: %s\n", geterror().c_str());
        exit(EXIT_FAILURE);
    }

    // Create output image spec
    ImageSpec spec (newWidth, newHeight, 4, TypeDesc::FLOAT);

    // Open output image file
    out->open(outImage, spec);

    // Write output image to disk and close
    out->write_image(TypeDesc::FLOAT, &oiioPixels[0]);
    out->close();
    delete out;
}
开发者ID:joshua-hull,项目名称:School-Work,代码行数:37,代码来源:warper.cpp

示例2: Simulate

 void Ibl::Simulate(std::string const& filename)
 {
     auto width = 2000U;
     auto height = 1000U;
     
     
     std::vector<float> data(width * height);
     std::fill(data.begin(), data.end(), 0.f);
     
     for (int i = 0; i < 100000; ++i)
     {
         auto xy = SampleCoord(RadeonRays::float2(RadeonRays::rand_float(), RadeonRays::rand_float()));
         data[xy.y * width + xy.x] += 1.f;
     }
     
     using namespace OpenImageIO;
     
     ImageOutput* out = ImageOutput::create(filename);
     
     if (!out)
     {
         throw std::runtime_error("Can't create image file on disk");
     }
     
     ImageSpec spec(width, height, 1, TypeDesc::UINT8);
     
     out->open(filename, spec);
     out->write_image(TypeDesc::FLOAT, &data[0]);
     out->close();
     
     delete out;
 }
开发者ID:GPUOpen-LibrariesAndSDKs,项目名称:RadeonRays_SDK,代码行数:32,代码来源:Ibl.cpp

示例3: writeOIIOImage

void lux::writeOIIOImage( const char* fname, Image& img, const map<string,string>& labels, float displayBrightness, float displayGamma )
{
   float* imagedata = new float[ img.Width()* img.Height() * 3 ];

   // fill image with the contents of img

   long index = 0;
   for( int j=0;j<img.Height();j++ )
   {
      for( int i=0;i<img.Width();i++ )
      {
         vector<float> pix = img.pixel(i,img.Height() - j - 1);
	 for( size_t c=0;c<3;c++ )
         {
            pix[c] = imagePlaneValue( pix[c], displayGamma, displayBrightness );
	    imagedata[index++] = pix[c];
         }
      }
   }

   ImageOutput *out = ImageOutput::create (fname); 
   if( !out )
   {
      cout << "Not able to write an image to file " << fname << endl;
   }
   else
   {
      ImageSpec spec (img.Width(), img.Height(), 3, TypeDesc::FLOAT); 
      spec.attribute("user", "imageTools");
      spec.attribute("writer", "OIIOFiles" );
      if( labels.size() > 0 )
      {
         map<string,string>::const_iterator lab = labels.begin();
	 while( lab != labels.end() )
	 {
	    const string& name = lab->first;
	    const string& value = lab->second;
	    spec.attribute( name, value );
	    lab++;
	 }
      }
      out->open (fname, spec);
      out->write_image (TypeDesc::FLOAT, imagedata); 
      out->close (); 
	cout <<endl<<endl<< "File " << fname << " written to file"<< endl;
      delete out;
   }
   delete[] imagedata;
}
开发者ID:zwelchWI,项目名称:vol_ren,代码行数:49,代码来源:OIIOFiles.C

示例4: SaveFrameBuffer

void SaveFrameBuffer(std::string const& name, float3 const* data)
{
	OIIO_NAMESPACE_USING;

	std::vector<float3> tempbuf(g_window_width * g_window_height);
	tempbuf.assign(data, data + g_window_width*g_window_height);

	ImageOutput* out = ImageOutput::create(name);

	if (!out)
	{
		throw std::runtime_error("Can't create image file on disk");
	}

	ImageSpec spec(g_window_width, g_window_height, 3, TypeDesc::FLOAT);

	out->open(name, spec);
	out->write_image(TypeDesc::FLOAT, &tempbuf[0], sizeof(float3));
	out->close();
}
开发者ID:NoSuchProcess,项目名称:FireRays_SDK,代码行数:20,代码来源:main.cpp

示例5: DumpPdf

 void Ibl::DumpPdf(std::string const& filename)
 {
     auto width = 2000U;
     auto height = 1000U;
     
     
     std::vector<float> data(width * height);
     
     for (auto x = 0U; x < width; ++x)
         for (auto y = 0U; y < height; ++y)
         {
             data[y * width + x] = GetPdf(RadeonRays::float2((float)x / m_width, (float)y / m_height));
         }
     
     auto max = std::max_element(data.cbegin(), data.cend());
     
     std::for_each(data.begin(), data.end(), [=](float& v)
                   {
                       v /= *max;
                   });
     
     using namespace OpenImageIO;
     
     ImageOutput* out = ImageOutput::create(filename);
     
     if (!out)
     {
         throw std::runtime_error("Can't create image file on disk");
     }
     
     ImageSpec spec(width, height, 1, TypeDesc::UINT8);
     
     out->open(filename, spec);
     out->write_image(TypeDesc::FLOAT, &data[0]);
     out->close();
     
     delete out;
 }
开发者ID:GPUOpen-LibrariesAndSDKs,项目名称:RadeonRays_SDK,代码行数:38,代码来源:Ibl.cpp

示例6: main

int main (int argc, const char *argv[]) {
    Timer timer;

    // Create a new shading system.  We pass it the RendererServices
    // object that services callbacks from the shading system, NULL for
    // the TextureSystem (which will create a default OIIO one), and
    // an error handler.
    shadingsys = new ShadingSystem (&rend, NULL, &errhandler);

    // Register the layout of all closures known to this renderer
    // Any closure used by the shader which is not registered, or
    // registered with a different number of arguments will lead
    // to a runtime error.
    register_closures(shadingsys);

    // Remember that each shader parameter may optionally have a
    // metadata hint [[int lockgeom=...]], where 0 indicates that the
    // parameter may be overridden by the geometry itself, for example
    // with data interpolated from the mesh vertices, and a value of 1
    // means that it is "locked" with respect to the geometry (i.e. it
    // will not be overridden with interpolated or
    // per-geometric-primitive data).
    // 
    // In order to most fully optimize shader, we typically want any
    // shader parameter not explicitly specified to default to being
    // locked (i.e. no per-geometry override):
    shadingsys->attribute("lockgeom", 1);

    // Read command line arguments
    getargs (argc, argv);

    // Setup common attributes
    shadingsys->attribute ("debug", debug2 ? 2 : (debug ? 1 : 0));
    shadingsys->attribute ("compile_report", debug|debug2);
    const char *opt_env = getenv ("TESTSHADE_OPT");  // overrides opt
    if (opt_env)
        shadingsys->attribute ("optimize", atoi(opt_env));
    else if (O0 || O1 || O2)
        shadingsys->attribute ("optimize", O2 ? 2 : (O1 ? 1 : 0));
    shadingsys->attribute ("debugnan", debugnan);

    // Loads a scene, creating camera, geometry and assigning shaders
    parse_scene();

    // validate options
    if (aa < 1) aa = 1;
    if (num_threads < 1)
        num_threads = boost::thread::hardware_concurrency();

    // prepare background importance table (if requested)
    if (backgroundResolution > 0 && backgroundShaderID >= 0) {
        // get a context so we can make several background shader calls
        OSL::PerThreadInfo *thread_info = shadingsys->create_thread_info();
        ShadingContext *ctx = shadingsys->get_context (thread_info);

        // build importance table to optimize background sampling
        background.prepare(backgroundResolution, eval_background, ctx);

        // release context
        shadingsys->release_context (ctx);
        shadingsys->destroy_thread_info(thread_info);
    } else {
        // we aren't directly evaluating the background
        backgroundResolution = 0;
    }

    double setuptime = timer.lap ();

    std::vector<Color3> pixels(xres * yres, Color3(0,0,0));

    // Create shared counter to iterate over one scanline at a time
    Counter scanline_counter(errhandler, yres, "Rendering");
    // launch a scanline worker for each thread
    boost::thread_group workers;
    for (int i = 0; i < num_threads; i++)
        workers.add_thread(new boost::thread(scanline_worker, boost::ref(scanline_counter), boost::ref(pixels)));
    workers.join_all();

    // Write image to disk
    ImageOutput* out = ImageOutput::create(imagefile);
    ImageSpec spec(xres, yres, 3, TypeDesc::HALF);
    if (out && out->open(imagefile, spec)) {
        out->write_image(TypeDesc::TypeFloat, &pixels[0]);
    } else {
        errhandler.error("Unable to write output image");
    }
    delete out;

    // Print some debugging info
    if (debug || stats) {
        double runtime = timer.lap();
        std::cout << "\n";
        std::cout << "Setup: " << OIIO::Strutil::timeintervalformat (setuptime,2) << "\n";
        std::cout << "Run  : " << OIIO::Strutil::timeintervalformat (runtime,2) << "\n";
        std::cout << "\n";
        std::cout << shadingsys->getstats (5) << "\n";
        OIIO::TextureSystem *texturesys = shadingsys->texturesys();
        if (texturesys)
            std::cout << texturesys->getstats (5) << "\n";
        std::cout << ustring::getstats() << "\n";
//.........这里部分代码省略.........
开发者ID:davidlee80,项目名称:OpenShadingLanguage,代码行数:101,代码来源:testrender.cpp

示例7: smt


//.........这里部分代码省略.........
				ImageBufAlgo::CompareResults result;
				deque< TileBufListEntry * >::iterator it;

				for(it = tileList.begin(); it != tileList.end(); it++ ) {
					TileBufListEntry *listEntry2 = *it;
					ImageBufAlgo::compare_yee( *tileBuf, listEntry2->image,
							result, 1.0f, 1.0f );
					if(result.nfail == 0) {
						match = true;
						i = listEntry2->tileNum;
						break;
					}
				}
				if( !match ) {
					tileList.push_back(listEntry);
					if((int)tileList.size() > 32) tileList.pop_front();
				}*/
			}

			// write tile to file.
			if( !match ) {
				unsigned char *std = (unsigned char *)tileBuf->localpixels();
				// process into dds
				NVTTOutputHandler *nvttHandler = new NVTTOutputHandler(tileSize);

				nvtt::InputOptions inputOptions;
				inputOptions.setTextureLayout( nvtt::TextureType_2D, tileRes, tileRes );
				inputOptions.setMipmapData( std, tileRes, tileRes );

				nvtt::CompressionOptions compressionOptions;
				compressionOptions.setFormat(nvtt::Format_DXT1a);

				nvtt::OutputOptions outputOptions;
				outputOptions.setOutputHeader(false);
				outputOptions.setOutputHandler( nvttHandler );

				nvtt::Compressor compressor;
				if( slow_dxt1 ) compressionOptions.setQuality(nvtt::Quality_Normal); 
				else           compressionOptions.setQuality(nvtt::Quality_Fastest); 
				compressor.process(inputOptions, compressionOptions, outputOptions);

				smt.write( nvttHandler->buffer, tileSize );
				delete nvttHandler;
				nTiles +=1;
			}
			delete tileBuf;
			// Write index to tilemap
			indexPixels[currentTile-1] = i;

    		gettimeofday(&t2, NULL);
			// compute and print the elapsed time in millisec
	    	elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;      // sec to ms
	    	elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;   // us to ms
			readings.push_back(elapsedTime);
			if(readings.size() > 1000)readings.pop_front();
			intervalTime += elapsedTime;
			if( verbose && intervalTime > 1 ) {
				for(unsigned int i = 0; i < readings.size(); ++i)
					averageTime+= readings[i];
				averageTime /= readings.size();
				intervalTime = 0;
			   	printf("\033[0G    %i of %i %%%0.1f complete | %%%0.1f savings | %0.1fs remaining.",
				currentTile, totalTiles,
				(float)currentTile / totalTiles * 100,
				(float)(1 - (float)nTiles / (float)currentTile) * 100,
			    averageTime * (totalTiles - currentTile) / 1000);
			}
		}
	}
	hashTable.clear();
	if( verbose ) cout << endl;
	smt.close();

	// retroactively fix up the tile count.
	smt.open(filename, ios::binary | ios::in | ios::out );
	smt.seekp( 20);
	smt.write( (char *)&nTiles, 4);
	smt.close();

	// Save tileindex
	ImageOutput *imageOutput;
	sprintf( filename, "%s_tilemap.exr", outPrefix.c_str() );
	
	imageOutput = ImageOutput::create(filename);
	if( !imageOutput ) {
		delete [] indexPixels;
		return true;
	}

	ImageSpec tilemapSpec( tcx, tcz, 1, TypeDesc::UINT);
	imageOutput->open( filename, tilemapSpec );
	imageOutput->write_image( TypeDesc::UINT, indexPixels );
	imageOutput->close();

	delete imageOutput;
	delete [] indexPixels;

	return false;

}
开发者ID:pajohns,项目名称:MapConv,代码行数:101,代码来源:smt.cpp

示例8: writeImage

// Function to write an image using OpenImageIO that reads and stores the pixel bein    g displayed on screen using OpenGL
void writeImage() {
 
  // Store the Output File Type in outfiletype, example .ppm or .jpg
  string outfiletype = outfilename.substr(outfilename.find("."));

  // Create ImageOutput instance using the outfilename & exit if error in creating
  ImageOutput *out = ImageOutput::create(outfilename);
  if (!out) {
    cerr << "Could not create an ImageOutput for " 
         << outfilename << "\nError: "
         << geterror()<<endl;
    exit(-1);
  }

  // Set outputchannels to 3 if outputfiletype is either ppm/pnm/pgm/pbm/hdr/rgbe else let it be equal to the number of channels of the input image (either 3 or 4)
  int outputchannels = (outfiletype==".ppm" || outfiletype==".pnm" || outfiletype==".pgm" || outfiletype==".pbm" || outfiletype==".hdr" || outfiletype==".rgbe" ? 3 : channels1 );

  // Allocate memory based on the number of channels
  unsigned char *oiio_pixels = new unsigned char[xresWarped*yresWarped*outputchannels];
  // Check if memory has been allocated successfully
  if (oiio_pixels==0) {
    // Memory not allocated successfully! Display message and Exit
    cout<<"Couldn't allocate memory. Exiting!"<<endl;
    exit(-1);
    delete out;
  }
 
  // If number of channels is 4 then read in RGBA format using GL_RGBA
  if(outputchannels==4) {
    for(int i=0, k=0; i<yresWarped && k<(xresWarped*yresWarped*outputchannels); i++) {
      for(int j=0; j<xresWarped; j++, k+=4) {
        oiio_pixels[k] = pixmapWarped[i][j].red;
        oiio_pixels[k+1] = pixmapWarped[i][j].green;
        oiio_pixels[k+2] = pixmapWarped[i][j].blue;
        oiio_pixels[k+3] = pixmapWarped[i][j].alpha;
      }
    }
  }
 
  // If number of channels is 3 then read in RGB format using GL_RGB
  else if(outputchannels==3) {
    for(int i=0, k=0; i<yresWarped && k<(xresWarped*yresWarped*outputchannels); i++) {
      for(int j=0; j<xresWarped; j++, k+=3) {
        oiio_pixels[k] = pixmapWarped[i][j].red;
        oiio_pixels[k+1] = pixmapWarped[i][j].green;
        oiio_pixels[k+2] = pixmapWarped[i][j].blue;
      }
    }
  }

  // Create ImageSpec for the output image with name outfile
  ImageSpec spec(xresWarped,yresWarped,outputchannels,TypeDesc::UINT8);
  if (! out->open (outfilename, spec)) {
    cerr << "Could not open " 
         << outfilename << "\nError: "
         << out->geterror()<< endl;
    delete out;
    delete [] oiio_pixels;
    exit(-1);
  }

  // This particular call to write flips the image for us
  int scanlinesize = xresWarped * outputchannels * sizeof(oiio_pixels[0]);
  if(! out->write_image (TypeDesc::UINT8, (unsigned char*)oiio_pixels+(yresWarped-1)*scanlinesize, AutoStride, -scanlinesize, AutoStride)) {
     cerr << "Could not write pixels to " 
          << outfilename << "\nError: "
          << out->geterror()<< endl;
     delete out;
     delete [] oiio_pixels;
     exit(-1);
   }

  // Close the output file
  if(! out->close ()) {
    std::cerr << "Error closing " 
              << outfilename << "\nError: " 
              << out->geterror() << endl;
    delete out;
    delete [] oiio_pixels;
    exit(-1);
  }
  delete out;
  delete [] oiio_pixels;
}
开发者ID:nitinmadhok,项目名称:panorama,代码行数:85,代码来源:panorama.cpp

示例9: ufilename


//.........这里部分代码省略.........
            ImageSpec outspec = inspec;
            bool nocopy = adjust_spec (in, out, inspec, outspec);
        
            if (miplevel > 0) {
                // Moving to next MIP level
                ImageOutput::OpenMode mode;
                if (out->supports ("mipmap"))
                    mode = ImageOutput::AppendMIPLevel;
                else if (out->supports ("multiimage") &&
                         out->supports ("appendsubimage")) {
                    mode = ImageOutput::AppendSubimage; // use if we must
                    if (! mip_to_subimage_warning
                        && strcmp(out->format_name(),"tiff")) {
                        std::cerr << "iconvert WARNING: " << out->format_name()
                                  << " does not support MIPmaps.\n";
                        std::cerr << "\tStoring the MIPmap levels in subimages.\n";
                    }
                    mip_to_subimage_warning = true;
                } else {
                    std::cerr << "iconvert WARNING: " << out->format_name()
                              << " does not support MIPmaps.\n";
                    std::cerr << "\tOnly the first level has been copied.\n";
                    break;  // on to the next subimage
                }
                ok = out->open (tempname.c_str(), outspec, mode);
            } else if (subimage > 0) {
                // Moving to next subimage
                ok = out->open (tempname.c_str(), outspec,
                                ImageOutput::AppendSubimage);
            } else {
                // First time opening
                if (subimagespecs.size())
                    ok = out->open (tempname.c_str(), int(subimagespecs.size()),
                                    &subimagespecs[0]);
                else
                    ok = out->open (tempname.c_str(), outspec, ImageOutput::Create);
            }
            if (! ok) {
                std::string err = out->geterror();
                std::cerr << "iconvert ERROR: " 
                          << (err.length() ? err : Strutil::format("Could not open \"%s\"", out_filename))
                          << "\n";
                ok = false;
                break;
            }

            if (! nocopy) {
                ok = out->copy_image (in);
                if (! ok)
                    std::cerr << "iconvert ERROR copying \"" << in_filename 
                              << "\" to \"" << out_filename << "\" :\n\t" 
                              << out->geterror() << "\n";
            } else {
                // Need to do it by hand for some reason.  Future expansion in which
                // only a subset of channels are copied, or some such.
                std::vector<char> pixels ((size_t)outspec.image_bytes(true));
                ok = in->read_image (outspec.format, &pixels[0]);
                if (! ok) {
                    std::cerr << "iconvert ERROR reading \"" << in_filename 
                              << "\" : " << in->geterror() << "\n";
                } else {
                    ok = out->write_image (outspec.format, &pixels[0]);
                    if (! ok)
                        std::cerr << "iconvert ERROR writing \"" << out_filename 
                                  << "\" : " << out->geterror() << "\n";
                }
            }
        
            ++miplevel;
        } while (ok && in->seek_subimage(subimage,miplevel,inspec));
    }

    out->close ();
    delete out;
    in->close ();
    delete in;

    // Figure out a time for the input file -- either one supplied by
    // the metadata, or the actual time stamp of the input file.
    std::time_t in_time;
    if (metadatatime.empty() ||
           ! DateTime_to_time_t (metadatatime.c_str(), in_time))
        in_time = Filesystem::last_write_time (in_filename);

    if (out_filename != tempname) {
        if (ok) {
            Filesystem::remove (out_filename);
            Filesystem::rename (tempname, out_filename);
        }
        else
            Filesystem::remove (tempname);
    }

    // If user requested, try to adjust the file's modification time to
    // the creation time indicated by the file's DateTime metadata.
    if (ok && adjust_time)
        Filesystem::last_write_time (out_filename, in_time);

    return ok;
}
开发者ID:Nazg-Gul,项目名称:oiio,代码行数:101,代码来源:iconvert.cpp

示例10: main


//.........这里部分代码省略.........
				"persistence value")
			("octaves,o", value<int>()->default_value(2),
				"number of octaves")
		;

		options_description hidden("Hidden options");
		hidden.add_options()
			("output-file", value<string>()->required(), "output file")
		;

		options_description all("Allowed options");
		all.add(desc).add(hidden);

		positional_options_description p;
		p.add("output-file", 1);

		variables_map vm;
		store(command_line_parser(argc, argv).options(all)
			.positional(p).run(), vm);

		if (vm.count("help"))
		{
			cout << "Usage: " << argv[0] << " [options] output-file" << endl;
			cout << desc << endl;
			return 0;
		}

		notify(vm);

		string outputfile = vm["output-file"].as<string>();
		ImageOutput* out = ImageOutput::create(outputfile);
		if (!out)
		{
			cerr << "Could not create an ImageOutput for "
				<< outputfile << ", error = "
				<< OpenImageIO::geterror() << endl;
			return 0;
		}

		const int xres = vm["xres"].as<int>();
		const int yres = vm["yres"].as<int>();
		const int channels = 3; // RGB
		ImageSpec outspec(xres, yres, channels, TypeDesc::UINT8);

		if (!out->open(outputfile, outspec))
		{
			cerr << "Could not open " << outputfile
				<< ", error = " << out->geterror() << endl;
			ImageOutput::destroy(out);
			return 0;
		}

		const int sample_size = vm["sample-size"].as<int>();
		const int seed = vm["seed"].as<int>();
		Perlin perlin(sample_size, seed);

		float persistence = vm["persistence"].as<float>();
		int octaves = vm["octaves"].as<int>();

		unsigned char pixels[xres * yres * channels];
		for (int y = 0; y < yres; y++)
		{
			for (int x = 0; x < xres; x++)
			{
				float frequency, amplitude;
				float total = 0.0f;

				for (int i = 1; i <= octaves; ++i)
				{
					frequency = pow(2.0f, i);
					amplitude = pow(persistence, i);

					total += (perlin.Noise2(frequency * x / sample_size,
						frequency * y / sample_size) + 1)/ 2.0f * amplitude;
				}
	
				total = min<float>(1.0f, max<float>(0.0f, total));
				unsigned int noise = (unsigned int) (total * 255);

				pixels[y * xres * channels + x * channels] = noise;
				pixels[y * xres * channels + x * channels + 1] = noise;
				pixels[y * xres * channels + x * channels + 2] = noise;
			}
		}

		if (!out->write_image(TypeDesc::UINT8, pixels))
		{
			cerr << "Could not write pixels to " << outputfile
				<< ", error = " << out->geterror() << endl;
			ImageOutput::destroy(out);
			return 0;
		}

		ImageOutput::destroy(out);
	}
	catch (exception& e)
	{
		cerr << e.what() << endl;
	}
}
开发者ID:SimonBoorer,项目名称:Perlin,代码行数:101,代码来源:main.cpp


注:本文中的ImageOutput::write_image方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。