Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/media/libwebp/src/enc/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  picture_rescale_enc.c   Sprache: C

 
// Copyright 2014 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// WebPPicture tools: copy, crop, rescaling and view.
//
// Author: Skal (pascal.massimino@gmail.com)

#include "src/webp/encode.h"

#include <assert.h>
#include <stdlib.h>

#include "src/enc/vp8i_enc.h"

#if !defined(WEBP_REDUCE_SIZE)
#include "src/utils/rescaler_utils.h"
#include "src/utils/utils.h"
#endif  // !defined(WEBP_REDUCE_SIZE)

#define HALVE(x) (((x) + 1) >> 1)

// Grab the 'specs' (writer, *opaque, width, height...) from 'src' and copy them
// into 'dst'. Mark 'dst' as not owning any memory.
static void PictureGrabSpecs(const WebPPicture* const src,
                             WebPPicture* const dst) {
  assert(src != NULL && dst != NULL);
  *dst = *src;
  WebPPictureResetBuffers(dst);
}

//------------------------------------------------------------------------------

// Adjust top-left corner to chroma sample position.
static void SnapTopLeftPosition(const WebPPicture* const pic,
                                intconst left, intconst top) {
  if (!pic->use_argb) {
    *left &= ~1;
    *top &= ~1;
  }
}

// Adjust top-left corner and verify that the sub-rectangle is valid.
static int AdjustAndCheckRectangle(const WebPPicture* const pic,
                                   intconst left, intconst top,
                                   int width, int height) {
  SnapTopLeftPosition(pic, left, top);
  if ((*left) < 0 || (*top) < 0) return 0;
  if (width <= 0 || height <= 0) return 0;
  if ((*left) + width > pic->width) return 0;
  if ((*top) + height > pic->height) return 0;
  return 1;
}

#if !defined(WEBP_REDUCE_SIZE)
int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) {
  if (src == NULL || dst == NULL) return 0;
  if (src == dst) return 1;

  PictureGrabSpecs(src, dst);
  if (!WebPPictureAlloc(dst)) return 0;

  if (!src->use_argb) {
    WebPCopyPlane(src->y, src->y_stride,
                  dst->y, dst->y_stride, dst->width, dst->height);
    WebPCopyPlane(src->u, src->uv_stride, dst->u, dst->uv_stride,
                  HALVE(dst->width), HALVE(dst->height));
    WebPCopyPlane(src->v, src->uv_stride, dst->v, dst->uv_stride,
                  HALVE(dst->width), HALVE(dst->height));
    if (dst->a != NULL)  {
      WebPCopyPlane(src->a, src->a_stride,
                    dst->a, dst->a_stride, dst->width, dst->height);
    }
  } else {
    WebPCopyPlane((const uint8_t*)src->argb, 4 * src->argb_stride,
                  (uint8_t*)dst->argb, 4 * dst->argb_stride,
                  4 * dst->width, dst->height);
  }
  return 1;
}
#endif  // !defined(WEBP_REDUCE_SIZE)

int WebPPictureIsView(const WebPPicture* picture) {
  if (picture == NULL) return 0;
  if (picture->use_argb) {
    return (picture->memory_argb_ == NULL);
  }
  return (picture->memory_ == NULL);
}

int WebPPictureView(const WebPPicture* src,
                    int left, int top, int width, int height,
                    WebPPicture* dst) {
  if (src == NULL || dst == NULL) return 0;

  // verify rectangle position.
  if (!AdjustAndCheckRectangle(src, &left, &top, width, height)) return 0;

  if (src != dst) {  // beware of aliasing! We don't want to leak 'memory_'.
    PictureGrabSpecs(src, dst);
  }
  dst->width = width;
  dst->height = height;
  if (!src->use_argb) {
    dst->y = src->y + top * src->y_stride + left;
    dst->u = src->u + (top >> 1) * src->uv_stride + (left >> 1);
    dst->v = src->v + (top >> 1) * src->uv_stride + (left >> 1);
    dst->y_stride = src->y_stride;
    dst->uv_stride = src->uv_stride;
    if (src->a != NULL) {
      dst->a = src->a + top * src->a_stride + left;
      dst->a_stride = src->a_stride;
    }
  } else {
    dst->argb = src->argb + top * src->argb_stride + left;
    dst->argb_stride = src->argb_stride;
  }
  return 1;
}

#if !defined(WEBP_REDUCE_SIZE)
//------------------------------------------------------------------------------
// Picture cropping

int WebPPictureCrop(WebPPicture* pic,
                    int left, int top, int width, int height) {
  WebPPicture tmp;

  if (pic == NULL) return 0;
  if (!AdjustAndCheckRectangle(pic, &left, &top, width, height)) return 0;

  PictureGrabSpecs(pic, &tmp);
  tmp.width = width;
  tmp.height = height;
  if (!WebPPictureAlloc(&tmp)) {
    return WebPEncodingSetError(pic, tmp.error_code);
  }

  if (!pic->use_argb) {
    const int y_offset = top * pic->y_stride + left;
    const int uv_offset = (top / 2) * pic->uv_stride + left / 2;
    WebPCopyPlane(pic->y + y_offset, pic->y_stride,
                  tmp.y, tmp.y_stride, width, height);
    WebPCopyPlane(pic->u + uv_offset, pic->uv_stride,
                  tmp.u, tmp.uv_stride, HALVE(width), HALVE(height));
    WebPCopyPlane(pic->v + uv_offset, pic->uv_stride,
                  tmp.v, tmp.uv_stride, HALVE(width), HALVE(height));

    if (tmp.a != NULL) {
      const int a_offset = top * pic->a_stride + left;
      WebPCopyPlane(pic->a + a_offset, pic->a_stride,
                    tmp.a, tmp.a_stride, width, height);
    }
  } else {
    const uint8_t* const src =
        (const uint8_t*)(pic->argb + top * pic->argb_stride + left);
    WebPCopyPlane(src, pic->argb_stride * 4, (uint8_t*)tmp.argb,
                  tmp.argb_stride * 4, width * 4, height);
  }
  WebPPictureFree(pic);
  *pic = tmp;
  return 1;
}

