Beispiel #1
0
static ImgloadErrorCode IMGLOAD_CALLBACK png_read_data(ImgloadPlugin plugin, ImgloadImage img)
{
    stbi_io_callbacks callbacks;
    callbacks.read = stb_read;
    callbacks.skip = stb_skip;
    callbacks.eof = stb_eof;


    imgload_plugin_image_seek(img, 0, SEEK_SET);

    int width, height, components;
    stbi_uc* ret = stbi_load_from_callbacks(&callbacks, img, &width, &height, &components, STBI_default);

    if (!ret)
    {
        return IMGLOAD_ERR_PLUGIN_ERROR;
    }

    int bpp;
    switch (components)
    {
    case STBI_grey:
        bpp = 1;
        break;
    case STBI_rgb:
        bpp = 3;
        break;
    case STBI_rgb_alpha:
        bpp = 4;
        break;
    default:
        return IMGLOAD_ERR_UNSUPPORTED_FORMAT;
    }

    size_t stride = width * bpp;
    size_t total_size = height * stride;

    uint8_t* buffer = (uint8_t*)imgload_plugin_realloc(plugin, NULL, total_size);
    if (!buffer)
    {
        stbi_image_free(ret);
        return IMGLOAD_ERR_OUT_OF_MEMORY;
    }

    // Copy data to our buffer
    memcpy(buffer, ret, total_size);

    stbi_image_free(ret);

    ImgloadImageData data;
    data.width = width;
    data.height = height;
    data.depth = 1;

    data.stride = stride;
    data.data_size = total_size;
    data.data = buffer;

    return imgload_plugin_image_set_image_data(img, 0, 0, &data, 1);
}
Stb::ImagePtr Stb::Image::loadFromStream(std::istream & s, Format fmt)
{
	ImagePtr image = std::static_pointer_cast<Image>(std::make_shared<Image::Wrapper>());

	try
	{
		int imageFmt = UNKNOWN;

		image->m_Data = stbi_load_from_callbacks(&g_StbCB, &s, &image->m_Width, &image->m_Height, &imageFmt, fmt);
		if (!image->m_Data)
			throw std::runtime_error(stbi_failure_reason());

		image->m_Format = static_cast<Format>(fmt == UNKNOWN ? imageFmt : fmt);
		if (image->m_Format == UNKNOWN)
			throw std::runtime_error("unable to determine pixel format for the image.");
	}
	catch (const std::exception & e)
	{
		if (image->m_Data)
			stbi_image_free(image->m_Data);

		std::clog << "Error reading image: " << e.what() << std::endl;
		image->m_Data = &g_DummyData;
		image->m_Width = 0;
		image->m_Height = 0;
		image->m_Format = UNKNOWN;
	}

	return image;
}
Beispiel #3
0
bool LoadImage( Image* image, const char* vfsPath )
{
    memset(image, 0, sizeof(Image));

    PHYSFS_File* file = PHYSFS_openRead(vfsPath);
    if(!file)
    {
        Error("Can't load '%s': %s", vfsPath, PHYSFS_getLastError());
        return false;
    }

    stbi_set_flip_vertically_on_load(1);

    image->data = stbi_load_from_callbacks(&PhysFSCallbacks,
                                           file,
                                           &image->width,
                                           &image->height,
                                           &image->channelCount,
                                           STBI_default);
    PHYSFS_close(file);
    if(!image->data)
    {
        Error("Can't load '%s': %s", vfsPath, stbi_failure_reason());
        return false;
    }

    image->type = GL_UNSIGNED_BYTE;

    return true;
}
Beispiel #4
0
                //bpp == the resulting bits per pixel
                //bpp == the source image bits per pixel
                //req_bpp == use this instead of the source
            bool load_info(
                QuickVec<unsigned char> &out_buffer,
                const char* _id,
                int* w, int* h, int* bpp, int* bpp_source, int req_bpp = 4
            ) {

                //get a io file pointer to the image
                snow::io::iosrc* src = snow::io::iosrc_from_file(_id, "rb");

                if(!src) {
                    snow::log(1, "/ snow / cannot open image file from %s", _id);
                    return false;
                }

                    //always use callbacks because we use snow abstracted IO
                stbi_io_callbacks stbi_snow_callbacks = {
                   snow_stbi_read,
                   snow_stbi_skip,
                   snow_stbi_eof
                };

                unsigned char *data = stbi_load_from_callbacks(&stbi_snow_callbacks, src, w, h, bpp_source, req_bpp);

                    //we are done with the src
                snow::io::close(src);

                snow::log(2, "/ snow / image / w:%d h:%d source bpp:%d bpp:%d\n", *w, *h, *bpp_source, req_bpp);

                if(data != NULL) {

                    int _w = *w;
                    int _h = *h;
                    int _bpp = *bpp_source;

                        //if a requested bpp was given, override it
                    if(req_bpp != 0) {
                        _bpp = req_bpp;
                    }

                        //actual used bpp
                    *bpp = _bpp;
                        //work out the total length of the buffer
                    unsigned int length = _w * _h * _bpp;
                        //store it
                    out_buffer.Set(data, length);
                        //clean up used memory
                    stbi_image_free(data);

                } else { //data != NULL

                    snow::log(1, "/ snow / image unable to be loaded by snow: %s reason: %s", _id, stbi_failure_reason());
                    return false;

                }

                return true;

            } //load_info
