예제 #1
0
    COR_EXPORT(Image*) CorConvertImage(
      Image* image,
      PixelFormat target_format)
    {
      COR_GUARD("CorConvertImage");

      // if we don't have an image, user doesn't care about format, or
      // the formats match, don't do any conversion.
      if (!image ||
          target_format == PF_DONTCARE ||
          target_format == image->getFormat())
      {
        return image;
      }

      COR_LOG("Doing the conversion...");

      // if we have a palettized image, convert it to a direct color
      // image and then convert that
      if (IsPalettized(image->getFormat())) {
        image = ExpandPalette(image);
      }

      return DirectConversion(image, target_format);
    }
예제 #2
0
  Image* DirectConversion(Image* image, PixelFormat target_format) {
    COR_GUARD("DirectConversion()");

    // assert isDirect(image->getFormat())

    const int width                 = image->getWidth();
    const int height                = image->getHeight();
    const PixelFormat source_format = image->getFormat();
    const byte* in                  = (byte*)image->getPixels();

    if (source_format == target_format) {
        return image;
    }

    const int target_size = GetPixelSize(target_format);
    byte* out_pixels = new byte[width * height * target_size];
    if (!ConvertPixels(out_pixels, target_format,
                       in, source_format,
                       width * height))
    {
      delete[] out_pixels;
      delete image;
      return 0;
    }

    delete image;
    return new SimpleImage(width, height, target_format, out_pixels);
  }
예제 #3
0
    COR_EXPORT(Image*) CorFlipImage(
      Image* image,
      int coordinate_axis)
    {
      COR_GUARD("CorFlipImage");

      // if we don't have an image, don't flip.
      if (!image) {
        return 0;
      }

      COR_LOG("Doing the flip...");

      const int width                = image->getWidth();
      const int height               = image->getHeight();
      byte* pixels                   = (byte*)image->getPixels();
      const PixelFormat pixel_format = image->getFormat();
      const int pixel_size           = GetPixelSize(pixel_format);

      // flip about the X axis
      if (coordinate_axis & CA_X) {

        byte* row = new byte[width * pixel_size];
        for (int h = 0; h < height / 2; ++h) {
          byte* top = pixels + h                * width * pixel_size;
          byte* bot = pixels + (height - h - 1) * width * pixel_size;
          std::memcpy(row, top, width * pixel_size);
          std::memcpy(top, bot, width * pixel_size);
          std::memcpy(bot, row, width * pixel_size);
        }
        delete[] row;

      }

      // flip about the Y axis
      if (coordinate_axis & CA_Y) {

        for (int h = 0; h < height; ++h) {
          byte* row = pixels + h * width * pixel_size;
          for (int w = 0; w < width / 2; ++w) {
            byte* left  = row + w               * pixel_size;
            byte* right = row + (width - w - 1) * pixel_size;
            for (int b = 0; b < pixel_size; ++b) {
              std::swap(left[b], right[b]);
            }
          }
        }

      }

      return image;
    }
예제 #4
0
  Image* ExpandPalette(Image* image) {
    COR_GUARD("ExpandPalette()");

    // assert isPalettized(image->getFormat())

    const int width                  = image->getWidth();
    const int height                 = image->getHeight();
    const byte* in                   = (byte*)image->getPixels();
    const PixelFormat palette_format = image->getPaletteFormat();
    const int pixel_size             = GetPixelSize(palette_format);
    const byte* palette              = (byte*)image->getPalette();

    byte* pixels = new byte[width * height * pixel_size];
    byte* out = pixels;
    for (int i = 0; i < width * height; ++i) {
      std::memcpy(out, palette + (*in) * pixel_size, pixel_size);
      out += pixel_size;
      ++in;
    }
    delete image;
    return new SimpleImage(width, height, palette_format, pixels);
  }