//------------------------------------------------------------------------------
// Simple picture rescaler

static int RescalePlane(const uint8_t* src,
                        int src_width, int src_height, int src_stride,
                        uint8_t* dst,
                        int dst_width, int dst_height, int dst_stride,
                        rescaler_t* const work,
                        int num_channels) {
  WebPRescaler rescaler;
  int y = 0;
  if (!WebPRescalerInit(&rescaler, src_width, src_height,
                        dst, dst_width, dst_height, dst_stride,
                        num_channels, work)) {
    return 0;
  }
  while (y < src_height) {
    y += WebPRescalerImport(&rescaler, src_height - y,
                            src + y * src_stride, src_stride);
    WebPRescalerExport(&rescaler);
  }
  return 1;
}

static void AlphaMultiplyARGB(WebPPicture* const pic, int inverse) {
  assert(pic->argb != NULL);
  WebPMultARGBRows((uint8_t*)pic->argb, pic->argb_stride * sizeof(*pic->argb),
                   pic->width, pic->height, inverse);
}

static void AlphaMultiplyY(WebPPicture* const pic, int inverse) {
  if (pic->a != NULL) {
    WebPMultRows(pic->y, pic->y_stride, pic->a, pic->a_stride,
                 pic->width, pic->height, inverse);
  }
}

int WebPPictureRescale(WebPPicture* picture, int width, int height) {
  WebPPicture tmp;
  int prev_width, prev_height;
  rescaler_t* work;

  if (picture == NULL) return 0;
  prev_width = picture->width;
  prev_height = picture->height;
  if (!WebPRescalerGetScaledDimensions(
          prev_width, prev_height, &width, &height)) {
    return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
  }

  PictureGrabSpecs(picture, &tmp);
  tmp.width = width;
  tmp.height = height;
  if (!WebPPictureAlloc(&tmp)) {
    return WebPEncodingSetError(picture, tmp.error_code);
  }

  if (!picture->use_argb) {
    work = (rescaler_t*)WebPSafeMalloc(2ULL * width, sizeof(*work));
    if (work == NULL) {
      WebPPictureFree(&tmp);
      return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
    }
    // If present, we need to rescale alpha first (for AlphaMultiplyY).
    if (picture->a != NULL) {
      WebPInitAlphaProcessing();
      if (!RescalePlane(picture->a, prev_width, prev_height, picture->a_stride,
                        tmp.a, width, height, tmp.a_stride, work, 1)) {
        return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
      }
    }

    // We take transparency into account on the luma plane only. That's not
    // totally exact blending, but still is a good approximation.
    AlphaMultiplyY(picture, 0);
    if (!RescalePlane(picture->y, prev_width, prev_height, picture->y_stride,
                      tmp.y, width, height, tmp.y_stride, work, 1) ||
        !RescalePlane(picture->u, HALVE(prev_width), HALVE(prev_height),
                      picture->uv_stride, tmp.u, HALVE(width), HALVE(height),
                      tmp.uv_stride, work, 1) ||
        !RescalePlane(picture->v, HALVE(prev_width), HALVE(prev_height),
                      picture->uv_stride, tmp.v, HALVE(width), HALVE(height),
                      tmp.uv_stride, work, 1)) {
      return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
    }
    AlphaMultiplyY(&tmp, 1);
  } else {
    work = (rescaler_t*)WebPSafeMalloc(2ULL * width * 4, sizeof(*work));
    if (work == NULL) {
      WebPPictureFree(&tmp);
      return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
    }
    // In order to correctly interpolate colors, we need to apply the alpha
    // weighting first (black-matting), scale the RGB values, and remove
    // the premultiplication afterward (while preserving the alpha channel).
    WebPInitAlphaProcessing();
    AlphaMultiplyARGB(picture, 0);
    if (!RescalePlane((const uint8_t*)picture->argb, prev_width, prev_height,
                      picture->argb_stride * 4, (uint8_t*)tmp.argb, width,
                      height, tmp.argb_stride * 4, work, 4)) {
      return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
    }
    AlphaMultiplyARGB(&tmp, 1);
  }
  WebPPictureFree(picture);
  WebPSafeFree(work);
  *picture = tmp;
  return 1;
}

#else  // defined(WEBP_REDUCE_SIZE)

int WebPPictureCopy(const WebPPicture* src, WebPPicture* dst) {
  (void)src;
  (void)dst;
  return 0;
}

int WebPPictureCrop(WebPPicture* pic,
                    int left, int top, int width, int height) {
  (void)pic;
  (void)left;
  (void)top;
  (void)width;
  (void)height;
  return 0;
}

int WebPPictureRescale(WebPPicture* pic, int width, int height) {
  (void)pic;
  (void)width;
  (void)height;
  return 0;
}
#endif  // !defined(WEBP_REDUCE_SIZE)

Messung V0.5
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.