Ejemplo n.º 1
0
bool AseFormat::onSave(FileOp *fop)
{
  Sprite* sprite = fop->document->getSprite();
  ASE_Header header;
  ASE_FrameHeader frame_header;
  int frame;

  FileHandle f(fop->filename.c_str(), "wb");

  /* prepare the header */
  ase_file_prepare_header(f, &header, sprite);

  /* write frame */
  for (frame=0; frame<sprite->getTotalFrames(); frame++) {
    /* prepare the header */
    ase_file_prepare_frame_header(f, &frame_header);

    /* frame duration */
    frame_header.duration = sprite->getFrameDuration(frame);

    /* the sprite is indexed and the palette changes? (or is the first frame) */
    if (sprite->getPixelFormat() == IMAGE_INDEXED &&
        (frame == 0 ||
         sprite->getPalette(frame-1)->countDiff(sprite->getPalette(frame), NULL, NULL) > 0)) {
      /* write the color chunk */
      ase_file_write_color2_chunk(f, sprite->getPalette(frame));
    }

    /* write extra chunks in the first frame */
    if (frame == 0) {
      LayerIterator it = sprite->getFolder()->get_layer_begin();
      LayerIterator end = sprite->getFolder()->get_layer_end();

      /* write layer chunks */
      for (; it != end; ++it)
        ase_file_write_layers(f, *it);
    }

    /* write cel chunks */
    ase_file_write_cels(f, sprite, sprite->getFolder(), frame);

    /* write the frame header */
    ase_file_write_frame_header(f, &frame_header);

    /* progress */
    if (sprite->getTotalFrames() > 1)
      fop_progress(fop, (float)(frame+1) / (float)(sprite->getTotalFrames()));
  }

  /* write the header */
  ase_file_write_header(f, &header);

  if (ferror(f)) {
    fop_error(fop, "Error writing file.\n");
    return false;
  }
  else {
    return true;
  }
}
Ejemplo n.º 2
0
 // Thread to do the hard work: save the file to the disk.
 virtual void onJob() override {
   try {
     fop_operate(m_fop, this);
   }
   catch (const std::exception& e) {
     fop_error(m_fop, "Error saving file:\n%s", e.what());
   }
   fop_done(m_fop);
 }
Ejemplo n.º 3
0
static void output_message(j_common_ptr cinfo)
{
  char buffer[JMSG_LENGTH_MAX];

  // Format the message.
  (*cinfo->err->format_message)(cinfo, buffer);

  // Put in the log file if.
  PRINTF("JPEG library: \"%s\"\n", buffer);

  // Leave the message for the application.
  fop_error(((struct error_mgr *)cinfo->err)->fop, "%s\n", buffer);
}
Ejemplo n.º 4
0
  // Thread to do the hard work: load the file from the disk.
  virtual void onJob() override {
    try {
      fop_operate(m_fop, this);
    }
    catch (const std::exception& e) {
      fop_error(m_fop, "Error loading file:\n%s", e.what());
    }

    if (fop_is_stop(m_fop) && m_fop->document) {
      delete m_fop->document;
      m_fop->document = NULL;
    }

    fop_done(m_fop);
  }
