Beispiel #1
0
QPixmap MediaPreviewWidget::currentImage() const {
	if (_document) {
		if (_document->sticker()) {
			if (_cacheStatus != CacheLoaded) {
				_document->checkSticker();
				if (_document->sticker()->img->isNull()) {
					if (_cacheStatus != CacheThumbLoaded && _document->thumb->loaded()) {
						QSize s = currentDimensions();
						_cache = _document->thumb->pixBlurred(s.width(), s.height());
						_cacheStatus = CacheThumbLoaded;
					}
				} else {
					QSize s = currentDimensions();
					_cache = _document->sticker()->img->pix(s.width(), s.height());
					_cacheStatus = CacheLoaded;
				}
			}
		} else {
			_document->automaticLoad(nullptr);
			if (_document->loaded()) {
				if (!_gif && _gif != BadClipReader) {
					MediaPreviewWidget *that = const_cast<MediaPreviewWidget*>(this);
					that->_gif = new ClipReader(_document->location(), _document->data(), func(that, &MediaPreviewWidget::clipCallback));
					if (gif()) _gif->setAutoplay();
				}
			}
			if (gif() && _gif->started()) {
				QSize s = currentDimensions();
				return _gif->current(s.width(), s.height(), s.width(), s.height(), getms());
			}
			if (_cacheStatus != CacheThumbLoaded && _document->thumb->loaded()) {
				QSize s = currentDimensions();
				_cache = _document->thumb->pixBlurred(s.width(), s.height());
				_cacheStatus = CacheThumbLoaded;
			}
		}
	} else if (_photo) {
		if (_cacheStatus != CacheLoaded) {
			if (_photo->full->loaded()) {
				QSize s = currentDimensions();
				LOG(("DIMENSIONS: %1 %2").arg(s.width()).arg(s.height()));
				_cache = _photo->full->pix(s.width(), s.height());
				_cacheStatus = CacheLoaded;
			} else {
				if (_cacheStatus != CacheThumbLoaded && _photo->thumb->loaded()) {
					QSize s = currentDimensions();
					LOG(("DIMENSIONS: %1 %2").arg(s.width()).arg(s.height()));
					_cache = _photo->thumb->pixBlurred(s.width(), s.height());
					_cacheStatus = CacheThumbLoaded;
				}
				_photo->thumb->load();
				_photo->full->load();
			}
		}

	}
	return _cache;
}
bool ParupaintPanvasInputOutput::loadGIF(ParupaintPanvas * panvas, const QString & filename, QString & errorStr)
{
	Q_ASSERT(panvas);

	QMovie gif(filename);
	if(!gif.isValid())
		return (errorStr = "Couldn't load GIF.").isEmpty();
	gif.jumpToFrame(0);

	panvas->setBackgroundColor(Qt::transparent);

	panvas->clearCanvas();
	panvas->resize(gif.frameRect().size());
	panvas->newCanvas(1, 0);

	do {
		const QImage & gif_image = gif.currentImage().convertToFormat(QImage::Format_ARGB32);
		ParupaintFrame * gif_frame = new ParupaintFrame(gif_image);
		panvas->layerAt(0)->appendFrame(gif_frame);

		gif.jumpToNextFrame();

	} while(gif.currentFrameNumber() != 0);

	return true;
}
Beispiel #3
0
/*
 * Read enough of the stream to initialize the SkGifCodec.
 * Returns a bool representing success or failure.
 *
 * @param codecOut
 * If it returned true, and codecOut was not nullptr,
 * codecOut will be set to a new SkGifCodec.
 *
 * @param gifOut
 * If it returned true, and codecOut was nullptr,
 * gifOut must be non-nullptr and gifOut will be set to a new
 * GifFileType pointer.
 *
 * @param stream
 * Deleted on failure.
 * codecOut will take ownership of it in the case where we created a codec.
 * Ownership is unchanged when we returned a gifOut.
 *
 */