예제 #5
0
  bool SaveJPEG(File* file, Image* image) {
    COR_GUARD("SaveJPEG");

    if (!image) {
      return false;
    }

    //Hack for now
    FILE* filePtr = (FILE*)file->GetFilePtr();
    if(!filePtr)
    {
      return false;
    }

    // If the image format isn't supported directly by this function,
    // clone to a supported format and try to save with that.
    switch (image->getFormat()) {
      case PF_R8G8B8:
	      break;
      default: {
	      COR_LOG("Unsupported pixel format... cloning");
	      std::auto_ptr<Image> cloned(CloneImage(image, PF_R8G8B8));
	      return SaveJPEG(file, cloned.get());
      }
    }

    const int width  = image->getWidth();
    const int height = image->getHeight();

   	jpeg_compress_struct cinfo;
	  jpeg_error_mgr jerr;

	  cinfo.err = jpeg_std_error(&jerr);
	  jpeg_create_compress(&cinfo);

	  int nChannels = 3;

	  cinfo.in_color_space = JCS_RGB;
	  jpeg_set_defaults(&cinfo);

	  cinfo.input_components = nChannels;
	  cinfo.num_components   = nChannels;
	  cinfo.image_width  = width;
	  cinfo.image_height = height;
	  cinfo.data_precision = 8;
	  cinfo.input_gamma = 1.0;

	  jpeg_set_quality(&cinfo, 75, FALSE);
    
	  jpeg_stdio_dest(&cinfo, filePtr);
	  jpeg_start_compress(&cinfo, TRUE);

	  unsigned char *curr_scanline = (unsigned char *)image->getPixels();

	  for (int y = 0; y < height; y++){
		  jpeg_write_scanlines(&cinfo, &curr_scanline, 1);
		  curr_scanline += nChannels * width;
	  }

	  jpeg_finish_compress(&cinfo);
	  jpeg_destroy_compress(&cinfo);

    return true;
  }
예제 #6
0
  Image* OpenTGA(File* file) {
    COR_GUARD("OpenTGA");

    // read header
    byte header[18];
    if (file->read(header, 18) != 18) {
      return 0;
    }

    // decode header
    int id_length        = header[0];
    int cm_type          = header[1];
    int image_type       = header[2];
    //int cm_first         = read16_le(header + 3);
    int cm_length        = read16_le(header + 5);
    int cm_entry_size    = header[7];  // in bits
    //int x_origin         = read16_le(header + 8);
    //int y_origin         = read16_le(header + 10);
    int width            = read16_le(header + 12);
    int height           = read16_le(header + 14);
    int pixel_depth      = header[16];
    int image_descriptor = header[17];
    
    bool mirrored = (image_descriptor & (1 << 4)) != 0;  // left-to-right?
    bool flipped  = (image_descriptor & (1 << 5)) == 0;  // bottom-to-top?

    /*
     * image types
     * 0  = no image data
     * 1  = uncompressed, color-mapped
     * 2  = uncompressed, true-color
     * 3  = uncompressed, black and white
     * 9  = RLE, color-mapped
     * 10 = RLE, true-color
     * 11 = RLE, black and white
     */

    // make sure we support the image
    if (image_type != 2 || (pixel_depth != 24 && pixel_depth != 32)) {
      return 0;
    }

    // skip image id
    byte unused[255];
    if (file->read(unused, id_length) != id_length) {
      return 0;
    }

    // skip color map
    if (cm_type != 0) {
      // allocate color map
      int cm_entry_bytes = (cm_entry_size + 7) / 8;
      int cm_size = cm_entry_bytes * cm_length;
      auto_array<byte> color_map(new byte[cm_size]);
      if (file->read(color_map, cm_size) != cm_size) {
        return 0;
      }
    }

    // read image data
    PixelFormat format;
    auto_array<byte> pixels;
    if (pixel_depth == 24) {

      COR_LOG("24-bit image");

      format = PF_B8G8R8;
      int image_size = width * height * 3;
      pixels = new byte[image_size];
      if (file->read(pixels, image_size) != image_size) {
        return 0;
      }

    } else if (pixel_depth == 32) {

      COR_LOG("32-bit image");

      format = PF_B8G8R8A8;
      int image_size = width * height * 4;
      pixels = new byte[image_size];
      if (file->read(pixels, image_size) != image_size) {
        return 0;
      }

    } else {
      return 0;
    }

    // reverse each row
    if (mirrored) {
      COR_LOG("Image is mirrored");

      const int bpp = pixel_depth / 8;  // bytes per pixel
      for (int y = 0; y < height; ++y) {

	// points to the first pixel of the row
	byte* start = pixels.get() + y * width * bpp;
	// points to the last pixel of the row
	byte* end   = start + (width - 1) * bpp;

	while (start < end) {
	  for (int b = 0; b < bpp; ++b) {
	    std::swap(start[b], end[b]);
	  }
	  start += bpp;
	  end   -= bpp;
	}
      }
    }

    // reverse rows as a whole
    if (flipped) {
      COR_LOG("Image is flipped");

      const int bpp = pixel_depth / 8;  // bytes per pixel
      const int row_size = width * bpp;
      auto_array<byte> temp(new byte[row_size]);  // for the swap

      // points to the beginning of the first row
      byte* start = pixels.get();

      // points to the beginning of the last row
      byte* end   = start + (height - 1) * width * bpp;

      while (start < end) {
	memcpy(temp.get(), start,      row_size);
	memcpy(start,      end,        row_size);
	memcpy(end,        temp.get(), row_size);

	start += row_size;
	end   -= row_size;
      }
    }

    return new SimpleImage(width, height, format, pixels.release());
  }
