/* static */ already_AddRefed<imgIEncoder> ImageEncoder::GetImageEncoder(nsAString& aType) { // Get an image encoder for the media type. nsCString encoderCID("@mozilla.org/image/encoder;2?type="); NS_ConvertUTF16toUTF8 encoderType(aType); encoderCID += encoderType; nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get()); if (!encoder && aType != NS_LITERAL_STRING("image/png")) { // Unable to create an encoder instance of the specified type. Falling back // to PNG. aType.AssignLiteral("image/png"); nsCString PNGEncoderCID("@mozilla.org/image/encoder;2?type=image/png"); encoder = do_CreateInstance(PNGEncoderCID.get()); } return encoder.forget(); }
NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer, const nsACString& aMimeType, PRInt32 aScaledWidth, PRInt32 aScaledHeight, nsIInputStream **aStream) { nsresult rv; PRBool doScaling = PR_TRUE; PRUint8 *bitmapData; PRUint32 bitmapDataLength, strideSize; // If no scaled size is specified, we'll just encode the image at its // original size (no scaling). if (aScaledWidth == 0 && aScaledHeight == 0) { doScaling = PR_FALSE; } else { NS_ENSURE_ARG(aScaledWidth > 0); NS_ENSURE_ARG(aScaledHeight > 0); } // Get an image encoder for the media type nsCAutoString encoderCID( NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType); nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get()); if (!encoder) return NS_IMAGELIB_ERROR_NO_ENCODER; // Use frame 0 from the image container. nsRefPtr<gfxImageSurface> frame; rv = aContainer->CopyFrame(imgIContainer::FRAME_CURRENT, PR_TRUE, getter_AddRefs(frame)); NS_ENSURE_SUCCESS(rv, rv); if (!frame) return NS_ERROR_NOT_AVAILABLE; PRInt32 w = frame->Width(), h = frame->Height(); if (!w || !h) return NS_ERROR_FAILURE; nsRefPtr<gfxImageSurface> dest; if (!doScaling) { // If we're not scaling the image, use the actual width/height. aScaledWidth = w; aScaledHeight = h; bitmapData = frame->Data(); if (!bitmapData) return NS_ERROR_FAILURE; strideSize = frame->Stride(); bitmapDataLength = aScaledHeight * strideSize; } else { // Prepare to draw a scaled version of the image to a temporary surface... // Create a temporary image surface dest = new gfxImageSurface(gfxIntSize(aScaledWidth, aScaledHeight), gfxASurface::ImageFormatARGB32); if (!dest) return NS_ERROR_OUT_OF_MEMORY; gfxContext ctx(dest); // Set scaling gfxFloat sw = (double) aScaledWidth / w; gfxFloat sh = (double) aScaledHeight / h; ctx.Scale(sw, sh); // Paint a scaled image ctx.SetOperator(gfxContext::OPERATOR_SOURCE); ctx.SetSource(frame); ctx.Paint(); bitmapData = dest->Data(); strideSize = dest->Stride(); bitmapDataLength = aScaledHeight * strideSize; } // Encode the bitmap rv = encoder->InitFromData(bitmapData, bitmapDataLength, aScaledWidth, aScaledHeight, strideSize, imgIEncoder::INPUT_FORMAT_HOSTARGB, EmptyString()); NS_ENSURE_SUCCESS(rv, rv); return CallQueryInterface(encoder, aStream); }