bool SkGifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, GifFileType** gifOut) {
    SkAutoTDelete<SkStream> streamDeleter(stream);

    // Read gif header, logical screen descriptor, and global color table
    SkAutoTCallVProc<GifFileType, CloseGif> gif(open_gif(stream));

    if (nullptr == gif) {
        gif_error("DGifOpen failed.\n");
        return false;
    }

    // Read through gif extensions to get to the image data.  Set the
    // transparent index based on the extension data.
    uint32_t transIndex;
    SkCodec::Result result = ReadUpToFirstImage(gif, &transIndex);
    if (kSuccess != result){
        return false;
    }

    // Read the image descriptor
    if (GIF_ERROR == DGifGetImageDesc(gif)) {
        return false;
    }
    // If reading the image descriptor is successful, the image count will be
    // incremented.
    SkASSERT(gif->ImageCount >= 1);

    if (nullptr != codecOut) {
        SkISize size;
        SkIRect frameRect;
        if (!GetDimensions(gif, &size, &frameRect)) {
            gif_error("Invalid gif size.\n");
            return false;
        }
        bool frameIsSubset = (size != frameRect.size());

        // Determine the encoded alpha type.  The transIndex might be valid if it less
        // than 256.  We are not certain that the index is valid until we process the color
        // table, since some gifs have color tables with less than 256 colors.  If
        // there might be a valid transparent index, we must indicate that the image has
        // alpha.
        // In the case where we must support alpha, we indicate kBinary, since every
        // pixel will either be fully opaque or fully transparent.
        SkEncodedInfo::Alpha alpha = (transIndex < 256) ? SkEncodedInfo::kBinary_Alpha :
                SkEncodedInfo::kOpaque_Alpha;

        // Return the codec
        // Use kPalette since Gifs are encoded with a color table.
        // Use 8-bits per component, since this is the output we get from giflib.
        // FIXME: Gifs can actually be encoded with 4-bits per pixel.  Can we support this?
        SkEncodedInfo info = SkEncodedInfo::Make(SkEncodedInfo::kPalette_Color, alpha, 8);
        *codecOut = new SkGifCodec(size.width(), size.height(), info, streamDeleter.release(),
                gif.release(), transIndex, frameRect, frameIsSubset);
    } else {
        SkASSERT(nullptr != gifOut);
        streamDeleter.release();
        *gifOut = gif.release();
    }
    return true;
}
Beispiel #4
0
void StickerPreviewWidget::showPreview(DocumentData *sticker) {
	if (sticker && !sticker->isAnimation() && !sticker->sticker()) sticker = 0;
	if (sticker) {
		_cache = QPixmap();
		if (isHidden() || _a_shown.animating()) {
			if (isHidden()) show();
			a_shown.start(1);
			_a_shown.start();
		} else {
			update();
		}
	} else if (isHidden()) {
		return;
	} else {
		if (_gif) _cache = currentImage();
		a_shown.start(0);
		_a_shown.start();
	}
	_doc = sticker;
	if (_gif) {
		if (gif()) {
			delete _gif;
		}
		_gif = 0;
	}
	_cacheStatus = CacheNotLoaded;
}
Beispiel #5
0
FrameSegment::FrameSegment(const QString &gifFileName){


    Q_ASSERT(gifFileName.endsWith("gif"));


    QMovie gif(gifFileName);
    if(!gif.isValid()){
        return;
    }


    gif.start();
    gif.setPaused(true);

    for(int i=0,size=gif.frameCount();i<size;++i){

        QImage frame=gif.currentImage();

        Q_ASSERT(!frame.isNull());

        frames_.append(Frame(frame,gif.nextFrameDelay()));

        gif.jumpToNextFrame();

    }

    gif.stop();

}
Beispiel #6
0
int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, mem8_ptr_t data, const mem_ptr_t<CellGifDecDataCtrlParam> dataCtrlParam, mem_ptr_t<CellGifDecDataOutInfo> dataOutInfo)
{
	if (!data.IsGood() || !dataCtrlParam.IsGood() || !dataOutInfo.IsGood())
		return CELL_GIFDEC_ERROR_ARG;

	dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_STOP;

	CellGifDecSubHandle* subHandle_data;
	if(!cellGifDec->CheckId(subHandle, subHandle_data))
		return CELL_GIFDEC_ERROR_FATAL;

	const u32& fd = subHandle_data->fd;
	const u64& fileSize = subHandle_data->fileSize;
	const CellGifDecOutParam& current_outParam = subHandle_data->outParam; 

	//Copy the GIF file to a buffer
	MemoryAllocator<unsigned char> gif(fileSize);
	MemoryAllocator<u64> pos, nread;
	cellFsLseek(fd, 0, CELL_SEEK_SET, pos);
	cellFsRead(fd, gif.GetAddr(), gif.GetSize(), nread);

	//Decode GIF file. (TODO: Is there any faster alternative? Can we do it without external libraries?)
	int width, height, actual_components;
	std::shared_ptr<unsigned char> image(stbi_load_from_memory(gif, fileSize, &width, &height, &actual_components, 4));
	if (!image)
		return CELL_GIFDEC_ERROR_STREAM_FORMAT;

	uint image_size = width * height * 4;

	switch((u32)current_outParam.outputColorSpace)
	{
	case CELL_GIFDEC_RGBA:
		if (!Memory.CopyFromReal(data.GetAddr(), image.get(), image_size))
		{
			cellGifDec->Error("cellGifDecDecodeData() failed (dataa_addr=0x%x)", data.GetAddr());
			return CELL_EFAULT;
		}
	break;

	case CELL_GIFDEC_ARGB:
		for(uint i = 0; i < image_size; i+=4)
		{
			data += image.get()[i+3];
			data += image.get()[i+0];
			data += image.get()[i+1];
			data += image.get()[i+2];
		}
	break;

	default:
		return CELL_GIFDEC_ERROR_ARG;
	}

	dataOutInfo->status = CELL_GIFDEC_DEC_STATUS_FINISH;
	dataOutInfo->recordType = CELL_GIFDEC_RECORD_TYPE_IMAGE_DESC;

	return CELL_OK;
}
Beispiel #7
0
void MediaPreviewWidget::resetGifAndCache() {
	if (_gif) {
		if (gif()) {
			delete _gif;
		}
		_gif = nullptr;
	}
	_cacheStatus = CacheNotLoaded;
	_cachedSize = QSize();
}
Beispiel #8
0
QPixmap StickerPreviewWidget::currentImage() const {
	if (_doc) {
		if (_doc->sticker()) {
			if (_cacheStatus != CacheLoaded) {
				_doc->checkSticker();
				if (_doc->sticker()->img->isNull()) {
					if (_cacheStatus != CacheThumbLoaded && _doc->thumb->loaded()) {
						QSize s = currentDimensions();
						_cache = _doc->thumb->pixBlurred(s.width(), s.height());
						_cacheStatus = CacheThumbLoaded;
					}
				} else {
					QSize s = currentDimensions();
					_cache = _doc->sticker()->img->pix(s.width(), s.height());
					_cacheStatus = CacheLoaded;
				}
			}
		} else {
			_doc->automaticLoad(0);
			if (_doc->loaded()) {
				if (!_gif && _gif != BadClipReader) {
					StickerPreviewWidget *that = const_cast<StickerPreviewWidget*>(this);
					that->_gif = new ClipReader(_doc->location(), _doc->data(), func(that, &StickerPreviewWidget::clipCallback));
					if (gif()) _gif->setAutoplay();
				}
			}
			if (gif() && _gif->started()) {
				QSize s = currentDimensions();
				return _gif->current(s.width(), s.height(), s.width(), s.height(), getms());
			}
			if (_cacheStatus != CacheThumbLoaded && _doc->thumb->loaded()) {
				QSize s = currentDimensions();
				_cache = _doc->thumb->pixBlurred(s.width(), s.height());
				_cacheStatus = CacheThumbLoaded;
			}
		}
	}
	return _cache;
}
Beispiel #9
0
void StickerPreviewWidget::clipCallback(ClipReaderNotification notification) {
	switch (notification) {
	case ClipReaderReinit: {
		if (gif() && _gif->state() == ClipError) {
			delete _gif;
			_gif = BadClipReader;
		}

		if (gif() && _gif->ready() && !_gif->started()) {
			QSize s = currentDimensions();
			_gif->start(s.width(), s.height(), s.width(), s.height(), false);
		}

		update();
	} break;

	case ClipReaderRepaint: {
		if (gif() && !_gif->currentDisplayed()) {
			update();
		}
	} break;
	}
}
Beispiel #10
0
QSize StickerPreviewWidget::currentDimensions() const {
	if (!_doc) return QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());

	QSize result(qMax(convertScale(_doc->dimensions.width()), 1), qMax(convertScale(_doc->dimensions.height()), 1));
	if (gif() && _gif->ready()) {
		result = QSize(qMax(convertScale(_gif->width()), 1), qMax(convertScale(_gif->height()), 1));
	}
	if (result.width() > st::maxStickerSize) {
		result.setHeight(qMax(qRound((st::maxStickerSize * result.height()) / result.width()), 1));
		result.setWidth(st::maxStickerSize);
	}
	if (result.height() > st::maxStickerSize) {
		result.setWidth(qMax(qRound((st::maxStickerSize * result.width()) / result.height()), 1));
		result.setHeight(st::maxStickerSize);
	}
	return result;
}
Beispiel #11
0
QSize MediaPreviewWidget::currentDimensions() const {
	if (!_cachedSize.isEmpty()) {
		return _cachedSize;
	}
	if (!_document && !_photo) {
		_cachedSize = QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());
		return _cachedSize;
	}

	QSize result, box;
	if (_photo) {
		result = QSize(_photo->full->width(), _photo->full->height());
		box = QSize(width() - 2 * st::boxVerticalMargin, height() - 2 * st::boxVerticalMargin);
	} else {
		result = _document->dimensions;
		if (gif() && _gif->ready()) {
			result = QSize(_gif->width(), _gif->height());
		}
		if (_document->sticker()) {
			box = QSize(st::maxStickerSize, st::maxStickerSize);
		} else {
			box = QSize(2 * st::maxStickerSize, 2 * st::maxStickerSize);
		}
	}
	result = QSize(qMax(convertScale(result.width()), 1), qMax(convertScale(result.height()), 1));
	if (result.width() > box.width()) {
		result.setHeight(qMax((box.width() * result.height()) / result.width(), 1));
		result.setWidth(box.width());
	}
	if (result.height() > box.height()) {
		result.setWidth(qMax((box.height() * result.width()) / result.height(), 1));
		result.setHeight(box.height());
	}
	if (_photo) {
		_cachedSize = result;
	}
	return result;
}
Beispiel #12
0
/*
 * Read enough of the stream to initialize the SkGifCodec.
 * Returns a bool representing success or failure.
 *
 * @param codecOut
 * If it returned true, and codecOut was not nullptr,
 * codecOut will be set to a new SkGifCodec.
 *
 * @param gifOut
 * If it returned true, and codecOut was nullptr,
 * gifOut must be non-nullptr and gifOut will be set to a new
 * GifFileType pointer.
 *
 * @param stream
 * Deleted on failure.
 * codecOut will take ownership of it in the case where we created a codec.
 * Ownership is unchanged when we returned a gifOut.
 *
 */
