Beispiel #1
0
    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;
}
Beispiel #3
0
    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;
}
Beispiel #6
0
	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;
}
Beispiel #8
0
/* 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;
}