ImageOps.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2. *
  3. * This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. #include "ImageOps.h"
  7. #include "ClippedImage.h"
  8. #include "DecodePool.h"
  9. #include "Decoder.h"
  10. #include "DecoderFactory.h"
  11. #include "DynamicImage.h"
  12. #include "FrozenImage.h"
  13. #include "IDecodingTask.h"
  14. #include "Image.h"
  15. #include "imgIContainer.h"
  16. #include "mozilla/gfx/2D.h"
  17. #include "nsStreamUtils.h"
  18. #include "OrientedImage.h"
  19. #include "SourceBuffer.h"
  20. using namespace mozilla::gfx;
  21. namespace mozilla {
  22. namespace image {
  23. /* static */ already_AddRefed<Image>
  24. ImageOps::Freeze(Image* aImage)
  25. {
  26. RefPtr<Image> frozenImage = new FrozenImage(aImage);
  27. return frozenImage.forget();
  28. }
  29. /* static */ already_AddRefed<imgIContainer>
  30. ImageOps::Freeze(imgIContainer* aImage)
  31. {
  32. nsCOMPtr<imgIContainer> frozenImage =
  33. new FrozenImage(static_cast<Image*>(aImage));
  34. return frozenImage.forget();
  35. }
  36. /* static */ already_AddRefed<Image>
  37. ImageOps::Clip(Image* aImage, nsIntRect aClip,
  38. const Maybe<nsSize>& aSVGViewportSize)
  39. {
  40. RefPtr<Image> clippedImage = new ClippedImage(aImage, aClip, aSVGViewportSize);
  41. return clippedImage.forget();
  42. }
  43. /* static */ already_AddRefed<imgIContainer>
  44. ImageOps::Clip(imgIContainer* aImage, nsIntRect aClip,
  45. const Maybe<nsSize>& aSVGViewportSize)
  46. {
  47. nsCOMPtr<imgIContainer> clippedImage =
  48. new ClippedImage(static_cast<Image*>(aImage), aClip, aSVGViewportSize);
  49. return clippedImage.forget();
  50. }
  51. /* static */ already_AddRefed<Image>
  52. ImageOps::Orient(Image* aImage, Orientation aOrientation)
  53. {
  54. RefPtr<Image> orientedImage = new OrientedImage(aImage, aOrientation);
  55. return orientedImage.forget();
  56. }
  57. /* static */ already_AddRefed<imgIContainer>
  58. ImageOps::Orient(imgIContainer* aImage, Orientation aOrientation)
  59. {
  60. nsCOMPtr<imgIContainer> orientedImage =
  61. new OrientedImage(static_cast<Image*>(aImage), aOrientation);
  62. return orientedImage.forget();
  63. }
  64. /* static */ already_AddRefed<imgIContainer>
  65. ImageOps::CreateFromDrawable(gfxDrawable* aDrawable)
  66. {
  67. nsCOMPtr<imgIContainer> drawableImage = new DynamicImage(aDrawable);
  68. return drawableImage.forget();
  69. }
  70. /* static */ already_AddRefed<gfx::SourceSurface>
  71. ImageOps::DecodeToSurface(nsIInputStream* aInputStream,
  72. const nsACString& aMimeType,
  73. uint32_t aFlags)
  74. {
  75. MOZ_ASSERT(aInputStream);
  76. nsresult rv;
  77. // Prepare the input stream.
  78. nsCOMPtr<nsIInputStream> inputStream = aInputStream;
  79. if (!NS_InputStreamIsBuffered(aInputStream)) {
  80. nsCOMPtr<nsIInputStream> bufStream;
  81. rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream),
  82. aInputStream, 1024);
  83. if (NS_SUCCEEDED(rv)) {
  84. inputStream = bufStream;
  85. }
  86. }
  87. // Figure out how much data we've been passed.
  88. uint64_t length;
  89. rv = inputStream->Available(&length);
  90. if (NS_FAILED(rv) || length > UINT32_MAX) {
  91. return nullptr;
  92. }
  93. // Write the data into a SourceBuffer.
  94. NotNull<RefPtr<SourceBuffer>> sourceBuffer = WrapNotNull(new SourceBuffer());
  95. sourceBuffer->ExpectLength(length);
  96. rv = sourceBuffer->AppendFromInputStream(inputStream, length);
  97. if (NS_FAILED(rv)) {
  98. return nullptr;
  99. }
  100. sourceBuffer->Complete(NS_OK);
  101. // Create a decoder.
  102. DecoderType decoderType =
  103. DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get());
  104. RefPtr<Decoder> decoder =
  105. DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
  106. Nothing(), ToSurfaceFlags(aFlags));
  107. if (!decoder) {
  108. return nullptr;
  109. }
  110. // Run the decoder synchronously.
  111. RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false);
  112. task->Run();
  113. if (!decoder->GetDecodeDone() || decoder->HasError()) {
  114. return nullptr;
  115. }
  116. // Pull out the surface.
  117. RawAccessFrameRef frame = decoder->GetCurrentFrameRef();
  118. if (!frame) {
  119. return nullptr;
  120. }
  121. RefPtr<SourceSurface> surface = frame->GetSourceSurface();
  122. if (!surface) {
  123. return nullptr;
  124. }
  125. return surface.forget();
  126. }
  127. } // namespace image
  128. } // namespace mozilla