Ejemplo n.º 1
0
rdctype::array<byte> CaptureFile::GetThumbnail(FileType type, uint32_t maxsize)
{
  rdctype::array<byte> buf;

  Serialiser ser(Filename(), Serialiser::READING, false);

  if(ser.HasError())
    return buf;

  ser.Rewind();

  int chunkType = ser.PushContext(NULL, NULL, 1, false);

  if(chunkType != THUMBNAIL_DATA)
    return buf;

  bool HasThumbnail = false;
  ser.Serialise(NULL, HasThumbnail);

  if(!HasThumbnail)
    return buf;

  byte *jpgbuf = NULL;
  size_t thumblen = 0;
  uint32_t thumbwidth = 0, thumbheight = 0;
  {
    ser.Serialise("ThumbWidth", thumbwidth);
    ser.Serialise("ThumbHeight", thumbheight);
    ser.SerialiseBuffer("ThumbnailPixels", jpgbuf, thumblen);
  }

  if(jpgbuf == NULL)
    return buf;

  // if the desired output is jpg and either there's no max size or it's already satisfied,
  // return the data directly
  if(type == FileType::JPG && (maxsize == 0 || (maxsize > thumbwidth && maxsize > thumbheight)))
  {
    create_array_init(buf, thumblen, jpgbuf);
  }
  else
  {
    // otherwise we need to decode, resample maybe, and re-encode

    int w = (int)thumbwidth;
    int h = (int)thumbheight;
    int comp = 3;
    byte *thumbpixels =
        jpgd::decompress_jpeg_image_from_memory(jpgbuf, (int)thumblen, &w, &h, &comp, 3);

    if(maxsize != 0)
    {
      uint32_t clampedWidth = RDCMIN(maxsize, thumbwidth);
      uint32_t clampedHeight = RDCMIN(maxsize, thumbheight);

      if(clampedWidth != thumbwidth || clampedHeight != thumbheight)
      {
        // preserve aspect ratio, take the smallest scale factor and multiply both
        float scaleX = float(clampedWidth) / float(thumbwidth);
        float scaleY = float(clampedHeight) / float(thumbheight);

        if(scaleX < scaleY)
          clampedHeight = uint32_t(scaleX * thumbheight);
        else if(scaleY < scaleX)
          clampedWidth = uint32_t(scaleY * thumbwidth);

        byte *resizedpixels = (byte *)malloc(3 * clampedWidth * clampedHeight);

        stbir_resize_uint8_srgb(thumbpixels, thumbwidth, thumbheight, 0, resizedpixels,
                                clampedWidth, clampedHeight, 0, 3, -1, 0);

        free(thumbpixels);

        thumbpixels = resizedpixels;
        thumbwidth = clampedWidth;
        thumbheight = clampedHeight;
      }
    }

    std::vector<byte> encodedBytes;

    switch(type)
    {
      case FileType::JPG:
      {
        int len = thumbwidth * thumbheight * 3;
        encodedBytes.resize(len);
        jpge::params p;
        p.m_quality = 90;
        jpge::compress_image_to_jpeg_file_in_memory(&encodedBytes[0], len, (int)thumbwidth,
                                                    (int)thumbheight, 3, thumbpixels, p);
        encodedBytes.resize(len);
        break;
      }
      case FileType::PNG:
      {
        stbi_write_png_to_func(&writeToByteVector, &encodedBytes, (int)thumbwidth, (int)thumbheight,
                               3, thumbpixels, 0);
        break;
      }
      case FileType::TGA:
      {
        stbi_write_tga_to_func(&writeToByteVector, &encodedBytes, (int)thumbwidth, (int)thumbheight,
                               3, thumbpixels);
        break;
      }
      case FileType::BMP:
      {
        stbi_write_bmp_to_func(&writeToByteVector, &encodedBytes, (int)thumbwidth, (int)thumbheight,
                               3, thumbpixels);
        break;
      }
      default:
      {
        RDCERR("Unsupported file type %d in thumbnail fetch", type);
        free(thumbpixels);
        delete[] jpgbuf;
        return buf;
      }
    }

    buf = encodedBytes;

    free(thumbpixels);
  }

  delete[] jpgbuf;

  return buf;
}
JNIEXPORT jint JNICALL Java_org_lwjgl_stb_STBImageResize_nstbir_1resize_1uint8_1srgb(JNIEnv *__env, jclass clazz, jlong input_pixelsAddress, jint input_w, jint input_h, jint input_stride_in_bytes, jlong output_pixelsAddress, jint output_w, jint output_h, jint output_stride_in_bytes, jint num_channels, jint alpha_channel, jint flags) {
    unsigned char const *input_pixels = (unsigned char const *)(intptr_t)input_pixelsAddress;
    unsigned char *output_pixels = (unsigned char *)(intptr_t)output_pixelsAddress;
    UNUSED_PARAMS(__env, clazz)
    return (jint)stbir_resize_uint8_srgb(input_pixels, input_w, input_h, input_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes, num_channels, alpha_channel, flags);
}