PotraceImage::PotraceImage(const IBWRecognizer& bwRecognizer, const RasterImage& rasterImg) { pixelMap = NULL; isInvertedMap = NULL; BuildMaps(bwRecognizer, rasterImg); this->width = rasterImg.GetWidth(); this->height = rasterImg.GetHeight(); }
NS_IMETHODIMP imgTools::DecodeImageData(nsIInputStream* aInStr, const nsACString& aMimeType, imgIContainer **aContainer) { nsresult rv; RasterImage* image; // convenience alias for *aContainer NS_ENSURE_ARG_POINTER(aInStr); // If the caller didn't provide an imgIContainer, create one. if (*aContainer) { NS_ABORT_IF_FALSE((*aContainer)->GetType() == imgIContainer::TYPE_RASTER, "wrong type of imgIContainer for decoding into"); image = static_cast<RasterImage*>(*aContainer); } else { *aContainer = image = new RasterImage(); NS_ADDREF(image); } // Initialize the Image. If we're using the one from the caller, we // require that it not be initialized. nsCString mimeType(aMimeType); rv = image->Init(nullptr, mimeType.get(), "<unknown>", Image::INIT_FLAG_NONE); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIInputStream> inStream = aInStr; if (!NS_InputStreamIsBuffered(aInStr)) { nsCOMPtr<nsIInputStream> bufStream; rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInStr, 1024); if (NS_SUCCEEDED(rv)) inStream = bufStream; } // Figure out how much data we've been passed uint64_t length; rv = inStream->Available(&length); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(length <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG); // Send the source data to the Image. WriteToRasterImage always // consumes everything it gets if it doesn't run out of memory. uint32_t bytesRead; rv = inStream->ReadSegments(RasterImage::WriteToRasterImage, static_cast<void*>(image), (uint32_t)length, &bytesRead); NS_ENSURE_SUCCESS(rv, rv); NS_ABORT_IF_FALSE(bytesRead == length || image->HasError(), "WriteToRasterImage should consume everything or the image must be in error!"); // Let the Image know we've sent all the data rv = image->SourceDataComplete(); NS_ENSURE_SUCCESS(rv, rv); // All done return NS_OK; }
void PotraceImage::BuildMaps(const IBWRecognizer& bwRecognizer, const RasterImage& rasterImg) { long numberOfPixels = rasterImg.GetWidth() * rasterImg.GetHeight(); pixelMap = new PixelColor::Enum[numberOfPixels]; long currentPixelIndex = 0; for (image_size_t y = 0; y < rasterImg.GetHeight(); ++y) { for (image_size_t x = 0; x < rasterImg.GetWidth(); ++x) { pixelMap[currentPixelIndex] = bwRecognizer.GetPotraceColor(rasterImg.GetColor(x, y)); ++currentPixelIndex; } } isInvertedMap = new bool[numberOfPixels]; for (long i = 0; i < numberOfPixels; ++i) { isInvertedMap[i] = false; } }
bool CompressedImage::render(std::string filename, unsigned short numberOfIterations, float ratio) { RasterImage output; std::vector<std::thread> threads; std::vector<Pixmap*> pixmaps(m_layers.size()); RenderingParameters params = { numberOfIterations, ratio }; //Render each layer concurrently for (unsigned int i = 0; i < m_layers.size(); ++i) threads.push_back(std::thread(&CompressedImage::renderingJob, this, std::ref(params), i, std::ref(pixmaps))); for (unsigned int i = 0; i < m_layers.size(); ++i) { threads[i].join(); output.addLayer(pixmaps[i]); } return output.save(filename); }
bool CompressedImage::import(const RasterImage& rasterImage, unsigned char rangeRegionSize) { //Retrieve all raster layers std::vector<Pixmap*> layers = rasterImage.getLayers(); PixmapCompressor compressor(rangeRegionSize, rangeRegionSize * 2); //Compress each layer separately for (unsigned int i = 0; i < layers.size(); ++i) { std::cout << "====================\nLayer " << i << "\n====================" << std::endl; m_layers.push_back(compressor.compress(layers[i])); } return true; }
bool WicFile::Read(RasterImage &imgDst, unsigned int frameNo) { ::IWICBitmapFrameDecode *frame(nullptr); ::IWICFormatConverter *format_converter(nullptr); try { // Get a frame. if (FAILED(decoder->GetFrame(frameNo, &frame))) throw std::runtime_error("Failed to get a frame."); // Create a format converter, // and convert the source image frame to 32bit BGRA regardless of original format. if (FAILED(this->factory->CreateFormatConverter(&format_converter))) throw std::runtime_error("Failed to create a format converter."); if (FAILED(format_converter->Initialize(frame, ::GUID_WICPixelFormat32bppPBGRA, ::WICBitmapDitherTypeNone, nullptr, 0.0, ::WICBitmapPaletteTypeCustom))) throw std::runtime_error("Failed to convert the source image frame."); // Copy image data to the destination. // Set the size with unsigned int instead of ::size_t because ::size_t (== unsigned long) // can be wider than unsigned int. unsigned int w, h; if (FAILED(format_converter->GetSize(&w, &h))) throw std::runtime_error("Failed to get the size of the source image frame."); unsigned int sz = w * h * 4; imgDst.Resize(1, 4, w, h); if (FAILED(format_converter->CopyPixels(nullptr, w * 4, sz, imgDst.data.data()))) throw std::runtime_error("Failed to copy pixels from the source image frame."); } catch (const std::exception &ex) { SafeRelease(format_converter); SafeRelease(frame); throw ex; // Re-throw the exception. } SafeRelease(format_converter); SafeRelease(frame); return true; // redundant response to maintain the class protocol. }
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */ NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) { LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "count", count); NS_ASSERTION(aRequest, "imgRequest::OnDataAvailable -- no request!"); nsresult rv; PRUint16 imageType; if (mGotData) { imageType = mImage->GetType(); } else { LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |First time through... finding mimetype|"); mGotData = PR_TRUE; /* look at the first few bytes and see if we can tell what the data is from that * since servers tend to lie. :( */ PRUint32 out; inStr->ReadSegments(sniff_mimetype_callback, this, count, &out); #ifdef NS_DEBUG /* NS_WARNING if the content type from the channel isn't the same if the sniffing */ #endif if (mContentType.IsEmpty()) { LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |sniffing of mimetype failed|"); nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest)); rv = NS_ERROR_FAILURE; if (chan) { rv = chan->GetContentType(mContentType); } if (NS_FAILED(rv)) { PR_LOG(gImgLog, PR_LOG_ERROR, ("[this=%p] imgRequest::OnDataAvailable -- Content type unavailable from the channel\n", this)); this->Cancel(NS_IMAGELIB_ERROR_FAILURE); return NS_BINDING_ABORTED; } LOG_MSG(gImgLog, "imgRequest::OnDataAvailable", "Got content type from the channel"); } /* now we have mimetype, so we can infer the image type that we want */ if (mContentType.EqualsLiteral(SVG_MIMETYPE)) { mImage = new VectorImage(mStatusTracker.forget()); } else { mImage = new RasterImage(mStatusTracker.forget()); } mImage->SetWindowID(mWindowId); imageType = mImage->GetType(); // Notify any imgRequestProxys that are observing us that we have an Image. nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers); while (iter.HasMore()) { iter.GetNext()->SetImage(mImage); } /* set our mimetype as a property */ nsCOMPtr<nsISupportsCString> contentType(do_CreateInstance("@mozilla.org/supports-cstring;1")); if (contentType) { contentType->SetData(mContentType); mProperties->Set("type", contentType); } /* set our content disposition as a property */ nsCAutoString disposition; nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest)); if (httpChannel) { httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-disposition"), disposition); } else { nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest)); if (multiPartChannel) { multiPartChannel->GetContentDisposition(disposition); } } if (!disposition.IsEmpty()) { nsCOMPtr<nsISupportsCString> contentDisposition(do_CreateInstance("@mozilla.org/supports-cstring;1")); if (contentDisposition) { contentDisposition->SetData(disposition); mProperties->Set("content-disposition", contentDisposition); } } LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "content type", mContentType.get()); // // Figure out our Image initialization flags // // We default to the static globals PRBool isDiscardable = gDiscardable; PRBool doDecodeOnDraw = gDecodeOnDraw; // We want UI to be as snappy as possible and not to flicker. Disable discarding // and decode-on-draw for chrome URLS PRBool isChrome = PR_FALSE; rv = mURI->SchemeIs("chrome", &isChrome); if (NS_SUCCEEDED(rv) && isChrome) isDiscardable = doDecodeOnDraw = PR_FALSE; // We don't want resources like the "loading" icon to be discardable or // decode-on-draw either. PRBool isResource = PR_FALSE; rv = mURI->SchemeIs("resource", &isResource); if (NS_SUCCEEDED(rv) && isResource) isDiscardable = doDecodeOnDraw = PR_FALSE; // For multipart/x-mixed-replace, we basically want a direct channel to the // decoder. Disable both for this case as well. if (mIsMultiPartChannel) isDiscardable = doDecodeOnDraw = PR_FALSE; // We have all the information we need PRUint32 imageFlags = Image::INIT_FLAG_NONE; if (isDiscardable) imageFlags |= Image::INIT_FLAG_DISCARDABLE; if (doDecodeOnDraw) imageFlags |= Image::INIT_FLAG_DECODE_ON_DRAW; if (mIsMultiPartChannel) imageFlags |= Image::INIT_FLAG_MULTIPART; // Get our URI string nsCAutoString uriString; rv = mURI->GetSpec(uriString); if (NS_FAILED(rv)) uriString.Assign("<unknown image URI>"); // Initialize the image that we created above. For RasterImages, this // instantiates a decoder behind the scenes, so if we don't have a decoder // for this mimetype we'll find out about it here. rv = mImage->Init(this, mContentType.get(), uriString.get(), imageFlags); if (NS_FAILED(rv)) { // Probably bad mimetype this->Cancel(rv); return NS_BINDING_ABORTED; } if (imageType == imgIContainer::TYPE_RASTER) { /* Use content-length as a size hint for http channels. */ if (httpChannel) { nsCAutoString contentLength; rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-length"), contentLength); if (NS_SUCCEEDED(rv)) { PRInt32 len = contentLength.ToInteger(&rv); // Pass anything usable on so that the RasterImage can preallocate // its source buffer if (len > 0) { PRUint32 sizeHint = (PRUint32) len; sizeHint = PR_MIN(sizeHint, 20000000); /* Bound by something reasonable */ RasterImage* rasterImage = static_cast<RasterImage*>(mImage.get()); rasterImage->SetSourceSizeHint(sizeHint); } } } } if (imageType == imgIContainer::TYPE_RASTER) { // If we were waiting on the image to do something, now's our chance. if (mDecodeRequested) { mImage->RequestDecode(); } } else { // imageType == imgIContainer::TYPE_VECTOR nsCOMPtr<nsIStreamListener> imageAsStream = do_QueryInterface(mImage); NS_ABORT_IF_FALSE(imageAsStream, "SVG-typed Image failed QI to nsIStreamListener"); imageAsStream->OnStartRequest(aRequest, nsnull); } } if (imageType == imgIContainer::TYPE_RASTER) { // WriteToRasterImage always consumes everything it gets PRUint32 bytesRead; rv = inStr->ReadSegments(RasterImage::WriteToRasterImage, static_cast<void*>(mImage), count, &bytesRead); NS_ABORT_IF_FALSE(bytesRead == count, "WriteToRasterImage should consume everything!"); } else { // imageType == imgIContainer::TYPE_VECTOR nsCOMPtr<nsIStreamListener> imageAsStream = do_QueryInterface(mImage); rv = imageAsStream->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset, count); } if (NS_FAILED(rv)) { PR_LOG(gImgLog, PR_LOG_WARNING, ("[this=%p] imgRequest::OnDataAvailable -- " "copy to RasterImage failed\n", this)); this->Cancel(NS_IMAGELIB_ERROR_FAILURE); return NS_BINDING_ABORTED; } return NS_OK; }
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long long sourceOffset, in unsigned long count); */ NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, uint64_t sourceOffset, uint32_t count) { LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "count", count); NS_ASSERTION(aRequest, "imgRequest::OnDataAvailable -- no request!"); nsresult rv; if (!mGotData || mResniffMimeType) { LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |First time through... finding mimetype|"); mGotData = true; mimetype_closure closure; nsAutoCString newType; closure.request = this; closure.newType = &newType; /* look at the first few bytes and see if we can tell what the data is from that * since servers tend to lie. :( */ uint32_t out; inStr->ReadSegments(sniff_mimetype_callback, &closure, count, &out); #ifdef DEBUG /* NS_WARNING if the content type from the channel isn't the same if the sniffing */ #endif nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest)); if (newType.IsEmpty()) { LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |sniffing of mimetype failed|"); rv = NS_ERROR_FAILURE; if (chan) { rv = chan->GetContentType(newType); } if (NS_FAILED(rv)) { PR_LOG(gImgLog, PR_LOG_ERROR, ("[this=%p] imgRequest::OnDataAvailable -- Content type unavailable from the channel\n", this)); this->Cancel(NS_IMAGELIB_ERROR_FAILURE); return NS_BINDING_ABORTED; } LOG_MSG(gImgLog, "imgRequest::OnDataAvailable", "Got content type from the channel"); } // If we're a regular image and this is the first call to OnDataAvailable, // this will always be true. If we've resniffed our MIME type (i.e. we're a // multipart/x-mixed-replace image), we have to be able to switch our image // type and decoder. // We always reinitialize for SVGs, because they have no way of // reinitializing themselves. if (mContentType != newType || newType.EqualsLiteral(SVG_MIMETYPE)) { mContentType = newType; // If we've resniffed our MIME type and it changed, we need to create a // new status tracker to give to the image, because we don't have one of // our own any more. if (mResniffMimeType) { NS_ABORT_IF_FALSE(mIsMultiPartChannel, "Resniffing a non-multipart image"); mStatusTracker = new imgStatusTracker(nullptr); } mResniffMimeType = false; /* now we have mimetype, so we can infer the image type that we want */ if (mContentType.EqualsLiteral(SVG_MIMETYPE)) { mImage = new VectorImage(mStatusTracker.forget()); } else { mImage = new RasterImage(mStatusTracker.forget()); } mImage->SetInnerWindowID(mInnerWindowId); // Notify any imgRequestProxys that are observing us that we have an Image. nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers); while (iter.HasMore()) { iter.GetNext()->SetImage(mImage); } /* set our mimetype as a property */ nsCOMPtr<nsISupportsCString> contentType(do_CreateInstance("@mozilla.org/supports-cstring;1")); if (contentType) { contentType->SetData(mContentType); mProperties->Set("type", contentType); } /* set our content disposition as a property */ nsAutoCString disposition; if (chan) { chan->GetContentDispositionHeader(disposition); } if (!disposition.IsEmpty()) { nsCOMPtr<nsISupportsCString> contentDisposition(do_CreateInstance("@mozilla.org/supports-cstring;1")); if (contentDisposition) { contentDisposition->SetData(disposition); mProperties->Set("content-disposition", contentDisposition); } } LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "content type", mContentType.get()); // // Figure out our Image initialization flags // // We default to the static globals bool isDiscardable = gDiscardable; bool doDecodeOnDraw = gDecodeOnDraw; // We want UI to be as snappy as possible and not to flicker. Disable discarding // and decode-on-draw for chrome URLS bool isChrome = false; rv = mURI->SchemeIs("chrome", &isChrome); if (NS_SUCCEEDED(rv) && isChrome) isDiscardable = doDecodeOnDraw = false; // We don't want resources like the "loading" icon to be discardable or // decode-on-draw either. bool isResource = false; rv = mURI->SchemeIs("resource", &isResource); if (NS_SUCCEEDED(rv) && isResource) isDiscardable = doDecodeOnDraw = false; // For multipart/x-mixed-replace, we basically want a direct channel to the // decoder. Disable both for this case as well. if (mIsMultiPartChannel) isDiscardable = doDecodeOnDraw = false; // We have all the information we need uint32_t imageFlags = Image::INIT_FLAG_NONE; if (isDiscardable) imageFlags |= Image::INIT_FLAG_DISCARDABLE; if (doDecodeOnDraw) imageFlags |= Image::INIT_FLAG_DECODE_ON_DRAW; if (mIsMultiPartChannel) imageFlags |= Image::INIT_FLAG_MULTIPART; // Get our URI string nsAutoCString uriString; rv = mURI->GetSpec(uriString); if (NS_FAILED(rv)) uriString.Assign("<unknown image URI>"); // Initialize the image that we created above. For RasterImages, this // instantiates a decoder behind the scenes, so if we don't have a decoder // for this mimetype we'll find out about it here. rv = mImage->Init(this, mContentType.get(), uriString.get(), imageFlags); // We allow multipart images to fail to initialize without cancelling the // load because subsequent images might be fine. if (NS_FAILED(rv) && !mIsMultiPartChannel) { // Probably bad mimetype this->Cancel(rv); return NS_BINDING_ABORTED; } if (mImage->GetType() == imgIContainer::TYPE_RASTER) { /* Use content-length as a size hint for http channels. */ nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest)); if (httpChannel) { nsAutoCString contentLength; rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-length"), contentLength); if (NS_SUCCEEDED(rv)) { int32_t len = contentLength.ToInteger(&rv); // Pass anything usable on so that the RasterImage can preallocate // its source buffer if (len > 0) { uint32_t sizeHint = (uint32_t) len; sizeHint = NS_MIN<uint32_t>(sizeHint, 20000000); /* Bound by something reasonable */ RasterImage* rasterImage = static_cast<RasterImage*>(mImage.get()); rv = rasterImage->SetSourceSizeHint(sizeHint); if (NS_FAILED(rv)) { // Flush memory, try to get some back, and try again rv = nsMemory::HeapMinimize(true); nsresult rv2 = rasterImage->SetSourceSizeHint(sizeHint); // If we've still failed at this point, things are going downhill if (NS_FAILED(rv) || NS_FAILED(rv2)) { NS_WARNING("About to hit OOM in imagelib!"); } } } } } } if (mImage->GetType() == imgIContainer::TYPE_RASTER) { // If we were waiting on the image to do something, now's our chance. if (mDecodeRequested) { mImage->StartDecoding(); } } else { // mImage->GetType() == imgIContainer::TYPE_VECTOR nsCOMPtr<nsIStreamListener> imageAsStream = do_QueryInterface(mImage); NS_ABORT_IF_FALSE(imageAsStream, "SVG-typed Image failed QI to nsIStreamListener"); imageAsStream->OnStartRequest(aRequest, nullptr); } } } if (mImage->GetType() == imgIContainer::TYPE_RASTER) { // WriteToRasterImage always consumes everything it gets // if it doesn't run out of memory uint32_t bytesRead; rv = inStr->ReadSegments(RasterImage::WriteToRasterImage, static_cast<void*>(mImage), count, &bytesRead); NS_ABORT_IF_FALSE(bytesRead == count || mImage->HasError(), "WriteToRasterImage should consume everything or the image must be in error!"); } else { // mImage->GetType() == imgIContainer::TYPE_VECTOR nsCOMPtr<nsIStreamListener> imageAsStream = do_QueryInterface(mImage); rv = imageAsStream->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset, count); } if (NS_FAILED(rv)) { PR_LOG(gImgLog, PR_LOG_WARNING, ("[this=%p] imgRequest::OnDataAvailable -- " "copy to RasterImage failed\n", this)); this->Cancel(NS_IMAGELIB_ERROR_FAILURE); return NS_BINDING_ABORTED; } return NS_OK; }