void FlattenLayers::onExecute() { Sprite* sprite = this->sprite(); auto doc = static_cast<Doc*>(sprite->document()); // Create a temporary image. ImageRef image(Image::create(sprite->pixelFormat(), sprite->width(), sprite->height())); LayerImage* flatLayer; // The layer onto which everything will be flattened. color_t bgcolor; // The background color to use for flatLayer. flatLayer = sprite->backgroundLayer(); if (flatLayer && flatLayer->isVisible()) { // There exists a visible background layer, so we will flatten onto that. bgcolor = doc->bgColor(flatLayer); } else { // Create a new transparent layer to flatten everything onto. flatLayer = new LayerImage(sprite); ASSERT(flatLayer->isVisible()); executeAndAdd(new cmd::AddLayer(sprite->root(), flatLayer, nullptr)); executeAndAdd(new cmd::SetLayerName(flatLayer, "Flattened")); bgcolor = sprite->transparentColor(); } render::Render render; render.setBgType(render::BgType::NONE); // Copy all frames to the background. for (frame_t frame(0); frame<sprite->totalFrames(); ++frame) { // Clear the image and render this frame. clear_image(image.get(), bgcolor); render.renderSprite(image.get(), sprite, frame); // TODO Keep cel links when possible ImageRef cel_image; Cel* cel = flatLayer->cel(frame); if (cel) { if (cel->links()) executeAndAdd(new cmd::UnlinkCel(cel)); cel_image = cel->imageRef(); ASSERT(cel_image); executeAndAdd(new cmd::CopyRect(cel_image.get(), image.get(), gfx::Clip(0, 0, image->bounds()))); } else { cel_image.reset(Image::createCopy(image.get())); cel = new Cel(frame, cel_image); flatLayer->addCel(cel); } } // Delete old layers. LayerList layers = sprite->root()->layers(); for (Layer* layer : layers) if (layer != flatLayer) executeAndAdd(new cmd::RemoveLayer(layer)); }
void BackgroundFromLayer::onExecute() { Layer* layer = this->layer(); Sprite* sprite = layer->sprite(); auto doc = static_cast<Doc*>(sprite->document()); color_t bgcolor = doc->bgColor(); // Create a temporary image to draw each cel of the new Background // layer. ImageRef bg_image(Image::create(sprite->pixelFormat(), sprite->width(), sprite->height())); CelList cels; layer->getCels(cels); for (Cel* cel : cels) { Image* cel_image = cel->image(); ASSERT(cel_image); clear_image(bg_image.get(), bgcolor); render::composite_image( bg_image.get(), cel_image, sprite->palette(cel->frame()), cel->x(), cel->y(), MID(0, cel->opacity(), 255), static_cast<LayerImage*>(layer)->blendMode()); // now we have to copy the new image (bg_image) to the cel... executeAndAdd(new cmd::SetCelPosition(cel, 0, 0)); // change opacity to 255 if (cel->opacity() < 255) executeAndAdd(new cmd::SetCelOpacity(cel, 255)); // Same size of cel image and background image, we can just // replace pixels. if (bg_image->width() == cel_image->width() && bg_image->height() == cel_image->height()) { executeAndAdd(new CopyRect(cel_image, bg_image.get(), gfx::Clip(0, 0, cel_image->bounds()))); } // In other case we have to replace the whole image (this is the // most common case, a smaller transparent cel that is converted // to a canvas size cel in the background) else { ImageRef bg_image2(Image::createCopy(bg_image.get())); executeAndAdd(new cmd::ReplaceImage(sprite, cel->imageRef(), bg_image2)); } } // Fill all empty cels with a flat image filled with bgcolor for (frame_t frame(0); frame<sprite->totalFrames(); ++frame) { Cel* cel = layer->cel(frame); if (!cel) { ImageRef cel_image(Image::create(sprite->pixelFormat(), sprite->width(), sprite->height())); clear_image(cel_image.get(), bgcolor); // Create the new cel and add it to the new background layer cel = new Cel(frame, cel_image); executeAndAdd(new cmd::AddCel(layer, cel)); } } executeAndAdd(new cmd::ConfigureBackground(layer)); }
void BackgroundFromLayer::onExecute() { Layer* layer = this->layer(); Sprite* sprite = layer->sprite(); app::Document* doc = static_cast<app::Document*>(sprite->document()); color_t bgcolor = doc->bgColor(); // create a temporary image to draw each frame of the new // `Background' layer ImageRef bg_image(Image::create(sprite->pixelFormat(), sprite->width(), sprite->height())); CelList cels; layer->getCels(cels); for (Cel* cel : cels) { // get the image from the sprite's stock of images Image* cel_image = cel->image(); ASSERT(cel_image); clear_image(bg_image.get(), bgcolor); render::composite_image( bg_image.get(), cel_image, sprite->palette(cel->frame()), cel->x(), cel->y(), MID(0, cel->opacity(), 255), static_cast<LayerImage*>(layer)->blendMode()); // now we have to copy the new image (bg_image) to the cel... executeAndAdd(new cmd::SetCelPosition(cel, 0, 0)); // change opacity to 255 if (cel->opacity() < 255) executeAndAdd(new cmd::SetCelOpacity(cel, 255)); // same size of cel-image and bg-image if (bg_image->width() == cel_image->width() && bg_image->height() == cel_image->height()) { executeAndAdd(new CopyRect(cel_image, bg_image.get(), gfx::Clip(0, 0, cel_image->bounds()))); } else { ImageRef bg_image2(Image::createCopy(bg_image.get())); executeAndAdd(new cmd::ReplaceImage(sprite, cel->imageRef(), bg_image2)); } } // Fill all empty cels with a flat-image filled with bgcolor for (frame_t frame(0); frame<sprite->totalFrames(); ++frame) { Cel* cel = layer->cel(frame); if (!cel) { ImageRef cel_image(Image::create(sprite->pixelFormat(), sprite->width(), sprite->height())); clear_image(cel_image.get(), bgcolor); // Create the new cel and add it to the new background layer cel = new Cel(frame, cel_image); executeAndAdd(new cmd::AddCel(layer, cel)); } } executeAndAdd(new cmd::ConfigureBackground(layer)); }