ASFUNCTIONBODY(BitmapData,_constructor)
{
	uint32_t width;
	uint32_t height;
	bool transparent;
	uint32_t fillColor;
	BitmapData* th = obj->as<BitmapData>();
	if(th->disposed)
		throw Class<ArgumentError>::getInstanceS("Disposed BitmapData");
	ARG_UNPACK(width, 0)(height, 0)(transparent, true)(fillColor, 0xFFFFFFFF);

	ASObject::_constructor(obj,NULL,0);
	//If the bitmap is already initialized, just return
	if(width==0 || height==0 || !th->data.empty())
		return NULL;

	uint32_t *pixels=new uint32_t[width*height];
	uint32_t c=GUINT32_TO_BE(fillColor); // fromRGB expects big endian data
	if(!transparent)
	{
		uint8_t *alpha=reinterpret_cast<uint8_t *>(&c);
		*alpha=0xFF;
	}
	for(uint32_t i=0; i<width*height; i++)
		pixels[i]=c;
	th->fromRGB(reinterpret_cast<uint8_t *>(pixels), width, height, ARGB32);
	th->transparent=transparent;

	return NULL;
}
Exemple #2
0
void Image::desaturate()
{
    if (isARGB() || isRGB())
    {
        const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), BitmapData::readWrite);

        if (isARGB())
        {
            for (int y = 0; y < destData.height; ++y)
            {
                uint8* p = destData.getLinePointer (y);

                for (int x = 0; x < destData.width; ++x)
                {
                    ((PixelARGB*) p)->desaturate();
                    p += destData.pixelStride;
                }
            }
        }
        else
        {
            for (int y = 0; y < destData.height; ++y)
            {
                uint8* p = destData.getLinePointer (y);

                for (int x = 0; x < destData.width; ++x)
                {
                    ((PixelRGB*) p)->desaturate();
                    p += destData.pixelStride;
                }
            }
        }
    }
}
ASFUNCTIONBODY(BitmapData,hitTest)
{
	BitmapData* th = obj->as<BitmapData>();
	if(th->disposed)
		throw Class<ArgumentError>::getInstanceS("Disposed BitmapData");

	_NR<Point> firstPoint;
	uint32_t firstAlphaThreshold;
	_NR<ASObject> secondObject;
	_NR<Point> secondBitmapDataPoint;
	uint32_t secondAlphaThreshold;
	ARG_UNPACK (firstPoint) (firstAlphaThreshold) (secondObject) (secondBitmapDataPoint, NullRef)
					(secondAlphaThreshold,1);

	if(!secondObject->getClass() || !secondObject->getClass()->isSubClass(Class<Point>::getClass()))
		throw Class<TypeError>::getInstanceS("Error #1034: Wrong type");

	if(!secondBitmapDataPoint.isNull() || secondAlphaThreshold!=1)
		LOG(LOG_NOT_IMPLEMENTED,"BitmapData.hitTest does not expect some parameters");

	Point* secondPoint = secondObject->as<Point>();

	uint32_t pix=th->getPixelPriv(secondPoint->getX()-firstPoint->getX(), secondPoint->getY()-firstPoint->getY());
	if((pix>>24)>=firstAlphaThreshold)
		return abstract_b(true);
	else
		return abstract_b(false);
Exemple #4
0
void Image::setPixelAt (const int x, const int y, const Colour& colour)
{
    if (isPositiveAndBelow (x, getWidth()) && isPositiveAndBelow (y, getHeight()))
    {
        const BitmapData destData (*this, x, y, 1, 1, BitmapData::writeOnly);
        destData.setPixelColour (0, 0, colour);
    }
}
Exemple #5
0
//==============================================================================
Colour Image::getPixelAt (const int x, const int y) const
{
    if (isPositiveAndBelow (x, getWidth()) && isPositiveAndBelow (y, getHeight()))
    {
        const BitmapData srcData (*this, x, y, 1, 1);
        return srcData.getPixelColour (0, 0);
    }

    return Colour();
}
ASFUNCTIONBODY(BitmapData,dispose)
{
	BitmapData* th = obj->as<BitmapData>();
	th->width = 0;
	th->height = 0;
	th->data.clear();
	th->data.shrink_to_fit();
	th->disposed = true;
	th->notifyUsers();
	return NULL;
}
Exemple #7
0
void or_bitmapdata_dimensions(ORBitmapDataRef bitmapdata, uint32_t *x,
                              uint32_t *y)
{
    BitmapData *t = reinterpret_cast<BitmapData *>(bitmapdata);
    if (x != NULL) {
        *x = t->width();
    }
    if (y != NULL) {
        *y = t->height();
    }
}
Exemple #8
0
ASFUNCTIONBODY(BitmapData,setPixel32)
{
	BitmapData* th = obj->as<BitmapData>();
	if(th->disposed)
		throw Class<ArgumentError>::getInstanceS("Disposed BitmapData");
	uint32_t x;
	uint32_t y;
	uint32_t color;
	ARG_UNPACK(x)(y)(color);
	th->setPixelPriv(x, y, color, th->transparent);
	return NULL;
}
ASFUNCTIONBODY(BitmapData,getPixel32)
{
	BitmapData* th = obj->as<BitmapData>();
	if(th->disposed)
		throw Class<ArgumentError>::getInstanceS("Disposed BitmapData");
	int32_t x;
	int32_t y;
	ARG_UNPACK(x)(y);

	uint32_t pix=th->getPixelPriv(x, y);
	return abstract_ui(pix);
}
Exemple #10
0
void Image::createSolidAreaMask (RectangleList& result, const float alphaThreshold) const
{
    if (hasAlphaChannel())
    {
        const uint8 threshold = (uint8) jlimit (0, 255, roundToInt (alphaThreshold * 255.0f));
        SparseSet<int> pixelsOnRow;

        const BitmapData srcData (*this, 0, 0, getWidth(), getHeight());

        for (int y = 0; y < srcData.height; ++y)
        {
            pixelsOnRow.clear();
            const uint8* lineData = srcData.getLinePointer (y);

            if (isARGB())
            {
                for (int x = 0; x < srcData.width; ++x)
                {
                    if (((const PixelARGB*) lineData)->getAlpha() >= threshold)
                        pixelsOnRow.addRange (Range<int> (x, x + 1));

                    lineData += srcData.pixelStride;
                }
            }
            else
            {
                for (int x = 0; x < srcData.width; ++x)
                {
                    if (*lineData >= threshold)
                        pixelsOnRow.addRange (Range<int> (x, x + 1));

                    lineData += srcData.pixelStride;
                }
            }

            for (int i = 0; i < pixelsOnRow.getNumRanges(); ++i)
            {
                const Range<int> range (pixelsOnRow.getRange (i));
                result.add (Rectangle<int> (range.getStart(), y, range.getLength(), 1));
            }

            result.consolidate();
        }
    }
    else
    {
        result.add (0, 0, getWidth(), getHeight());
    }
}
ASFUNCTIONBODY(BitmapData,draw)
{
	BitmapData* th = obj->as<BitmapData>();
	if(th->disposed)
		throw Class<ArgumentError>::getInstanceS("Disposed BitmapData");

	_NR<ASObject> drawable;
	_NR<Matrix> matrix;
	_NR<ColorTransform> ctransform;
	_NR<ASString> blendMode;
	_NR<Rectangle> clipRect;
	bool smoothing;
	ARG_UNPACK (drawable) (matrix, NullRef) (ctransform, NullRef) (blendMode, NullRef)
					(clipRect, NullRef) (smoothing, false);

	if(!drawable->getClass() || !drawable->getClass()->isSubClass(InterfaceClass<IBitmapDrawable>::getClass()) )
		throw Class<TypeError>::getInstanceS("Error #1034: Wrong type");

	if(!ctransform.isNull() || !blendMode.isNull() || !clipRect.isNull() || smoothing)
		LOG(LOG_NOT_IMPLEMENTED,"BitmapData.draw does not support many parameters");

	if(drawable->is<BitmapData>())
	{
		BitmapData* data=drawable->as<BitmapData>();
		//Compute the initial matrix, if any
		MATRIX initialMatrix;
		if(!matrix.isNull())
			initialMatrix=matrix->getMATRIX();
		CairoRenderContext ctxt(th->getData(), th->width, th->height);
		//Blit the data while transforming it
		ctxt.transformedBlit(initialMatrix, data->getData(),
				data->getWidth(), data->getHeight(),
				CairoRenderContext::FILTER_NONE);
	}
	else if(drawable->is<DisplayObject>())
	{
		DisplayObject* d=drawable->as<DisplayObject>();
		//Compute the initial matrix, if any
		MATRIX initialMatrix;
		if(!matrix.isNull())
			initialMatrix=matrix->getMATRIX();
		th->drawDisplayObject(d, initialMatrix);
	}
	else
		LOG(LOG_NOT_IMPLEMENTED,"BitmapData.draw does not support " << drawable->toDebugString());

	th->notifyUsers();
	return NULL;
}
Exemple #12
0
void Bitmap::setTexture(TextureBase *texturebase)
{
    BitmapData *originalbitmapdata = bitmapdata_;
    TextureBase *originaltexturebase = texturebase_;

    bitmapdata_ = NULL;
    texturebase_ = texturebase;
    texturebase_->ref();

    setAnchorPoint(anchorx_, anchory_);  // here setAnchorPoint updates geometry and bounds

    if (originalbitmapdata)
        originalbitmapdata->unref();
    if (originaltexturebase)
        originaltexturebase->unref();
}
Exemple #13
0
void Image::setPixelData (int x, int y, int w, int h,
                          const uint8* const sourcePixelData, const int sourceLineStride)
{
    jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= getWidth() && y + h <= getHeight());

    if (Rectangle<int>::intersectRectangles (x, y, w, h, 0, 0, getWidth(), getHeight()))
    {
        const BitmapData dest (*this, x, y, w, h, BitmapData::writeOnly);

        for (int i = 0; i < h; ++i)
        {
            memcpy (dest.getLinePointer(i),
                    sourcePixelData + sourceLineStride * i,
                    w * dest.pixelStride);
        }
    }
}
Exemple #14
0
Image Image::convertedToFormat (PixelFormat newFormat) const
{
    if (image == nullptr || newFormat == image->pixelFormat)
        return *this;

    const int w = image->width, h = image->height;

    const ScopedPointer<ImageType> type (image->createType());
    Image newImage (type->create (newFormat, w, h, false));

    if (newFormat == SingleChannel)
    {
        if (! hasAlphaChannel())
        {
            newImage.clear (getBounds(), Colours::black);
        }
        else
        {
            const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly);
            const BitmapData srcData (*this, 0, 0, w, h);

            for (int y = 0; y < h; ++y)
            {
                const PixelARGB* const src = (const PixelARGB*) srcData.getLinePointer (y);
                uint8* const dst = destData.getLinePointer (y);

                for (int x = 0; x < w; ++x)
                    dst[x] = src[x].getAlpha();
            }
        }
    }
    else if (image->pixelFormat == SingleChannel && newFormat == Image::ARGB)
    {
        const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly);
        const BitmapData srcData (*this, 0, 0, w, h);

        for (int y = 0; y < h; ++y)
        {
            const PixelAlpha* const src = (const PixelAlpha*) srcData.getLinePointer (y);
            PixelARGB* const dst = (PixelARGB*) destData.getLinePointer (y);

            for (int x = 0; x < w; ++x)
                dst[x].set (src[x]);
        }
    }
    else
    {
        if (hasAlphaChannel())
            newImage.clear (getBounds());

        Graphics g (newImage);
        g.drawImageAt (*this, 0, 0);
    }

    return newImage;
}
Exemple #15
0
Image Image::convertedToFormat (PixelFormat newFormat) const
{
    if (image == nullptr || newFormat == image->format)
        return *this;

    const int w = image->width, h = image->height;
    Image newImage (newFormat, w, h, false, image->getType());

    if (newFormat == SingleChannel)
    {
        if (! hasAlphaChannel())
        {
            newImage.clear (getBounds(), Colours::black);
        }
        else
        {
            const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly);
            const BitmapData srcData (*this, 0, 0, w, h);

            for (int y = 0; y < h; ++y)
            {
                const PixelARGB* src = (const PixelARGB*) srcData.getLinePointer(y);
                uint8* dst = destData.getLinePointer (y);

                for (int x = w; --x >= 0;)
                {
                    *dst++ = src->getAlpha();
                    ++src;
                }
            }
        }
    }
    else
    {
        if (hasAlphaChannel())
            newImage.clear (getBounds());

        Graphics g (newImage);
        g.drawImageAt (*this, 0, 0);
    }

    return newImage;
}
Exemple #16
0
void Image::multiplyAllAlphas (const float amountToMultiplyBy)
{
    if (hasAlphaChannel())
    {
        const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), BitmapData::readWrite);

        if (isARGB())
        {
            for (int y = 0; y < destData.height; ++y)
            {
                uint8* p = destData.getLinePointer (y);

                for (int x = 0; x < destData.width; ++x)
                {
                    ((PixelARGB*) p)->multiplyAlpha (amountToMultiplyBy);
                    p += destData.pixelStride;
                }
            }
        }
        else
        {
            for (int y = 0; y < destData.height; ++y)
            {
                uint8* p = destData.getLinePointer (y);

                for (int x = 0; x < destData.width; ++x)
                {
                    *p = (uint8) (*p * amountToMultiplyBy);
                    p += destData.pixelStride;
                }
            }
        }
    }
    else
    {
        jassertfalse; // can't do this without an alpha-channel!
    }
}
Exemple #17
0
//--------------------------------------------------------------------------------
BitmapData* LoadJPEG(const Path& in_file)
{
	struct jpeg_decompress_struct cinfo;
	struct my_error_mgr jerr;
	
	FILE *infile;
	JSAMPARRAY buffer;

	FOPEN(&infile, in_file.GetData(), L("rb"));
								  
	if (infile == nullptr)
	{
		Assert(false);
		return nullptr;
	}

	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;
	if (setjmp(jerr.setjmp_buffer)) 
	{
		jpeg_destroy_decompress(&cinfo);
		fclose(infile);
		return nullptr;
	}

	jpeg_create_decompress(&cinfo);
	jpeg_stdio_src(&cinfo, infile);
	jpeg_read_header(&cinfo, true);
	jpeg_start_decompress(&cinfo);

	BufferFormat eFormat = BufferFormat::INVALID_FORMAT;
	switch (cinfo.out_color_space)
	{
	case JCS_EXT_ABGR:	eFormat = BufferFormat::RGBA_U32; break;
	case JCS_EXT_BGRA:	eFormat = BufferFormat::ARGB_U32; break;
	case JCS_EXT_RGBA:	eFormat = BufferFormat::ABGR_U32; break;
	case JCS_RGB:		eFormat = BufferFormat::BGR_U24; break;
	case JCS_EXT_BGR:	eFormat = BufferFormat::RGB_U24; break;
	//case JCS_RGB565:	eFormat = BufferFormat::R5G6B5_U16; break;
	case JCS_GRAYSCALE: eFormat = BufferFormat::A_U8; break;
	default:
		Assert(false);
		return nullptr;
	}

	BitmapData* pData = new BitmapData(cinfo.output_width, cinfo.output_height, eFormat);

	buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, pData->GetBufferPitch(), 1);

	while (cinfo.output_scanline < cinfo.output_height) 
	{
		jpeg_read_scanlines(&cinfo, buffer, 1);
		memcpy((u8*)&(pData->GetBuffer()[(cinfo.output_scanline-1) * pData->GetBufferPitch()]), buffer[0], pData->GetBufferPitch());
	}

	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	fclose(infile);

	Assert(jerr.pub.num_warnings == 0);

	return pData;
}
Exemple #18
0
void Image::moveImageSection (int dx, int dy,
                              int sx, int sy,
                              int w, int h)
{
    if (dx < 0)
    {
        w += dx;
        sx -= dx;
        dx = 0;
    }

    if (dy < 0)
    {
        h += dy;
        sy -= dy;
        dy = 0;
    }

    if (sx < 0)
    {
        w += sx;
        dx -= sx;
        sx = 0;
    }

    if (sy < 0)
    {
        h += sy;
        dy -= sy;
        sy = 0;
    }

    const int minX = jmin (dx, sx);
    const int minY = jmin (dy, sy);

    w = jmin (w, getWidth()  - jmax (sx, dx));
    h = jmin (h, getHeight() - jmax (sy, dy));

    if (w > 0 && h > 0)
    {
        const int maxX = jmax (dx, sx) + w;
        const int maxY = jmax (dy, sy) + h;

        const BitmapData destData (*this, minX, minY, maxX - minX, maxY - minY, BitmapData::readWrite);

        uint8* dst       = destData.getPixelPointer (dx - minX, dy - minY);
        const uint8* src = destData.getPixelPointer (sx - minX, sy - minY);

        const size_t lineSize = (size_t) (destData.pixelStride * w);

        if (dy > sy)
        {
            while (--h >= 0)
            {
                const int offset = h * destData.lineStride;
                memmove (dst + offset, src + offset, lineSize);
            }
        }
        else if (dst != src)
        {
            while (--h >= 0)
            {
                memmove (dst, src, lineSize);
                dst += destData.lineStride;
                src += destData.lineStride;
            }
        }
    }
}
Exemple #19
0
ASFUNCTIONBODY(BitmapData,draw)
{
	BitmapData* th = obj->as<BitmapData>();
	if(th->disposed)
		throw Class<ArgumentError>::getInstanceS("Disposed BitmapData");

	_NR<ASObject> drawable;
	_NR<Matrix> matrix;
	_NR<ColorTransform> ctransform;
	_NR<ASString> blendMode;
	_NR<Rectangle> clipRect;
	bool smoothing;
	ARG_UNPACK (drawable) (matrix, NullRef) (ctransform, NullRef) (blendMode, NullRef)
					(clipRect, NullRef) (smoothing, false);

	if(!drawable->getClass() || !drawable->getClass()->isSubClass(InterfaceClass<IBitmapDrawable>::getClass()) )
		throw Class<TypeError>::getInstanceS("Error #1034: Wrong type");

	if(!ctransform.isNull() || !blendMode.isNull() || !clipRect.isNull() || smoothing)
		LOG(LOG_NOT_IMPLEMENTED,"BitmapData.draw does not support many parameters");

	if(drawable->is<BitmapData>())
	{
		BitmapData* data=drawable->as<BitmapData>();
		//Compute the initial matrix, if any
		MATRIX initialMatrix;
		if(!matrix.isNull())
			initialMatrix=matrix->getMATRIX();
		CairoRenderContext ctxt(th->getData(), th->width, th->height);
		//Blit the data while transforming it
		ctxt.transformedBlit(initialMatrix, data->getData(),
				data->getWidth(), data->getHeight(),
				CairoRenderContext::FILTER_NONE);
	}
	else if(drawable->is<DisplayObject>())
	{
		//Create an InvalidateQueue to store all the hierarchy of objects that must be drawn
		SoftwareInvalidateQueue queue;
		DisplayObject* d=drawable->as<DisplayObject>();
		d->requestInvalidation(&queue);
		CairoRenderContext ctxt(th->getData(), th->width, th->height);
		//Compute the initial matrix, if any
		MATRIX initialMatrix;
		if(!matrix.isNull())
			initialMatrix=matrix->getMATRIX();
		for(auto it=queue.queue.begin();it!=queue.queue.end();it++)
		{
			DisplayObject* target=(*it).getPtr();
			//Get the drawable from each of the added objects
			IDrawable* drawable=target->invalidate(d, initialMatrix);
			if(drawable==NULL)
				continue;

			//Compute the matrix for this object
			uint8_t* buf=drawable->getPixelBuffer();
			//Construct a CachedSurface using the data
			CachedSurface& surface=ctxt.allocateCustomSurface(target,buf);
			surface.tex.width=drawable->getWidth();
			surface.tex.height=drawable->getHeight();
			surface.xOffset=drawable->getXOffset();
			surface.yOffset=drawable->getYOffset();
			delete drawable;
		}
		d->Render(ctxt, false);
	}
	else
		LOG(LOG_NOT_IMPLEMENTED,"BitmapData.draw does not support " << drawable->toDebugString());

	th->notifyUsers();
	return NULL;
}