void Sprite::pickCels(int x, int y, frame_t frame, int opacityThreshold, CelList& cels) const { std::vector<Layer*> layers; getLayersList(layers); for (int i=(int)layers.size()-1; i>=0; --i) { Layer* layer = layers[i]; if (!layer->isImage() || !layer->isVisible()) continue; Cel* cel = layer->cel(frame); if (!cel) continue; Image* image = cel->image(); if (!image) continue; if (!cel->bounds().contains(gfx::Point(x, y))) continue; color_t color = get_pixel(image, x - cel->x(), y - cel->y()); bool isOpaque = true; switch (image->pixelFormat()) { case IMAGE_RGB: isOpaque = (rgba_geta(color) >= opacityThreshold); break; case IMAGE_INDEXED: isOpaque = (color != image->maskColor()); break; case IMAGE_GRAYSCALE: isOpaque = (graya_geta(color) >= opacityThreshold); break; } if (!isOpaque) continue; cels.push_back(cel); } fflush(stdout); }
void ShiftMaskedCel::shift(int dx, int dy) { Cel* cel = this->cel(); Image* image = cel->image(); Mask* mask = static_cast<app::Document*>(cel->document())->mask(); ASSERT(mask->bitmap()); if (!mask->bitmap()) return; int x = cel->x(); int y = cel->y(); mask->offsetOrigin(-x, -y); doc::algorithm::shift_image_with_mask(image, mask, dx, dy); mask->offsetOrigin(x, y); image->incrementVersion(); }
void RenderEngine::renderLayer( const Layer* layer, Image *image, int source_x, int source_y, FrameNumber frame, Zoom zoom, void (*zoomed_func)(Image*, const Image*, const Palette*, int, int, int, int, Zoom), bool render_background, bool render_transparent, int blend_mode) { // we can't read from this layer if (!layer->isVisible()) return; switch (layer->type()) { case ObjectType::LayerImage: { if ((!render_background && layer->isBackground()) || (!render_transparent && !layer->isBackground())) break; const Cel* cel = static_cast<const LayerImage*>(layer)->getCel(frame); if (cel != NULL) { Image* src_image; // Is the 'preview_image' set to be used with this layer? if ((selected_layer == layer) && (selected_frame == frame) && (preview_image != NULL)) { src_image = preview_image; } // If not, we use the original cel-image from the images' stock else { src_image = cel->image(); } if (src_image) { int t, output_opacity; output_opacity = MID(0, cel->opacity(), 255); output_opacity = INT_MULT(output_opacity, global_opacity, t); ASSERT(src_image->maskColor() == m_sprite->transparentColor()); (*zoomed_func)(image, src_image, m_sprite->getPalette(frame), zoom.apply(cel->x()) - source_x, zoom.apply(cel->y()) - source_y, output_opacity, (blend_mode < 0 ? static_cast<const LayerImage*>(layer)->getBlendMode(): blend_mode), zoom); } } break; } case ObjectType::LayerFolder: { LayerConstIterator it = static_cast<const LayerFolder*>(layer)->getLayerBegin(); LayerConstIterator end = static_cast<const LayerFolder*>(layer)->getLayerEnd(); for (; it != end; ++it) { renderLayer(*it, image, source_x, source_y, frame, zoom, zoomed_func, render_background, render_transparent, blend_mode); } break; } } // Draw extras if (m_document->getExtraCel() && layer == m_currentLayer && frame == m_currentFrame) { Cel* extraCel = m_document->getExtraCel(); if (extraCel->opacity() > 0) { Image* extraImage = m_document->getExtraCelImage(); (*zoomed_func)(image, extraImage, m_sprite->getPalette(frame), zoom.apply(extraCel->x()) - source_x, zoom.apply(extraCel->y()) - source_y, extraCel->opacity(), m_document->getExtraCelBlendMode(), zoom); } } }
void CopyCel::onExecute() { LayerImage* srcLayer = static_cast<LayerImage*>(m_srcLayer.layer()); LayerImage* dstLayer = static_cast<LayerImage*>(m_dstLayer.layer()); ASSERT(srcLayer); ASSERT(dstLayer); Sprite* srcSprite = srcLayer->sprite(); Sprite* dstSprite = dstLayer->sprite(); ASSERT(srcSprite); ASSERT(dstSprite); ASSERT(m_srcFrame >= 0 && m_srcFrame < srcSprite->totalFrames()); ASSERT(m_dstFrame >= 0); (void)srcSprite; // To avoid unused variable warning on Release mode Cel* srcCel = srcLayer->cel(m_srcFrame); Cel* dstCel = dstLayer->cel(m_dstFrame); // Clear destination cel if it does exist. It'll be overriden by the // copy of srcCel. if (dstCel) { if (dstCel->links()) executeAndAdd(new cmd::UnlinkCel(dstCel)); executeAndAdd(new cmd::ClearCel(dstCel)); } // Add empty frames until newFrame while (dstSprite->totalFrames() <= m_dstFrame) executeAndAdd(new cmd::AddFrame(dstSprite, dstSprite->totalFrames())); Image* srcImage = (srcCel ? srcCel->image(): NULL); ImageRef dstImage; dstCel = dstLayer->cel(m_dstFrame); if (dstCel) dstImage = dstCel->imageRef(); bool createLink = (srcLayer == dstLayer && dstLayer->isContinuous()); // For background layer if (dstLayer->isBackground()) { ASSERT(dstCel); ASSERT(dstImage); if (!dstCel || !dstImage || !srcCel || !srcImage) return; if (createLink) { executeAndAdd(new cmd::SetCelData(dstCel, srcCel->dataRef())); } else { BlendMode blend = (srcLayer->isBackground() ? BlendMode::SRC: BlendMode::NORMAL); ImageRef tmp(Image::createCopy(dstImage.get())); render::composite_image(tmp.get(), srcImage, srcCel->x(), srcCel->y(), 255, blend); executeAndAdd(new cmd::CopyRect(dstImage.get(), tmp.get(), gfx::Clip(tmp->bounds()))); } } // For transparent layers else { if (dstCel) executeAndAdd(new cmd::RemoveCel(dstCel)); if (srcCel) { if (createLink) dstCel = Cel::createLink(srcCel); else dstCel = Cel::createCopy(srcCel); dstCel->setFrame(m_dstFrame); executeAndAdd(new cmd::AddCel(dstLayer, dstCel)); } } }
/** * [working thread] */ virtual void onJob() { UndoTransaction undoTransaction(m_writer.context(), "Sprite Size"); DocumentApi api = m_writer.document()->getApi(); // Get all sprite cels CelList cels; m_sprite->getCels(cels); // For each cel... int progress = 0; for (CelIterator it = cels.begin(); it != cels.end(); ++it, ++progress) { Cel* cel = *it; // Change its location api.setCelPosition(m_sprite, cel, scale_x(cel->x()), scale_y(cel->y())); // Get cel's image Image* image = cel->image(); if (!image) continue; // Resize the image int w = scale_x(image->width()); int h = scale_y(image->height()); Image* new_image = Image::create(image->pixelFormat(), MAX(1, w), MAX(1, h)); doc::algorithm::fixup_image_transparent_colors(image); doc::algorithm::resize_image(image, new_image, m_resize_method, m_sprite->getPalette(cel->frame()), m_sprite->getRgbMap(cel->frame())); api.replaceStockImage(m_sprite, cel->imageIndex(), new_image); jobProgress((float)progress / cels.size()); // cancel all the operation? if (isCanceled()) return; // UndoTransaction destructor will undo all operations } // Resize mask if (m_document->isMaskVisible()) { base::UniquePtr<Image> old_bitmap (crop_image(m_document->mask()->bitmap(), -1, -1, m_document->mask()->bitmap()->width()+2, m_document->mask()->bitmap()->height()+2, 0)); int w = scale_x(old_bitmap->width()); int h = scale_y(old_bitmap->height()); base::UniquePtr<Mask> new_mask(new Mask); new_mask->replace(scale_x(m_document->mask()->bounds().x-1), scale_y(m_document->mask()->bounds().y-1), MAX(1, w), MAX(1, h)); algorithm::resize_image(old_bitmap, new_mask->bitmap(), m_resize_method, m_sprite->getPalette(FrameNumber(0)), // Ignored m_sprite->getRgbMap(FrameNumber(0))); // Ignored // Reshrink new_mask->intersect(new_mask->bounds()); // Copy new mask api.copyToCurrentMask(new_mask); // Regenerate mask m_document->resetTransformation(); m_document->generateMaskBoundaries(); } // resize sprite api.setSpriteSize(m_sprite, m_new_width, m_new_height); // commit changes undoTransaction.commit(); }