Beispiel #5
0
DeletablePixels loadStbi(const Path &path, int &w, int &h, int &channels)
{
    InputStreamHandle in = FileUtils::openInputStream(path);
    if (!in)
        return makeVoidPixels();

    return DeletablePixels(stbi_load_from_callbacks(&istreamCallback, in.get(),
            &w, &h, &channels, 4), stbi_image_free);
}
Beispiel #6
0
                //bpp == the resulting bits per pixel
                //bpp == the source image bits per pixel
                //req_bpp == use this instead of the source
            bool info_from_bytes(
                QuickVec<unsigned char> &out_buffer,
                const unsigned char* bytes, int byteOffset, int byteLength,
                const char* _id, int *w, int *h, int* bpp, int* bpp_source, int req_bpp = 4
            ) {

                    //get a io file pointer to the image
                snow::io::iosrc* src = snow::io::iosrc_from_mem( (void*)(bytes + byteOffset), byteLength );

                if(!src) {
                    snow::log(1, "/ snow / cannot open bytes from %s", _id);
                    return false;
                }

                    //always use callbacks because we use snow abstracted IO
                stbi_io_callbacks stbi_snow_callbacks = {
                   snow_stbi_read,
                   snow_stbi_skip,
                   snow_stbi_eof
                };

                unsigned char *data = stbi_load_from_callbacks(&stbi_snow_callbacks, src, w, h, bpp_source, req_bpp);

                    //we are done with the src
                snow::io::close(src);

                snow::log(2, "/ snow / image / w:%d h:%d source bpp:%d bpp:%d\n", *w, *h, *bpp_source, req_bpp);

                if(data != NULL) {

                    int _w = *w;
                    int _h = *h;
                    int _bpp = *bpp_source;

                        //if a requested bpp was given, override it
                    if(req_bpp != 0) {
                        _bpp = req_bpp;
                    }

                        //actual used bpp
                    *bpp = _bpp;
                        //work out the total length of the output buffer
                    unsigned int length = _w * _h * _bpp;
                        //store it
                    out_buffer.Set(data, length);
                        //clean up used memory
                    stbi_image_free(data);

                } //data != NULL

                return true;

            } //info_from_bytes
