Example #1
0
void DocumentApi::deselectMask()
{
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetMask(getObjects(),
        m_document));

  m_document->setMaskVisible(false);
}
Example #2
0
void DocumentApi::setMaskPosition(int x, int y)
{
  ASSERT(m_document->getMask());

  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetMaskPosition(getObjects(), m_document));

  m_document->getMask()->setOrigin(x, y);
  m_document->resetTransformation();
}
Example #3
0
void DocumentApi::copyToCurrentMask(Mask* mask)
{
  ASSERT(m_document->getMask());
  ASSERT(mask);

  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetMask(getObjects(),
        m_document));

  m_document->getMask()->copyFrom(mask);
}
Example #4
0
void DocumentApi::configureLayerAsBackground(LayerImage* layer)
{
  // Add undoers.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled()) {
    m_undoers->pushUndoer(new undoers::SetLayerFlags(getObjects(), layer));
    m_undoers->pushUndoer(new undoers::SetLayerName(getObjects(), layer));
    m_undoers->pushUndoer(new undoers::MoveLayer(getObjects(), layer));
  }

  // Do the action.
  layer->configureAsBackground();
}
Example #5
0
void DocumentApi::restackLayerAfter(Layer* layer, Layer* afterThis)
{
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::MoveLayer(getObjects(), layer));

  layer->getParent()->stackLayer(layer, afterThis);

  DocumentEvent ev(m_document);
  ev.sprite(layer->getSprite());
  ev.layer(layer);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onLayerRestacked, ev);
}
Example #6
0
void DocumentApi::setConstantFrameRate(Sprite* sprite, int msecs)
{
  // Add undoers.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled()) {
    for (FrameNumber fr(0); fr<sprite->getTotalFrames(); ++fr)
      m_undoers->pushUndoer(new undoers::SetFrameDuration(
          getObjects(), sprite, fr));
  }

  // Do the action.
  sprite->setDurationForAllFrames(msecs);
}
Example #7
0
void DocumentApi::setCelPosition(Sprite* sprite, Cel* cel, int x, int y)
{
  ASSERT(cel);

  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetCelPosition(getObjects(), cel));

  cel->setPosition(x, y);

  DocumentEvent ev(m_document);
  ev.sprite(sprite);
  ev.cel(cel);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onCelPositionChanged, ev);
}
Example #8
0
void DocumentApi::flipImage(Image* image,
                                const gfx::Rect& bounds,
                                raster::algorithm::FlipType flipType)
{
  // Insert the undo operation.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled()) {
    m_undoers->pushUndoer
      (new undoers::FlipImage
       (getObjects(), image, bounds, flipType));
  }

  // Flip the portion of the bitmap.
  raster::algorithm::flip_image(image, bounds, flipType);
}
Example #9
0
// Adds a new image in the stock. Returns the image index in the
// stock.
int DocumentApi::addImageInStock(Sprite* sprite, Image* image)
{
  ASSERT(image != NULL);

  // Do the action.
  int imageIndex = sprite->getStock()->addImage(image);

  // Add undoers.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::AddImage(getObjects(),
        sprite->getStock(), imageIndex));

  return imageIndex;
}
Example #10
0
void DocumentApi::setSpriteSize(Sprite* sprite, int w, int h)
{
  ASSERT(w > 0);
  ASSERT(h > 0);

  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetSpriteSize(getObjects(), sprite));

  sprite->setSize(w, h);

  DocumentEvent ev(m_document);
  ev.sprite(sprite);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onSpriteSizeChanged, ev);
}
Example #11
0
// Removes and destroys the specified image in the stock.
void DocumentApi::removeImageFromStock(Sprite* sprite, int imageIndex)
{
  ASSERT(imageIndex >= 0);

  Image* image = sprite->getStock()->getImage(imageIndex);
  ASSERT(image);

  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::RemoveImage(getObjects(),
        sprite->getStock(), imageIndex));

  sprite->getStock()->removeImage(image);
  delete image;
}
Example #12
0
void DocumentApi::replaceStockImage(Sprite* sprite, int imageIndex, Image* newImage)
{
  // Get the current image in the 'image_index' position.
  Image* oldImage = sprite->getStock()->getImage(imageIndex);
  ASSERT(oldImage);

  // Replace the image in the stock.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::ReplaceImage(getObjects(),
        sprite->getStock(), imageIndex));

  sprite->getStock()->replaceImage(imageIndex, newImage);
  delete oldImage;
}
Example #13
0
void DocumentApi::setCelFramePosition(Sprite* sprite, Cel* cel, FrameNumber frame)
{
  ASSERT(cel);
  ASSERT(frame >= 0);

  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetCelFrame(getObjects(), cel));

  cel->setFrame(frame);

  DocumentEvent ev(m_document);
  ev.sprite(sprite);
  ev.cel(cel);
  ev.frame(frame);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onCelFrameChanged, ev);
}
Example #14
0
void DocumentApi::addCel(LayerImage* layer, Cel* cel)
{
  ASSERT(layer);
  ASSERT(cel);

  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::AddCel(getObjects(), layer, cel));

  layer->addCel(cel);

  DocumentEvent ev(m_document);
  ev.sprite(layer->getSprite());
  ev.layer(layer);
  ev.cel(cel);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onAddCel, ev);
}
Example #15
0
void DocumentApi::setFrameDuration(Sprite* sprite, FrameNumber frame, int msecs)
{
  // Add undoers.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetFrameDuration(
        getObjects(), sprite, frame));

  // Do the action.
  sprite->setFrameDuration(frame, msecs);

  // Notify observers.
  DocumentEvent ev(m_document);
  ev.sprite(sprite);
  ev.frame(frame);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onFrameDurationChanged, ev);
}
Example #16
0
void DocumentApi::addLayer(LayerFolder* folder, Layer* newLayer, Layer* afterThis)
{
  // Add undoers.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::AddLayer(getObjects(),
                                                m_document, newLayer));

  // Do the action.
  folder->addLayer(newLayer);
  folder->stackLayer(newLayer, afterThis);

  // Notify observers.
  DocumentEvent ev(m_document);
  ev.sprite(folder->getSprite());
  ev.layer(newLayer);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onAddLayer, ev);
}
Example #17
0
void DocumentApi::setTotalFrames(Sprite* sprite, FrameNumber frames)
{
  ASSERT(frames >= 1);

  // Add undoers.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetTotalFrames(getObjects(), m_document, sprite));

  // Do the action.
  sprite->setTotalFrames(frames);

  // Notify observers.
  DocumentEvent ev(m_document);
  ev.sprite(sprite);
  ev.frame(frames);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onTotalFramesChanged, ev);
}
Example #18
0
void DocumentApi::flipImageWithMask(Image* image, const Mask* mask, raster::algorithm::FlipType flipType, int bgcolor)
{
  UniquePtr<Image> flippedImage((Image::createCopy(image)));

  // Flip the portion of the bitmap.
  raster::algorithm::flip_image_with_mask(flippedImage, mask, flipType, bgcolor);

  // Insert the undo operation.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled()) {
    UniquePtr<Dirty> dirty((new Dirty(image, flippedImage)));
    dirty->saveImagePixels(image);

    m_undoers->pushUndoer(new undoers::DirtyArea(getObjects(), image, dirty));
  }

  // Copy the flipped image into the image specified as argument.
  image_copy(image, flippedImage, 0, 0);
}
Example #19
0
void DocumentApi::addFrame(Sprite* sprite, FrameNumber newFrame)
{
  // Move cels, and create copies of the cels in the given "newFrame".
  addFrameForLayer(sprite->getFolder(), newFrame);

  // Add the frame in the sprite structure, it adjusts the total
  // number of frames in the sprite.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::AddFrame(getObjects(), m_document, sprite, newFrame));

  sprite->addFrame(newFrame);

  // Notify observers about the new frame.
  DocumentEvent ev(m_document);
  ev.sprite(sprite);
  ev.frame(newFrame);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onAddFrame, ev);
}
Example #20
0
void DocumentApi::layerFromBackground(Layer* layer)
{
  ASSERT(layer != NULL);
  ASSERT(layer->isImage());
  ASSERT(layer->isReadable());
  ASSERT(layer->isWritable());
  ASSERT(layer->isBackground());
  ASSERT(layer->getSprite() != NULL);
  ASSERT(layer->getSprite()->getBackgroundLayer() != NULL);

  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled()) {
    m_undoers->pushUndoer(new undoers::SetLayerFlags(getObjects(), layer));
    m_undoers->pushUndoer(new undoers::SetLayerName(getObjects(), layer));
  }

  layer->setBackground(false);
  layer->setMoveable(true);
  layer->setName("Layer 0");
}
Example #21
0
void DocumentApi::removeLayer(Layer* layer)
{
  ASSERT(layer != NULL);

  // Notify observers that a layer will be removed (e.g. an Editor can
  // select another layer if the removed layer is the active one).
  DocumentEvent ev(m_document);
  ev.sprite(layer->getSprite());
  ev.layer(layer);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onRemoveLayer, ev);

  // Add undoers.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::RemoveLayer(getObjects(), m_document, layer));

  // Do the action.
  layer->getParent()->removeLayer(layer);
  delete layer;
}
Example #22
0
void DocumentApi::removeCel(LayerImage* layer, Cel* cel)
{
  ASSERT(layer);
  ASSERT(cel);

  Sprite* sprite = layer->getSprite();

  DocumentEvent ev(m_document);
  ev.sprite(sprite);
  ev.layer(layer);
  ev.cel(cel);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onRemoveCel, ev);

  // find if the image that use the cel to remove, is used by
  // another cels
  bool used = false;
  for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
    Cel* it = layer->getCel(frame);
    if (it && it != cel && it->getImage() == cel->getImage()) {
      used = true;
      break;
    }
  }

  // if the image is only used by this cel,
  // we can remove the image from the stock
  if (!used)
    removeImageFromStock(sprite, cel->getImage());

  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::RemoveCel(getObjects(),
        layer, cel));

  // remove the cel from the layer
  layer->removeCel(cel);

  // and here we destroy the cel
  delete cel;
}
Example #23
0
void DocumentApi::removeFrame(Sprite* sprite, FrameNumber frame)
{
  ASSERT(frame >= 0);

  // Remove cels from this frame (and displace one position backward
  // all next frames)
  removeFrameOfLayer(sprite->getFolder(), frame);

  // Add undoers to restore the removed frame from the sprite (to
  // restore the number and durations of frames).
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::RemoveFrame(getObjects(), m_document, sprite, frame));

  // Remove the frame from the sprite. This is the low level
  // operation, it modifies the number and duration of frames.
  sprite->removeFrame(frame);

  // Notify observers.
  DocumentEvent ev(m_document);
  ev.sprite(sprite);
  ev.frame(frame);
  m_document->notifyObservers<DocumentEvent&>(&DocumentObserver::onRemoveFrame, ev);
}
Example #24
0
void DocumentApi::flattenLayers(Sprite* sprite, int bgcolor)
{
  Image* cel_image;
  Cel* cel;

  DocumentUndo* undo = m_document->getUndo();

  // Create a temporary image.
  UniquePtr<Image> image_wrap(Image::create(sprite->getPixelFormat(),
                                            sprite->getWidth(),
                                            sprite->getHeight()));
  Image* image = image_wrap.get();

  // Get the background layer from the sprite.
  LayerImage* background = sprite->getBackgroundLayer();
  if (!background) {
    // If there aren't a background layer we must to create the background.
    background = new LayerImage(sprite);

    addLayer(sprite->getFolder(), background, NULL);
    configureLayerAsBackground(background);
  }

  // Copy all frames to the background.
  for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
    // Clear the image and render this frame.
    image_clear(image, bgcolor);
    layer_render(sprite->getFolder(), image, 0, 0, frame);

    cel = background->getCel(frame);
    if (cel) {
      cel_image = sprite->getStock()->getImage(cel->getImage());
      ASSERT(cel_image != NULL);

      // We have to save the current state of `cel_image' in the undo.
      if (undo->isEnabled()) {
        Dirty* dirty = new Dirty(cel_image, image);
        dirty->saveImagePixels(cel_image);
        m_undoers->pushUndoer(new undoers::DirtyArea(
            getObjects(), cel_image, dirty));
        delete dirty;
      }
    }
    else {
      // If there aren't a cel in this frame in the background, we
      // have to create a copy of the image for the new cel.
      cel_image = Image::createCopy(image);
      // TODO error handling: if createCopy throws

      // Here we create the new cel (with the new image `cel_image').
      cel = new Cel(frame, sprite->getStock()->addImage(cel_image));
      // TODO error handling: if new Cel throws

      // And finally we add the cel in the background.
      background->addCel(cel);
    }

    image_copy(cel_image, image, 0, 0);
  }

  // Delete old layers.
  LayerList layers = sprite->getFolder()->getLayersList();
  LayerIterator it = layers.begin();
  LayerIterator end = layers.end();
  for (; it != end; ++it)
    if (*it != background)
      removeLayer(*it);
}
Example #25
0
void DocumentApi::backgroundFromLayer(LayerImage* layer, int bgcolor)
{
  ASSERT(layer);
  ASSERT(layer->isImage());
  ASSERT(layer->isReadable());
  ASSERT(layer->isWritable());
  ASSERT(layer->getSprite() != NULL);
  ASSERT(layer->getSprite()->getBackgroundLayer() == NULL);

  DocumentUndo* undo = m_document->getUndo();
  Sprite* sprite = layer->getSprite();

  // create a temporary image to draw each frame of the new
  // `Background' layer
  UniquePtr<Image> bg_image_wrap(Image::create(sprite->getPixelFormat(),
                                               sprite->getWidth(),
                                               sprite->getHeight()));
  Image* bg_image = bg_image_wrap.get();

  CelIterator it = layer->getCelBegin();
  CelIterator end = layer->getCelEnd();

  for (; it != end; ++it) {
    Cel* cel = *it;
    ASSERT((cel->getImage() > 0) &&
           (cel->getImage() < sprite->getStock()->size()));

    // get the image from the sprite's stock of images
    Image* cel_image = sprite->getStock()->getImage(cel->getImage());
    ASSERT(cel_image);

    image_clear(bg_image, bgcolor);
    image_merge(bg_image, cel_image,
                cel->getX(),
                cel->getY(),
                MID(0, cel->getOpacity(), 255),
                layer->getBlendMode());

    // now we have to copy the new image (bg_image) to the cel...
    setCelPosition(sprite, cel, 0, 0);

    // same size of cel-image and bg-image
    if (bg_image->w == cel_image->w &&
        bg_image->h == cel_image->h) {
      if (undo->isEnabled())
        m_undoers->pushUndoer(new undoers::ImageArea(getObjects(),
            cel_image, 0, 0, cel_image->w, cel_image->h));

      image_copy(cel_image, bg_image, 0, 0);
    }
    else {
      replaceStockImage(sprite, cel->getImage(), Image::createCopy(bg_image));
    }
  }

  // Fill all empty cels with a flat-image filled with bgcolor
  for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
    Cel* cel = layer->getCel(frame);
    if (!cel) {
      Image* cel_image = Image::create(sprite->getPixelFormat(), sprite->getWidth(), sprite->getHeight());
      image_clear(cel_image, bgcolor);

      // Add the new image in the stock
      int image_index = addImageInStock(sprite, cel_image);

      // Create the new cel and add it to the new background layer
      cel = new Cel(frame, image_index);
      addCel(layer, cel);
    }
  }

  configureLayerAsBackground(layer);
}
Example #26
0
// Clears the mask region in the current sprite with the specified background color.
void DocumentApi::clearMask(Layer* layer, Cel* cel, int bgcolor)
{
  Image* image = getCelImage(layer->getSprite(), cel);
  if (!image)
    return;

  Mask* mask = m_document->getMask();
  DocumentUndo* undo = m_document->getUndo();

  // If the mask is empty or is not visible then we have to clear the
  // entire image in the cel.
  if (!m_document->isMaskVisible()) {
    // If the layer is the background then we clear the image.
    if (layer->isBackground()) {
      if (undo->isEnabled())
        m_undoers->pushUndoer(new undoers::ImageArea(getObjects(),
            image, 0, 0, image->w, image->h));

      // clear all
      image_clear(image, bgcolor);
    }
    // If the layer is transparent we can remove the cel (and its
    // associated image).
    else {
      ASSERT(layer->isImage());
      removeCel(static_cast<LayerImage*>(layer), cel);
    }
  }
  else {
    int offset_x = mask->getBounds().x-cel->getX();
    int offset_y = mask->getBounds().y-cel->getY();
    int u, v, putx, puty;
    int x1 = MAX(0, offset_x);
    int y1 = MAX(0, offset_y);
    int x2 = MIN(image->w-1, offset_x+mask->getBounds().w-1);
    int y2 = MIN(image->h-1, offset_y+mask->getBounds().h-1);

    // Do nothing
    if (x1 > x2 || y1 > y2)
      return;

    if (undo->isEnabled())
      m_undoers->pushUndoer(new undoers::ImageArea(getObjects(),
          image, x1, y1, x2-x1+1, y2-y1+1));

    // Clear the masked zones
    for (v=0; v<mask->getBounds().h; v++) {
      div_t d = div(0, 8);
      uint8_t* address = ((uint8_t**)mask->getBitmap()->line)[v]+d.quot;

      for (u=0; u<mask->getBounds().w; u++) {
        if ((*address & (1<<d.rem))) {
          putx = u + offset_x;
          puty = v + offset_y;
          image_putpixel(image, putx, puty, bgcolor);
        }

        _image_bitmap_next_bit(d, address);
      }
    }
  }
}
Example #27
0
void Document::copyLayerContent(const Layer* sourceLayer0, Document* destDoc, Layer* destLayer0) const
{
  DocumentUndo* undo = destDoc->getUndo();

  // Copy the layer name
  destLayer0->setName(sourceLayer0->getName());

  if (sourceLayer0->isImage() && destLayer0->isImage()) {
    const LayerImage* sourceLayer = static_cast<const LayerImage*>(sourceLayer0);
    LayerImage* destLayer = static_cast<LayerImage*>(destLayer0);

    // copy cels
    CelConstIterator it = sourceLayer->getCelBegin();
    CelConstIterator end = sourceLayer->getCelEnd();

    for (; it != end; ++it) {
      const Cel* sourceCel = *it;
      UniquePtr<Cel> newCel(new Cel(*sourceCel));

      ASSERT((sourceCel->getImage() >= 0) &&
             (sourceCel->getImage() < sourceLayer->getSprite()->getStock()->size()));

      const Image* sourceImage = sourceLayer->getSprite()->getStock()->getImage(sourceCel->getImage());
      ASSERT(sourceImage != NULL);

      Image* newImage = Image::createCopy(sourceImage);
      newCel->setImage(destLayer->getSprite()->getStock()->addImage(newImage));

      if (undo->isEnabled()) {
        undo->pushUndoer(new undoers::AddImage(undo->getObjects(),
            destLayer->getSprite()->getStock(),
            newCel->getImage()));
      }

      destLayer->addCel(newCel);
      newCel.release();
    }
  }
  else if (sourceLayer0->isFolder() && destLayer0->isFolder()) {
    const LayerFolder* sourceLayer = static_cast<const LayerFolder*>(sourceLayer0);
    LayerFolder* destLayer = static_cast<LayerFolder*>(destLayer0);

    LayerConstIterator it = sourceLayer->getLayerBegin();
    LayerConstIterator end = sourceLayer->getLayerEnd();

    for (; it != end; ++it) {
      Layer* sourceChild = *it;
      UniquePtr<Layer> destChild(NULL);

      if (sourceChild->isImage()) {
        destChild.reset(new LayerImage(destLayer->getSprite()));
        copyLayerContent(sourceChild, destDoc, destChild);
      }
      else if (sourceChild->isFolder()) {
        destChild.reset(new LayerFolder(destLayer->getSprite()));
        copyLayerContent(sourceChild, destDoc, destChild);
      }
      else {
        ASSERT(false);
      }

      ASSERT(destChild != NULL);

      // Add the new layer in the sprite.
      destDoc->getApi().addLayer(destLayer,
                                 destChild.release(),
                                 destLayer->getLastLayer());
    }
  }
  else  {
    ASSERT(false && "Trying to copy two incompatible layers");
  }
}
Example #28
0
void DocumentApi::setPixelFormat(Sprite* sprite, PixelFormat newFormat, DitheringMethod dithering_method)
{
  Image* old_image;
  Image* new_image;
  int c;

  if (sprite->getPixelFormat() == newFormat)
    return;

  // Change pixel format of the stock of images.
  DocumentUndo* undo = m_document->getUndo();
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetStockPixelFormat(getObjects(), sprite->getStock()));

  sprite->getStock()->setPixelFormat(newFormat);

  // TODO Review this, why we use the palette in frame 0?
  FrameNumber frame(0);

  // Use the rgbmap for the specified sprite
  const RgbMap* rgbmap = sprite->getRgbMap(frame);

  for (c=0; c<sprite->getStock()->size(); c++) {
    old_image = sprite->getStock()->getImage(c);
    if (!old_image)
      continue;

    new_image = quantization::convert_pixel_format
      (old_image, newFormat, dithering_method, rgbmap,
       sprite->getPalette(frame),
       sprite->getBackgroundLayer() != NULL);

    replaceStockImage(sprite, c, new_image);
  }

  // Change sprite's pixel format.
  if (undo->isEnabled())
    m_undoers->pushUndoer(new undoers::SetSpritePixelFormat(getObjects(), sprite));

  sprite->setPixelFormat(newFormat);

  // Regenerate extras
  m_document->destroyExtraCel();

  // When we are converting to grayscale color mode, we've to destroy
  // all palettes and put only one grayscaled-palette at the first
  // frame.
  if (newFormat == IMAGE_GRAYSCALE) {
    // Add undoers to revert all palette changes.
    if (undo->isEnabled()) {
      PalettesList palettes = sprite->getPalettes();
      for (PalettesList::iterator it = palettes.begin(); it != palettes.end(); ++it) {
        Palette* palette = *it;
        m_undoers->pushUndoer(new undoers::RemovePalette(
            getObjects(), sprite, palette->getFrame()));
      }

      m_undoers->pushUndoer(new undoers::AddPalette(
        getObjects(), sprite, FrameNumber(0)));
    }

    // It's a UniquePtr because setPalette'll create a copy of "graypal".
    UniquePtr<Palette> graypal(Palette::createGrayscale());

    sprite->resetPalettes();
    sprite->setPalette(graypal, true);
  }
}