예제 #7
0
  bool SavePNG(File* file, Image* image) {
    COR_GUARD("SavePNG");

    if (!image) {
      return false;
    }

    // If the image format isn't supported directly by this function,
    // clone to a supported format and try to save with that.
    switch (image->getFormat()) {
      case PF_R8G8B8A8:
      case PF_R8G8B8:
      case PF_I8:
	break;
      default: {
	COR_LOG("Unsupported pixel format... cloning");
	std::auto_ptr<Image> cloned(CloneImage(image, PF_R8G8B8A8));
	return SavePNG(file, cloned.get());
      }
    }

    // create write struct
    png_structp png_ptr = png_create_write_struct(
      PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
      return false;
    }

    // error handling!
    if (setjmp(png_jmpbuf(png_ptr))) {
      png_destroy_write_struct(&png_ptr, NULL);
      return false;
    }

    // create info struct
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
      png_destroy_write_struct(&png_ptr, NULL);
      return false;
    }

    int width  = image->getWidth();
    int height = image->getHeight();

    // set image characteristics
    png_set_write_fn(png_ptr, file, PNG_write, PNG_flush);

    int color_format = 0; // png output format
    int color_format_bpp = 0; // png bytes per pixel
    bool color_format_paletted = false; // png palette needed flag

    // figure out output format
    switch (image->getFormat()) {
      case PF_R8G8B8A8:
        color_format = PNG_COLOR_TYPE_RGB_ALPHA;
        color_format_bpp = 4;
        break;
      case PF_R8G8B8:
        color_format = PNG_COLOR_TYPE_RGB;
        color_format_bpp = 3;
        break;
      case PF_I8:
        color_format = PNG_COLOR_TYPE_PALETTE;
        color_format_bpp = 1;
        color_format_paletted = true;
        break;
      default:
        // Unsupported format.  This should already be taken care of
        // by the test at the beginning of this function.
        return false;
    }
    png_set_IHDR(
      png_ptr, info_ptr,
      width, height,
      8,
      color_format,
      PNG_INTERLACE_NONE,
      PNG_COMPRESSION_TYPE_DEFAULT,
      PNG_FILTER_TYPE_DEFAULT);

    if (color_format_paletted) {
      COR_LOG("Saving palettized image...");

      int image_palette_format = image->getPaletteFormat(); // palette format
      int image_palette_size = image->getPaletteSize(); // palette size

      // allocate png palette and get pointer to image palette
      png_color* png_palette = (png_color*)png_malloc(
	png_ptr, sizeof(png_color) * image_palette_size);
      byte* image_palette = (byte*)image->getPalette();
      if (image_palette_format == PF_R8G8B8) {
	// 24 bit source palette
	for (int i = 0; i < image_palette_size; i++) {
	  // copy entry directly
	  png_palette[i].red   = *image_palette++;
	  png_palette[i].green = *image_palette++;
	  png_palette[i].blue  = *image_palette++;
	}
      } else if (image_palette_format == PF_R8G8B8A8) {
	// 32 bit source palette
	for (int i = 0; i < image_palette_size; i++) {
	  // copy entry, skip alpha
	  png_palette[i].red   = *image_palette++;
	  png_palette[i].green = *image_palette++;
	  png_palette[i].blue  = *image_palette++;
	  image_palette++;
	}
      }
      // write palette
      png_set_PLTE(png_ptr, info_ptr, png_palette, image_palette_size);
    }

    byte* pixels = (byte*)image->getPixels();

    // build rows
    void** rows = (void**)png_malloc(png_ptr, sizeof(void*) * height);
    for (int i = 0; i < height; ++i) {
      rows[i] = png_malloc(png_ptr, color_format_bpp * width);
      memcpy(rows[i], pixels, color_format_bpp * width);
      pixels += width * color_format_bpp;      
    }
    png_set_rows(png_ptr, info_ptr, (png_bytepp)rows);
    info_ptr->valid |= PNG_INFO_IDAT;

    // actually write the image
    png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

    png_destroy_write_struct(&png_ptr, &info_ptr);
    return true;
  }