TextureResourceData* TextureLoader_stbi(ResourceDataSource &dataSource, Allocator &alloc, bool forceRGBA)
{
    stbi_io_callbacks callbacks;
    callbacks.read = read;
    callbacks.skip = skip;
    callbacks.eof = eof;

    int x, y, bpp;
    auto pixels = stbi_load_from_callbacks(&callbacks, &dataSource, &x, &y, &bpp, forceRGBA ? 4 : 0);
    if (!pixels)
    {
#ifdef STB_DO_ERROR_PRINT
        DFLOG_WARN(stbi_failure_reason());
#endif
        return nullptr;
    }

    auto fmt = PixelFormat::INVALID;

    if (bpp == STBI_rgb)
    {
        fmt = PixelFormat::RGB;
    }
    else if (bpp == STBI_rgb_alpha)
    {
        fmt = PixelFormat::RGBA;
    }
    else
    {
        DFLOG_WARN("Parsed image with an invalid bpp");
        stbi_image_free(pixels);
        return nullptr;
    }

    if (forceRGBA)
        fmt = PixelFormat::RGBA;

    auto resource = MAKE_NEW(alloc, TextureResourceData);
    resource->format = fmt;

    resource->mipLevels.resize(1);
    resource->mipLevels[0].width = x;
    resource->mipLevels[0].height = y;

    int compCount = forceRGBA ? 4 : bpp;

    resource->mipLevels[0].pixels.resize(compCount * x * y);
    memcpy(resource->mipLevels[0].pixels.data(), pixels, compCount * x * y);

    stbi_image_free(pixels);

    return resource;
}
Beispiel #8
0
bool ImageLoader::loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, Vector2u& size)
{
    // Clear the array (just in case)
    pixels.clear();

    // Make sure that the stream's reading position is at the beginning
    stream.seek(0);

    // Setup the stb_image callbacks
    stbi_io_callbacks callbacks;
    callbacks.read = &read;
    callbacks.skip = &skip;
    callbacks.eof  = &eof;

    // Load the image and get a pointer to the pixels in memory
    int width = 0;
    int height = 0;
    int channels = 0;
    unsigned char* ptr = stbi_load_from_callbacks(&callbacks, &stream, &width, &height, &channels, STBI_rgb_alpha);

    if (ptr)
    {
        // Assign the image properties
        size.x = width;
        size.y = height;

        if (width && height)
        {
            // Copy the loaded pixels to the pixel buffer
            pixels.resize(width * height * 4);
            memcpy(&pixels[0], ptr, pixels.size());
        }

        // Free the loaded pixels (they are now in our own pixel buffer)
        stbi_image_free(ptr);

        return true;
    }
    else
    {
        // Error, failed to load the image
        err() << "Failed to load image from stream. Reason: " << stbi_failure_reason() << std::endl;

        return false;
    }
}
Beispiel #9
0
/*
  call-seq:
    load_image(io, required_components = COMPONENTS_DEFAULT) => [data, width, height, components]
    load_image(io, required_components = COMPONENTS_DEFAULT) { |info| ... } => obj

  Loads an image using stb_image and returns the resulting data and its width,
  height, and the number of components per pixel in the data. The returned data
  is a packed string of unsigned 8-bit integers (8 bits per component). The
  length of the string will always be width * height * components.

  In the second form, the info array is yielded to the block if the image is
  successfully loaded. Otherwise, the method returns nil. This is possibly more
  convenient than doing an <tt>if info ... end</tt> block to check if the
  image was successfully loaded.

  === IO Objects

  IO objects accepted for loading data with must implement at least
  IO#read(length) and either IO#eof or IO#eof?. In addition, they may also
  implement a skip(length) method that skips length bytes and does not return
  any value. If the IO object does not respond to #skip, #read will be called
  instead and its result will be discarded. If you want to avoid unnecessary
  allocations, it may be wise to implement a skip method.

  === Components

  If required_components is provided and not the default value, the image data
  returned will have as many components as are requested. In turn, the number of
  components returned via the array will be the same as required_components.

  Valid options for required_components are:

  [::COMPONENTS_DEFAULT]    The default value, loads as many components as are
                            provided by the image.
  [::COMPONENTS_GREY]       Loads only one component.
  [::COMPONENTS_GREY_ALPHA] Loads two components.
  [::COMPONENTS_RGB]        Loads three components (red, green, and blue).
  [::COMPONENTS_RGB_ALPHA]  Loads four components (red, green, blue, and alpha).

  === Example

    open('image.png') { |io|
      STBI.load_image(io) { |data, width, height, components|
        format = case components
                 when STBI::COMPONENTS_GREY       then Gl::GL_RED
                 when STBI::COMPONENTS_GREY_ALPHA then Gl::GL_RG
                 when STBI_COMPONENTS_RGB         then Gl::RGB
                 when STBI_COMPONENTS_RGB_ALPHA   then Gl::RGBA
                 end

        Gl::glTexImage2D(Gl::GL_TEXTURE_2D, 0, format, width, height, 0,
                         format, Gl::GL_UNSIGNED_BYTE, data)
      }
    }
 */