bool SkGifCodec::ReadHeader(SkStream* stream, SkCodec** codecOut, GifFileType** gifOut) {
    SkAutoTDelete<SkStream> streamDeleter(stream);

    // Read gif header, logical screen descriptor, and global color table
    SkAutoTCallVProc<GifFileType, CloseGif> gif(open_gif(stream));

    if (nullptr == gif) {
        gif_error("DGifOpen failed.\n");
        return false;
    }

    // Read through gif extensions to get to the image data.  Set the
    // transparent index based on the extension data.
    uint32_t transIndex;
    SkCodec::Result result = ReadUpToFirstImage(gif, &transIndex);
    if (kSuccess != result){
        return false;
    }

    // Read the image descriptor
    if (GIF_ERROR == DGifGetImageDesc(gif)) {
        return false;
    }
    // If reading the image descriptor is successful, the image count will be
    // incremented.
    SkASSERT(gif->ImageCount >= 1);

    if (nullptr != codecOut) {
        SkISize size;
        SkIRect frameRect;
        if (!GetDimensions(gif, &size, &frameRect)) {
            gif_error("Invalid gif size.\n");
            return false;
        }
        bool frameIsSubset = (size != frameRect.size());

        // Determine the recommended alpha type.  The transIndex might be valid if it less
        // than 256.  We are not certain that the index is valid until we process the color
        // table, since some gifs have color tables with less than 256 colors.  If
        // there might be a valid transparent index, we must indicate that the image has
        // alpha.
        // In the case where we must support alpha, we have the option to set the
        // suggested alpha type to kPremul or kUnpremul.  Both are valid since the alpha
        // component will always be 0xFF or the entire 32-bit pixel will be set to zero.
        // We prefer kPremul because we support kPremul, and it is more efficient to use
        // kPremul directly even when kUnpremul is supported.
        SkAlphaType alphaType = (transIndex < 256) ? kPremul_SkAlphaType : kOpaque_SkAlphaType;

        // Return the codec
        // kIndex is the most natural color type for gifs, so we set this as
        // the default.
        SkImageInfo imageInfo = SkImageInfo::Make(size.width(), size.height(), kIndex_8_SkColorType,
                alphaType);
        *codecOut = new SkGifCodec(imageInfo, streamDeleter.detach(), gif.detach(), transIndex,
                frameRect, frameIsSubset);
    } else {
        SkASSERT(nullptr != gifOut);
        streamDeleter.detach();
        *gifOut = gif.detach();
    }
    return true;
}
Beispiel #13
0
void
genstmt(NODE *n)
{
    VREG	*muuo_ac;

    if (n == NULL) return;
    switch (n->Nop) {

    case N_STATEMENT:
	{ NODE *beg, *next;
	if (n->Nleft && n->Nleft->Nop == N_DATA) { /* Check for auto inits */
	    genadata(n->Nleft);		/* Yep, do them */
	    n = n->Nright;		/* then move on to real statements */
	}
	for(beg = n; n != NULL; n = n->Nright) {
	    if(n->Nop != N_STATEMENT)
		int_error("genstmt: bad stmt %N", n);
	    if(n->Nleft == NULL) continue;

	    /* Check out following stmt for possible optimizations */
	    if(n->Nright && (next = n->Nright->Nleft) != NULL && optgen) {
		switch(next->Nop) {

		/* Hack to encourage tail recursion */
		case Q_RETURN:			/* If next will be RETURN */
		    if(next->Nright == NULL) {	/* and has no return val */
			NODE *v;		/* Then try to optimize */
			if((v = laststmt(n->Nleft)) != NULL && v->Nop == N_FNCALL)
			    v->Nflag |= NF_RETEXPR;
		    }
		    break;

		/* If next stmt is a GOTO, ensure that any jumps
		 * within current stmt to end of stmt will
		 * instead go directly to object of the GOTO.
		 * Avoids jumping to jumps...
		 * We do a similar hack for BREAK and CONTINUE,
		 * which are similar to GOTOs except that their
		 * destination is kept in variables global to the
		 * code generation routines.
		 */
		case Q_CASE:	/* Not sure about this one yet */
		case N_LABEL:

		case Q_GOTO:
		    n->Nleft->Nendlab = next->Nxfsym;
		    break;
		case Q_BREAK:
		    n->Nleft->Nendlab = brklabel;
		    break;
		case Q_CONTINUE:
		    n->Nleft->Nendlab = looplabel;
		    break;
	        default:
	            ;	/* do nothing */
	    }	/* end of Nop switch */
	    }	/* end of next-stmt check */

	    /* Optimize label usage */
	    if(n->Nright == NULL 	/* If this is last stmt in list */
		&& optgen)
		n->Nleft->Nendlab = beg->Nendlab;	/* Copy from 1st */

	    genstmt(n->Nleft);
	}
	break;
	} /* end of N_STATEMENT case block */

    case Q_CASE:
	codlabel(n->Nxfsym);		/* send forward label */
	n->Nleft->Nendlab = n->Nendlab;	/* propagate end label */
	genstmt (n->Nleft);		/* finish rest of body */
	break;

    case N_LABEL:
	if (n->Nxfsym->Sname[0] == '%' && isdigit(n->Nxfsym->Sname[1]))
	    code_debugcall(n);
	else
	    codgolab(n->Nxfsym);		/* send goto label */
	n->Nleft->Nendlab = n->Nendlab;	/* propagate end label */
	genstmt(n->Nleft);		/* finish rest of body */
	break;

    case Q_BREAK:	code6(P_JRST, NULL, brklabel);	break;
    case Q_GOTO:	code6(P_JRST, NULL, n->Nxfsym);	break;
    case Q_CONTINUE:	code6(P_JRST, NULL, looplabel);	break;
    case Q_DO:		gdo(n);		break;
    case Q_FOR:		gfor(n);	break;
    case Q_IF:		gif(n);		break;
    case Q_RETURN:      greturn(n);	break;
    case Q_SWITCH:	gswitch(n);	break;
    case Q_WHILE:	gwhile(n);	break;

#if SYS_CSI	/* Added 1/91 for in-line monitor calls; KAR */
    case Q_MUUO:
	muuo_ac = gmuuo(n);
	vrfree(muuo_ac);
	break;
#endif

    case N_EXPRLIST:		/* Same as expression stmt */
    default:			/* None of above, assume expression stmt */
	genxrelease(n);		/* Generate it and flush any result */
	break;
    }
}