static gint algo_stitch_handle( ImageInfo *pin_image , ImageInfo *pout_image , gint nums) { if (nums > 4) nums = 4; gint dstW = pout_image[0].width; gint dstH = pout_image[0].height;//dongliang:结构体ImageInfo的定义在哪里,看一下里面都有些什么东西 gint dstL = pout_image[0].linesize;//dongliang:这里的linesize是个什么含义? guchar *dstY = pout_image[0].buf; guchar *dstU = dstY + dstL*dstH;//dongliang:为什么这里是dstL*dstH,而下面的V分量是dstL*dstH/4? guchar *dstV = dstU + dstL*dstH/4; g_print("dstL:%d. dstW:%d. dstH:%d.\n", dstL, dstW, dstH); memset(dstY, 0, dstL*dstH);//dongliang:初始状态申请dstL*dstH多的无符号字符,填充为空 memset(dstU, 128, dstL*dstH/4); memset(dstV, 128, dstL*dstH/4);//dongliang:为什么这里和上面都是dstL*dstH/4? gint t; gint x, y, xx, yy; //image coordinates for (t=0; t<nums; t++) { gint srcW = pin_image[t].width; gint srcH = pin_image[t].height; gint srcL = pin_image[t].linesize; guchar *srcY = pin_image[t].buf; guchar *srcU = srcY + srcL*srcH; guchar *srcV = srcU + srcL*srcH/4; g_print("src:t%d. srcL:%d. srcW:%d. srcH:%d.\n", t, srcL, srcW, srcH); for (y=0; y<dstH; y++) { for (x=0; x<dstW; x++) { double xin, yin, xout, yout; xin = x; yin = y; imageTransform(xin, yin, &xout, &yout, t); xx = (int)(xout+0.5); yy = (int)(yout+0.5); if (yy >= 0 && yy < srcH && xx >= 0 && xx < srcW) { dstY[y*dstL+x] = srcY[yy*srcL+xx]; if (x%2==0 && y%2==0) // do u & v { dstU[y/2*dstL/2+x/2] = srcU[yy/2*srcL/2+xx/2]; dstV[y/2*dstL/2+x/2] = srcV[yy/2*srcL/2+xx/2]; } } } } } return FILTER_SWAP; }
bool TextureSource::generateImage(std::string part_of_name, video::IImage *& baseimg) { video::IVideoDriver* driver = m_device->getVideoDriver(); assert(driver); // Stuff starting with [ are special commands if(part_of_name.size() == 0 || part_of_name[0] != '[') { video::IImage *image = m_sourcecache.getOrLoad(part_of_name, m_device); if(image == NULL) { if(part_of_name != ""){ errorstream<<"generateImage(): Could not load image \"" <<part_of_name<<"\""<<" while building texture"<<std::endl; errorstream<<"generateImage(): Creating a dummy" <<" image for \""<<part_of_name<<"\""<<std::endl; } // Just create a dummy image //core::dimension2d<u32> dim(2,2); core::dimension2d<u32> dim(1,1); image = driver->createImage(video::ECF_A8R8G8B8, dim); assert(image); /*image->setPixel(0,0, video::SColor(255,255,0,0)); image->setPixel(1,0, video::SColor(255,0,255,0)); image->setPixel(0,1, video::SColor(255,0,0,255)); image->setPixel(1,1, video::SColor(255,255,0,255));*/ image->setPixel(0,0, video::SColor(255,myrand()%256, myrand()%256,myrand()%256)); /*image->setPixel(1,0, video::SColor(255,myrand()%256, myrand()%256,myrand()%256)); image->setPixel(0,1, video::SColor(255,myrand()%256, myrand()%256,myrand()%256)); image->setPixel(1,1, video::SColor(255,myrand()%256, myrand()%256,myrand()%256));*/ } // If base image is NULL, load as base. if(baseimg == NULL) { //infostream<<"Setting "<<part_of_name<<" as base"<<std::endl; /* Copy it this way to get an alpha channel. Otherwise images with alpha cannot be blitted on images that don't have alpha in the original file. */ core::dimension2d<u32> dim = image->getDimension(); baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); image->copyTo(baseimg); } // Else blit on base. else { //infostream<<"Blitting "<<part_of_name<<" on base"<<std::endl; // Size of the copied area core::dimension2d<u32> dim = image->getDimension(); //core::dimension2d<u32> dim(16,16); // Position to copy the blitted to in the base image core::position2d<s32> pos_to(0,0); // Position to copy the blitted from in the blitted image core::position2d<s32> pos_from(0,0); // Blit /*image->copyToWithAlpha(baseimg, pos_to, core::rect<s32>(pos_from, dim), video::SColor(255,255,255,255), NULL);*/ blit_with_alpha(image, baseimg, pos_from, pos_to, dim); } //cleanup image->drop(); } else { // A special texture modification /*infostream<<"generateImage(): generating special " <<"modification \""<<part_of_name<<"\"" <<std::endl;*/ /* [crack:N:P [cracko:N:P Adds a cracking texture N = animation frame count, P = crack progression */ if(part_of_name.substr(0,6) == "[crack") { if(baseimg == NULL) { errorstream<<"generateImage(): baseimg==NULL " <<"for part_of_name=\""<<part_of_name <<"\", cancelling."<<std::endl; return false; } // Crack image number and overlay option bool use_overlay = (part_of_name[6] == 'o'); Strfnd sf(part_of_name); sf.next(":"); s32 frame_count = stoi(sf.next(":")); s32 progression = stoi(sf.next(":")); /* Load crack image. It is an image with a number of cracking stages horizontally tiled. */ video::IImage *img_crack = m_sourcecache.getOrLoad( "crack_anylength.png", m_device); if(img_crack && progression >= 0) { draw_crack(img_crack, baseimg, use_overlay, frame_count, progression, driver); img_crack->drop(); } } /* [combine:WxH:X,Y=filename:X,Y=filename2 Creates a bigger texture from an amount of smaller ones */ else if(part_of_name.substr(0,8) == "[combine") { Strfnd sf(part_of_name); sf.next(":"); u32 w0 = stoi(sf.next("x")); u32 h0 = stoi(sf.next(":")); infostream<<"combined w="<<w0<<" h="<<h0<<std::endl; core::dimension2d<u32> dim(w0,h0); if(baseimg == NULL) { baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); baseimg->fill(video::SColor(0,0,0,0)); } while(sf.atend() == false) { u32 x = stoi(sf.next(",")); u32 y = stoi(sf.next("=")); std::string filename = sf.next(":"); infostream<<"Adding \""<<filename <<"\" to combined ("<<x<<","<<y<<")" <<std::endl; video::IImage *img = m_sourcecache.getOrLoad(filename, m_device); if(img) { core::dimension2d<u32> dim = img->getDimension(); infostream<<"Size "<<dim.Width <<"x"<<dim.Height<<std::endl; core::position2d<s32> pos_base(x, y); video::IImage *img2 = driver->createImage(video::ECF_A8R8G8B8, dim); img->copyTo(img2); img->drop(); /*img2->copyToWithAlpha(baseimg, pos_base, core::rect<s32>(v2s32(0,0), dim), video::SColor(255,255,255,255), NULL);*/ blit_with_alpha(img2, baseimg, v2s32(0,0), pos_base, dim); img2->drop(); } else { infostream<<"img==NULL"<<std::endl; } } } /* "[brighten" */ else if(part_of_name.substr(0,9) == "[brighten") { if(baseimg == NULL) { errorstream<<"generateImage(): baseimg==NULL " <<"for part_of_name=\""<<part_of_name <<"\", cancelling."<<std::endl; return false; } brighten(baseimg); } /* "[noalpha" Make image completely opaque. Used for the leaves texture when in old leaves mode, so that the transparent parts don't look completely black when simple alpha channel is used for rendering. */ else if(part_of_name.substr(0,8) == "[noalpha") { if(baseimg == NULL) { errorstream<<"generateImage(): baseimg==NULL " <<"for part_of_name=\""<<part_of_name <<"\", cancelling."<<std::endl; return false; } core::dimension2d<u32> dim = baseimg->getDimension(); // Set alpha to full for(u32 y=0; y<dim.Height; y++) for(u32 x=0; x<dim.Width; x++) { video::SColor c = baseimg->getPixel(x,y); c.setAlpha(255); baseimg->setPixel(x,y,c); } } /* "[makealpha:R,G,B" Convert one color to transparent. */ else if(part_of_name.substr(0,11) == "[makealpha:") { if(baseimg == NULL) { errorstream<<"generateImage(): baseimg==NULL " <<"for part_of_name=\""<<part_of_name <<"\", cancelling."<<std::endl; return false; } Strfnd sf(part_of_name.substr(11)); u32 r1 = stoi(sf.next(",")); u32 g1 = stoi(sf.next(",")); u32 b1 = stoi(sf.next("")); std::string filename = sf.next(""); core::dimension2d<u32> dim = baseimg->getDimension(); /*video::IImage *oldbaseimg = baseimg; baseimg = driver->createImage(video::ECF_A8R8G8B8, dim); oldbaseimg->copyTo(baseimg); oldbaseimg->drop();*/ // Set alpha to full for(u32 y=0; y<dim.Height; y++) for(u32 x=0; x<dim.Width; x++) { video::SColor c = baseimg->getPixel(x,y); u32 r = c.getRed(); u32 g = c.getGreen(); u32 b = c.getBlue(); if(!(r == r1 && g == g1 && b == b1)) continue; c.setAlpha(0); baseimg->setPixel(x,y,c); } } /* "[transformN" Rotates and/or flips the image. N can be a number (between 0 and 7) or a transform name. Rotations are counter-clockwise. 0 I identity 1 R90 rotate by 90 degrees 2 R180 rotate by 180 degrees 3 R270 rotate by 270 degrees 4 FX flip X 5 FXR90 flip X then rotate by 90 degrees 6 FY flip Y 7 FYR90 flip Y then rotate by 90 degrees Note: Transform names can be concatenated to produce their product (applies the first then the second). The resulting transform will be equivalent to one of the eight existing ones, though (see: dihedral group). */ else if(part_of_name.substr(0,10) == "[transform") { if(baseimg == NULL) { errorstream<<"generateImage(): baseimg==NULL " <<"for part_of_name=\""<<part_of_name <<"\", cancelling."<<std::endl; return false; } u32 transform = parseImageTransform(part_of_name.substr(10)); core::dimension2d<u32> dim = imageTransformDimension( transform, baseimg->getDimension()); video::IImage *image = driver->createImage( baseimg->getColorFormat(), dim); assert(image); imageTransform(transform, baseimg, image); baseimg->drop(); baseimg = image; } /* [inventorycube{topimage{leftimage{rightimage In every subimage, replace ^ with &. Create an "inventory cube". NOTE: This should be used only on its own. Example (a grass block (not actually used in game): "[inventorycube{grass.png{mud.png&grass_side.png{mud.png&grass_side.png" */ else if(part_of_name.substr(0,14) == "[inventorycube") { if(baseimg != NULL) { errorstream<<"generateImage(): baseimg!=NULL " <<"for part_of_name=\""<<part_of_name <<"\", cancelling."<<std::endl; return false; } str_replace_char(part_of_name, '&', '^'); Strfnd sf(part_of_name); sf.next("{"); std::string imagename_top = sf.next("{"); std::string imagename_left = sf.next("{"); std::string imagename_right = sf.next("{"); // Generate images for the faces of the cube video::IImage *img_top = generateImageFromScratch(imagename_top); video::IImage *img_left = generateImageFromScratch(imagename_left); video::IImage *img_right = generateImageFromScratch(imagename_right); assert(img_top && img_left && img_right); // Create textures from images video::ITexture *texture_top = driver->addTexture( (imagename_top + "__temp__").c_str(), img_top); video::ITexture *texture_left = driver->addTexture( (imagename_left + "__temp__").c_str(), img_left); video::ITexture *texture_right = driver->addTexture( (imagename_right + "__temp__").c_str(), img_right); assert(texture_top && texture_left && texture_right); // Drop images img_top->drop(); img_left->drop(); img_right->drop(); /* Draw a cube mesh into a render target texture */ scene::IMesh* cube = createCubeMesh(v3f(1, 1, 1)); setMeshColor(cube, video::SColor(255, 255, 255, 255)); cube->getMeshBuffer(0)->getMaterial().setTexture(0, texture_top); cube->getMeshBuffer(1)->getMaterial().setTexture(0, texture_top); cube->getMeshBuffer(2)->getMaterial().setTexture(0, texture_right); cube->getMeshBuffer(3)->getMaterial().setTexture(0, texture_right); cube->getMeshBuffer(4)->getMaterial().setTexture(0, texture_left); cube->getMeshBuffer(5)->getMaterial().setTexture(0, texture_left); TextureFromMeshParams params; params.mesh = cube; params.dim.set(64, 64); params.rtt_texture_name = part_of_name + "_RTT"; // We will delete the rtt texture ourselves params.delete_texture_on_shutdown = false; params.camera_position.set(0, 1.0, -1.5); params.camera_position.rotateXZBy(45); params.camera_lookat.set(0, 0, 0); // Set orthogonal projection params.camera_projection_matrix.buildProjectionMatrixOrthoLH( 1.65, 1.65, 0, 100); params.ambient_light.set(1.0, 0.2, 0.2, 0.2); params.light_position.set(10, 100, -50); params.light_color.set(1.0, 0.5, 0.5, 0.5); params.light_radius = 1000; video::ITexture *rtt = generateTextureFromMesh(params); // Drop mesh cube->drop(); // Free textures of images driver->removeTexture(texture_top); driver->removeTexture(texture_left); driver->removeTexture(texture_right); if(rtt == NULL) { baseimg = generateImageFromScratch(imagename_top); return true; } // Create image of render target video::IImage *image = driver->createImage(rtt, v2s32(0,0), params.dim); assert(image); // Cleanup texture driver->removeTexture(rtt); baseimg = driver->createImage(video::ECF_A8R8G8B8, params.dim); if(image) { image->copyTo(baseimg); image->drop(); } } /* [lowpart:percent:filename Adds the lower part of a texture */ else if(part_of_name.substr(0,9) == "[lowpart:") { Strfnd sf(part_of_name); sf.next(":"); u32 percent = stoi(sf.next(":")); std::string filename = sf.next(":"); //infostream<<"power part "<<percent<<"%% of "<<filename<<std::endl; if(baseimg == NULL) baseimg = driver->createImage(video::ECF_A8R8G8B8, v2u32(16,16)); video::IImage *img = m_sourcecache.getOrLoad(filename, m_device); if(img) { core::dimension2d<u32> dim = img->getDimension(); core::position2d<s32> pos_base(0, 0); video::IImage *img2 = driver->createImage(video::ECF_A8R8G8B8, dim); img->copyTo(img2); img->drop(); core::position2d<s32> clippos(0, 0); clippos.Y = dim.Height * (100-percent) / 100; core::dimension2d<u32> clipdim = dim; clipdim.Height = clipdim.Height * percent / 100 + 1; core::rect<s32> cliprect(clippos, clipdim); img2->copyToWithAlpha(baseimg, pos_base, core::rect<s32>(v2s32(0,0), dim), video::SColor(255,255,255,255), &cliprect); img2->drop(); } } /* [verticalframe:N:I Crops a frame of a vertical animation. N = frame count, I = frame index */ else if(part_of_name.substr(0,15) == "[verticalframe:") { Strfnd sf(part_of_name); sf.next(":"); u32 frame_count = stoi(sf.next(":")); u32 frame_index = stoi(sf.next(":")); if(baseimg == NULL){ errorstream<<"generateImage(): baseimg!=NULL " <<"for part_of_name=\""<<part_of_name <<"\", cancelling."<<std::endl; return false; } v2u32 frame_size = baseimg->getDimension(); if (frame_count) frame_size.Y /= frame_count; video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, frame_size); if(!img){ errorstream<<"generateImage(): Could not create image " <<"for part_of_name=\""<<part_of_name <<"\", cancelling."<<std::endl; return false; } // Fill target image with transparency img->fill(video::SColor(0,0,0,0)); core::dimension2d<u32> dim = frame_size; core::position2d<s32> pos_dst(0, 0); core::position2d<s32> pos_src(0, frame_index * frame_size.Y); baseimg->copyToWithAlpha(img, pos_dst, core::rect<s32>(pos_src, dim), video::SColor(255,255,255,255), NULL); // Replace baseimg baseimg->drop(); baseimg = img; } else { errorstream<<"generateImage(): Invalid " " modification: \""<<part_of_name<<"\""<<std::endl; } } return true; }
void saveFilePNG(std::vector<unsigned char> &image, const std::string& str) { imageTransform(image,str); }