Ejemplo n.º 5
0
bool FliFormat::onLoad(FileOp* fop)
{
#define SETPAL()                                                \
  do {                                                          \
      for (c=0; c<256; c++) {                                   \
        pal->setEntry(c, _rgba(cmap[c*3],                       \
                               cmap[c*3+1],                     \
                               cmap[c*3+2], 255));              \
      }                                                         \
      pal->setFrame(frpos_out);                                 \
      sprite->setPalette(pal, true);                            \
    } while (0)

  unsigned char cmap[768];
  unsigned char omap[768];
  s_fli_header fli_header;
  Image *bmp, *old, *image;
  Sprite *sprite;
  LayerImage *layer;
  Palette *pal;
  int c, w, h;
  FrameNumber frpos_in;
  FrameNumber frpos_out;
  int index = 0;
  Cel *cel;

  /* open the file to read in binary mode */
  FileHandle f(fop->filename.c_str(), "rb");

  fli_read_header(f, &fli_header);
  fseek(f, 128, SEEK_SET);

  if (fli_header.magic == NO_HEADER) {
    fop_error(fop, "The file doesn't have a FLIC header\n");
    return false;
  }

  /* size by frame */
  w = fli_header.width;
  h = fli_header.height;

  /* create the bitmaps */
  bmp = Image::create(IMAGE_INDEXED, w, h);
  old = Image::create(IMAGE_INDEXED, w, h);
  pal = new Palette(FrameNumber(0), 256);
  if (!bmp || !old || !pal) {
    fop_error(fop, "Not enough memory.\n");
    if (bmp) image_free(bmp);
    if (old) image_free(old);
    if (pal) delete pal;
    return false;
  }

  // Create the image
  sprite = new Sprite(IMAGE_INDEXED, w, h, 256);
  layer = new LayerImage(sprite);
  sprite->getFolder()->addLayer(layer);
  layer->configureAsBackground();

  // Set frames and speed
  sprite->setTotalFrames(FrameNumber(fli_header.frames));
  sprite->setDurationForAllFrames(fli_header.speed);

  /* write frame by frame */
  for (frpos_in = frpos_out = FrameNumber(0);
       frpos_in < sprite->getTotalFrames();
       ++frpos_in) {
    /* read the frame */
    fli_read_frame(f, &fli_header,
                   (unsigned char *)old->dat, omap,
                   (unsigned char *)bmp->dat, cmap);

    /* first frame, or the frames changes, or the palette changes */
    if ((frpos_in == 0) ||
        (image_count_diff(old, bmp))
#ifndef USE_LINK /* TODO this should be configurable through a check-box */
        || (memcmp(omap, cmap, 768) != 0)
#endif
        ) {
      /* the image changes? */
      if (frpos_in != 0)
        ++frpos_out;

      /* add the new frame */
      image = Image::createCopy(bmp);
      if (!image) {
        fop_error(fop, "Not enough memory\n");
        break;
      }

      index = sprite->getStock()->addImage(image);
      if (index < 0) {
        image_free(image);
        fop_error(fop, "Not enough memory\n");
        break;
      }

      cel = new Cel(frpos_out, index);
      layer->addCel(cel);

      /* first frame or the palette changes */
      if ((frpos_in == 0) || (memcmp(omap, cmap, 768) != 0))
        SETPAL();
    }
#ifdef USE_LINK
    /* the palette changes */
    else if (memcmp(omap, cmap, 768) != 0) {
      ++frpos_out;
      SETPAL();

      // Add link
      cel = new Cel(frpos_out, index);
      layer_add_cel(layer, cel);
    }
#endif
    // The palette and the image don't change: add duration to the last added frame
    else {
      sprite->setFrameDuration(frpos_out,
                               sprite->getFrameDuration(frpos_out)+fli_header.speed);
    }

    /* update the old image and color-map to the new ones to compare later */
    image_copy(old, bmp, 0, 0);
    memcpy(omap, cmap, 768);

    /* update progress */
    fop_progress(fop, (float)(frpos_in+1) / (float)(sprite->getTotalFrames()));
    if (fop_is_stop(fop))
      break;

    /* just one frame? */
    if (fop->oneframe)
      break;
  }

  // Update number of frames
  sprite->setTotalFrames(frpos_out.next());

  // Destroy the bitmaps
  image_free(bmp);
  image_free(old);
  delete pal;

  fop->document = new Document(sprite);
  return true;
}
Ejemplo n.º 6
0
bool FliFormat::onSave(FileOp* fop)
{
  Sprite* sprite = fop->document->getSprite();
  unsigned char cmap[768];
  unsigned char omap[768];
  s_fli_header fli_header;
  int c, times;
  Image *bmp, *old;
  Palette *pal;

  /* prepare fli header */
  fli_header.filesize = 0;
  fli_header.frames = 0;
  fli_header.width = sprite->getWidth();
  fli_header.height = sprite->getHeight();

  if ((fli_header.width == 320) && (fli_header.height == 200))
    fli_header.magic = HEADER_FLI;
  else
    fli_header.magic = HEADER_FLC;

  fli_header.depth = 8;
  fli_header.flags = 3;
  fli_header.speed = get_time_precision(sprite);
  fli_header.created = 0;
  fli_header.updated = 0;
  fli_header.aspect_x = 1;
  fli_header.aspect_y = 1;
  fli_header.oframe1 = fli_header.oframe2 = 0;

  /* open the file to write in binary mode */
  FileHandle f(fop->filename.c_str(), "wb");

  fseek(f, 128, SEEK_SET);

  /* create the bitmaps */
  bmp = Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight());
  old = Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight());
  if ((!bmp) || (!old)) {
    fop_error(fop, "Not enough memory for temporary bitmaps.\n");
    if (bmp) image_free(bmp);
    if (old) image_free(old);
    return false;
  }

  /* write frame by frame */
  for (FrameNumber frpos(0);
       frpos < sprite->getTotalFrames();
       ++frpos) {
    /* get color map */
    pal = sprite->getPalette(frpos);
    for (c=0; c<256; c++) {
      cmap[3*c  ] = _rgba_getr(pal->getEntry(c));
      cmap[3*c+1] = _rgba_getg(pal->getEntry(c));
      cmap[3*c+2] = _rgba_getb(pal->getEntry(c));
    }

    /* render the frame in the bitmap */
    image_clear(bmp, 0);
    layer_render(sprite->getFolder(), bmp, 0, 0, frpos);

    /* how many times this frame should be written to get the same
       time that it has in the sprite */
    times = sprite->getFrameDuration(frpos) / fli_header.speed;

    for (c=0; c<times; c++) {
      /* write this frame */
      if (frpos == 0 && c == 0)
        fli_write_frame(f, &fli_header, NULL, NULL,
                        (unsigned char *)bmp->dat, cmap, W_ALL);
      else
        fli_write_frame(f, &fli_header,
                        (unsigned char *)old->dat, omap,
                        (unsigned char *)bmp->dat, cmap, W_ALL);

      /* update the old image and color-map to the new ones to compare later */
      image_copy(old, bmp, 0, 0);
      memcpy(omap, cmap, 768);
    }

    /* update progress */
    fop_progress(fop, (float)(frpos.next()) / (float)(sprite->getTotalFrames()));
  }

  /* write the header and close the file */
  fli_write_header(f, &fli_header);

  /* destroy the bitmaps */
  image_free(bmp);
  image_free(old);

  return true;
}
Ejemplo n.º 7
0
static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, int frame,
                                    PixelFormat pixelFormat,
                                    FileOp *fop, ASE_Header *header, size_t chunk_end)
{
  /* read chunk data */
  int layer_index = fgetw(f);
  int x = ((short)fgetw(f));
  int y = ((short)fgetw(f));
  int opacity = fgetc(f);
  int cel_type = fgetw(f);
  Layer* layer;

  ase_file_read_padding(f, 7);

  layer = sprite->indexToLayer(layer_index);
  if (!layer) {
    fop_error(fop, "Frame %d didn't found layer with index %d\n",
              frame, layer_index);
    return NULL;
  }
  if (!layer->is_image()) {
    fop_error(fop, "Invalid .ase file (frame %d in layer %d which does not contain images\n",
              frame, layer_index);
    return NULL;
  }

  // Create the new frame.
  UniquePtr<Cel> cel(new Cel(frame, 0));
  cel->setPosition(x, y);
  cel->setOpacity(opacity);

  switch (cel_type) {

    case ASE_FILE_RAW_CEL: {
      // Read width and height
      int w = fgetw(f);
      int h = fgetw(f);

      if (w > 0 && h > 0) {
        Image* image = Image::create(pixelFormat, w, h);

        // Read pixel data
        switch (image->getPixelFormat()) {

          case IMAGE_RGB:
            read_raw_image<RgbTraits>(f, image, fop, header);
            break;

          case IMAGE_GRAYSCALE:
            read_raw_image<GrayscaleTraits>(f, image, fop, header);
            break;

          case IMAGE_INDEXED:
            read_raw_image<IndexedTraits>(f, image, fop, header);
            break;
        }

        cel->setImage(sprite->getStock()->addImage(image));
      }
      break;
    }

    case ASE_FILE_LINK_CEL: {
      // Read link position
      int link_frame = fgetw(f);
      Cel* link = static_cast<LayerImage*>(layer)->getCel(link_frame);

      if (link) {
        // Create a copy of the linked cel (avoid using links cel)
        Image* image = Image::createCopy(sprite->getStock()->getImage(link->getImage()));
        cel->setImage(sprite->getStock()->addImage(image));
      }
      else {
        // Linked cel doesn't found
        return NULL;
      }
      break;
    }

    case ASE_FILE_COMPRESSED_CEL: {
      // Read width and height
      int w = fgetw(f);
      int h = fgetw(f);

      if (w > 0 && h > 0) {
        Image* image = Image::create(pixelFormat, w, h);

        // Try to read pixel data
        try {
          switch (image->getPixelFormat()) {

            case IMAGE_RGB:
              read_compressed_image<RgbTraits>(f, image, chunk_end, fop, header);
              break;

            case IMAGE_GRAYSCALE:
              read_compressed_image<GrayscaleTraits>(f, image, chunk_end, fop, header);
              break;

            case IMAGE_INDEXED:
              read_compressed_image<IndexedTraits>(f, image, chunk_end, fop, header);
              break;
          }
        }
        // OK, in case of error we can show the problem, but continue
        // loading more cels.
        catch (const std::exception& e) {
          fop_error(fop, e.what());
        }

        cel->setImage(sprite->getStock()->addImage(image));
      }
      break;
    }

  }

  Cel* newCel = cel.release();
  static_cast<LayerImage*>(layer)->addCel(newCel);
  return newCel;
}
Ejemplo n.º 8
0
bool AseFormat::onLoad(FileOp *fop)
{
  Sprite *sprite = NULL;
  ASE_Header header;
  ASE_FrameHeader frame_header;
  int current_level;
  int frame_pos;
  int chunk_pos;
  int chunk_size;
  int chunk_type;
  int c, frame;

  FileHandle f(fop->filename.c_str(), "rb");
  if (!f)
    return false;

  if (!ase_file_read_header(f, &header)) {
    fop_error(fop, "Error reading header\n");
    return false;
  }

  // Create the new sprite
  sprite = new Sprite(header.depth == 32 ? IMAGE_RGB:
                      header.depth == 16 ? IMAGE_GRAYSCALE: IMAGE_INDEXED,
                      header.width, header.height, header.ncolors);
  if (!sprite) {
    fop_error(fop, "Error creating sprite with file spec\n");
    return false;
  }

  // Set frames and speed
  sprite->setTotalFrames(header.frames);
  sprite->setDurationForAllFrames(header.speed);

  // Set transparent entry
  sprite->setTransparentColor(header.transparent_index);

  // Prepare variables for layer chunks
  Layer* last_layer = sprite->getFolder();
  current_level = -1;

  /* read frame by frame to end-of-file */
  for (frame=0; frame<sprite->getTotalFrames(); frame++) {
    /* start frame position */
    frame_pos = ftell(f);
    fop_progress(fop, (float)frame_pos / (float)header.size);

    /* read frame header */
    ase_file_read_frame_header(f, &frame_header);

    /* correct frame type */
    if (frame_header.magic == ASE_FILE_FRAME_MAGIC) {
      /* use frame-duration field? */
      if (frame_header.duration > 0)
        sprite->setFrameDuration(frame, frame_header.duration);

      /* read chunks */
      for (c=0; c<frame_header.chunks; c++) {
        /* start chunk position */
        chunk_pos = ftell(f);
        fop_progress(fop, (float)chunk_pos / (float)header.size);

        /* read chunk information */
        chunk_size = fgetl(f);
        chunk_type = fgetw(f);

        switch (chunk_type) {

          /* only for 8 bpp images */
          case ASE_FILE_CHUNK_FLI_COLOR:
          case ASE_FILE_CHUNK_FLI_COLOR2:
            /* fop_error(fop, "Color chunk\n"); */

            if (sprite->getPixelFormat() == IMAGE_INDEXED) {
              Palette *prev_pal = sprite->getPalette(frame);
              Palette *pal =
                chunk_type == ASE_FILE_CHUNK_FLI_COLOR ?
                ase_file_read_color_chunk(f, sprite, frame):
                ase_file_read_color2_chunk(f, sprite, frame);

              if (prev_pal->countDiff(pal, NULL, NULL) > 0) {
                sprite->setPalette(pal, true);
              }

              delete pal;
            }
            else
              fop_error(fop, "Warning: was found a color chunk in non-8bpp file\n");
            break;

          case ASE_FILE_CHUNK_LAYER: {
            /* fop_error(fop, "Layer chunk\n"); */

            ase_file_read_layer_chunk(f, sprite,
                                      &last_layer,
                                      &current_level);
            break;
          }

          case ASE_FILE_CHUNK_CEL: {
            /* fop_error(fop, "Cel chunk\n"); */

            ase_file_read_cel_chunk(f, sprite, frame,
                                    sprite->getPixelFormat(), fop, &header,
                                    chunk_pos+chunk_size);
            break;
          }

          case ASE_FILE_CHUNK_MASK: {
            Mask *mask;

            /* fop_error(fop, "Mask chunk\n"); */

            mask = ase_file_read_mask_chunk(f);
            if (mask)
              delete mask;      // TODO add the mask in some place?
            else
              fop_error(fop, "Warning: error loading a mask chunk\n");

            break;
          }

          case ASE_FILE_CHUNK_PATH:
            /* fop_error(fop, "Path chunk\n"); */
            break;

          default:
            fop_error(fop, "Warning: Unsupported chunk type %d (skipping)\n", chunk_type);
            break;
        }

        /* skip chunk size */
        fseek(f, chunk_pos+chunk_size, SEEK_SET);
      }
    }

    /* skip frame size */
    fseek(f, frame_pos+frame_header.size, SEEK_SET);

    /* just one frame? */
    if (fop->oneframe)
      break;

    if (fop_is_stop(fop))
      break;
  }

  fop->document = new Document(sprite);

  if (ferror(f)) {
    fop_error(fop, "Error reading file.\n");
    return false;
  }
  else {
    return true;
  }
}
Ejemplo n.º 9
0
bool JpegFormat::onSave(FileOp* fop)
{
  struct jpeg_compress_struct cinfo;
  struct error_mgr jerr;
  Image *image = fop->seq.image;
  FILE *file;
  JSAMPARRAY buffer;
  JDIMENSION buffer_height;
  SharedPtr<JpegOptions> jpeg_options = fop->seq.format_options;
  int c;

  // Open the file for write in it.
  file = fopen(fop->filename.c_str(), "wb");
  if (!file) {
    fop_error(fop, "Error creating file.\n");
    return false;
  }

  // Allocate and initialize JPEG compression object.
  jerr.fop = fop;
  cinfo.err = jpeg_std_error(&jerr.head);
  jpeg_create_compress(&cinfo);

  // SPECIFY data destination file.
  jpeg_stdio_dest(&cinfo, file);

  // SET parameters for compression.
  cinfo.image_width = image->w;
  cinfo.image_height = image->h;

  if (image->imgtype == IMAGE_GRAYSCALE) {
    cinfo.input_components = 1;
    cinfo.in_color_space = JCS_GRAYSCALE;
  }
  else {
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;
  }

  jpeg_set_defaults(&cinfo);
  jpeg_set_quality(&cinfo, (int)MID(0, 100.0f * jpeg_options->quality, 100), true);
  cinfo.dct_method = JDCT_ISLOW;
  cinfo.smoothing_factor = 0;

  // START compressor.
  jpeg_start_compress(&cinfo, true);

  // CREATE the buffer.
  buffer_height = 1;
  buffer = (JSAMPARRAY)base_malloc(sizeof(JSAMPROW) * buffer_height);
  if (!buffer) {
    fop_error(fop, "Not enough memory for the buffer.\n");
    jpeg_destroy_compress(&cinfo);
    fclose(file);
    return false;
  }

  for (c=0; c<(int)buffer_height; c++) {
    buffer[c] = (JSAMPROW)base_malloc(sizeof(JSAMPLE) *
				      cinfo.image_width * cinfo.num_components);
    if (!buffer[c]) {
      fop_error(fop, "Not enough memory for buffer scanlines.\n");
      for (c--; c>=0; c--)
        base_free(buffer[c]);
      base_free(buffer);
      jpeg_destroy_compress(&cinfo);
      fclose(file);
      return false;
    }
  }

  // Write each scan line.
  while (cinfo.next_scanline < cinfo.image_height) {
    // RGB
    if (image->imgtype == IMAGE_RGB) {
      uint32_t* src_address;
      uint8_t* dst_address;
      int x, y;
      for (y=0; y<(int)buffer_height; y++) {
        src_address = ((uint32_t**)image->line)[cinfo.next_scanline+y];
        dst_address = ((uint8_t**)buffer)[y];
        for (x=0; x<image->w; x++) {
          c = *(src_address++);
          *(dst_address++) = _rgba_getr(c);
          *(dst_address++) = _rgba_getg(c);
          *(dst_address++) = _rgba_getb(c);
        }
      }
    }
    // Grayscale.
    else {
      uint16_t* src_address;
      uint8_t* dst_address;
      int x, y;
      for (y=0; y<(int)buffer_height; y++) {
        src_address = ((uint16_t**)image->line)[cinfo.next_scanline+y];
        dst_address = ((uint8_t**)buffer)[y];
        for (x=0; x<image->w; x++)
          *(dst_address++) = _graya_getv(*(src_address++));
      }
    }
    jpeg_write_scanlines(&cinfo, buffer, buffer_height);
    
    fop_progress(fop, (float)(cinfo.next_scanline+1) / (float)(cinfo.image_height));
  }

  // Destroy all data.
  for (c=0; c<(int)buffer_height; c++)
    base_free(buffer[c]);
  base_free(buffer);

  // Finish compression.
  jpeg_finish_compress(&cinfo);

  // Release JPEG compression object.
  jpeg_destroy_compress(&cinfo);

  // We can close the output file.
  fclose(file);

  // All fine.
  return true;
}