static VALUE sr_load_image(int argc, VALUE *argv, VALUE sr_self)
{
  VALUE sr_callbacks;
  VALUE sr_req_comp;
  VALUE sr_image_data = Qnil;
  int x = 0;
  int y = 0;
  int components[2] = {
    STBI_default,
    0
  };

  rb_scan_args(argc, argv, "11", &sr_callbacks, &sr_req_comp);

  if (NIL_P(sr_callbacks)) {
    rb_raise(rb_eArgError, "IO object cannot be nil");
    return Qnil;
  } if (RTEST(sr_req_comp)) {
    components[0] = FIX2INT(sr_req_comp);
  }

  if (!rb_obj_respond_to(sr_callbacks, s_read_funcid, 0) ||
      !(rb_obj_respond_to(sr_callbacks, s_eof_funcid, 0) ||
        rb_obj_respond_to(sr_callbacks, s_eof_qm_funcid, 0))) {
    rb_raise(rb_eTypeError, "IO object does not respond to either read or eof/eof?");
  }

  stbi_uc *data = stbi_load_from_callbacks(&s_st_callbacks, &sr_callbacks,
    &x, &y, &components[1], components[0]);

  if (data) {
    const long length = x * y * components[!components[0]];
    sr_image_data = rb_ary_new3(4,
      rb_external_str_new((const char *)data, length),
      INT2FIX(x), INT2FIX(y),
      INT2FIX(components[!components[0]]));
    stbi_image_free(data);
  }

  if (!NIL_P(sr_image_data) && rb_block_given_p()) {
    return rb_yield_splat(sr_image_data);
  } else {
    return sr_image_data;
  }
}
Beispiel #10
0
void Gosu::loadImageFile(Gosu::Bitmap& bitmap, Reader input)
{
    stbi_io_callbacks callbacks;
    callbacks.read = readCallback;
    callbacks.skip = skipCallback;
    callbacks.eof = eofCallback;
    int x, y, n;
    stbi_uc* bytes = stbi_load_from_callbacks(&callbacks, &input, &x, &y, &n, STBI_rgb_alpha);

    if (bytes == 0) {
        // TODO - stbi_failure_reason is not thread safe. Everything here should be wrapped in a mutex.
        throw std::runtime_error("Cannot load image: " + std::string(stbi_failure_reason()));
    }

    bitmap.resize(x, y);
    std::memcpy(bitmap.data(), bytes, x * y * sizeof(Gosu::Color));

    stbi_image_free(bytes);
}
Beispiel #11
0
bool ImageLoader::loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, unsigned int& width, unsigned int& height)
{
    // Clear the array (just in case)
    pixels.clear();

    // Setup the stb_image callbacks
    stbi_io_callbacks callbacks;
    callbacks.read = &read;
    callbacks.skip = &skip;
    callbacks.eof  = &eof;

    // Load the image and get a pointer to the pixels in memory
    int imgWidth, imgHeight, imgChannels;
    unsigned char* ptr = stbi_load_from_callbacks(&callbacks, &stream, &imgWidth, &imgHeight, &imgChannels, STBI_rgb_alpha);

    if (ptr && imgWidth && imgHeight)
    {
        // Assign the image properties
        width  = imgWidth;
        height = imgHeight;

        // Copy the loaded pixels to the pixel buffer
        pixels.resize(width * height * 4);
        memcpy(&pixels[0], ptr, pixels.size());

        // Free the loaded pixels (they are now in our own pixel buffer)
        stbi_image_free(ptr);

        return true;
    }
    else
    {
        // Error, failed to load the image
        err() << "Failed to load image from stream. Reason : " << stbi_failure_reason() << std::endl;

        return false;
    }
}