Пример #1
0
// Assumes that an initial valid guess of change rectangle 'rect' is passed.
static void MinimizeChangeRectangle(const WebPPicture* const src,
                                    const WebPPicture* const dst,
                                    FrameRect* const rect) {
  int i, j;
  // Sanity checks.
  assert(src->width == dst->width && src->height == dst->height);
  assert(rect->x_offset_ + rect->width_ <= dst->width);
  assert(rect->y_offset_ + rect->height_ <= dst->height);

  // Left boundary.
  for (i = rect->x_offset_; i < rect->x_offset_ + rect->width_; ++i) {
    const uint32_t* const src_argb =
        &src->argb[rect->y_offset_ * src->argb_stride + i];
    const uint32_t* const dst_argb =
        &dst->argb[rect->y_offset_ * dst->argb_stride + i];
    if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride,
                      rect->height_)) {
      --rect->width_;  // Redundant column.
      ++rect->x_offset_;
    } else {
      break;
    }
  }
  if (rect->width_ == 0) goto NoChange;

  // Right boundary.
  for (i = rect->x_offset_ + rect->width_ - 1; i >= rect->x_offset_; --i) {
    const uint32_t* const src_argb =
        &src->argb[rect->y_offset_ * src->argb_stride + i];
    const uint32_t* const dst_argb =
        &dst->argb[rect->y_offset_ * dst->argb_stride + i];
    if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride,
                      rect->height_)) {
      --rect->width_;  // Redundant column.
    } else {
      break;
    }
  }
  if (rect->width_ == 0) goto NoChange;

  // Top boundary.
  for (j = rect->y_offset_; j < rect->y_offset_ + rect->height_; ++j) {
    const uint32_t* const src_argb =
        &src->argb[j * src->argb_stride + rect->x_offset_];
    const uint32_t* const dst_argb =
        &dst->argb[j * dst->argb_stride + rect->x_offset_];
    if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width_)) {
      --rect->height_;  // Redundant row.
      ++rect->y_offset_;
    } else {
      break;
    }
  }
  if (rect->height_ == 0) goto NoChange;

  // Bottom boundary.
  for (j = rect->y_offset_ + rect->height_ - 1; j >= rect->y_offset_; --j) {
    const uint32_t* const src_argb =
        &src->argb[j * src->argb_stride + rect->x_offset_];
    const uint32_t* const dst_argb =
        &dst->argb[j * dst->argb_stride + rect->x_offset_];
    if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width_)) {
      --rect->height_;  // Redundant row.
    } else {
      break;
    }
  }
  if (rect->height_ == 0) goto NoChange;

  if (IsEmptyRect(rect)) {
 NoChange:
    rect->x_offset_ = 0;
    rect->y_offset_ = 0;
    rect->width_ = 0;
    rect->height_ = 0;
  }
}
Пример #2
0
// Compare rectangular region specified within an image and return number of pixels mismatching
size_t CompareImage(vx_image image, vx_rectangle_t * rectRegion, vx_uint8 * refImage, float errLimitMin, float errLimitMax, int frameNumber, const char * fileNameRef)
{
	// get number of planes, image format, and pixel type
	vx_df_image format = VX_DF_IMAGE_VIRT;
	vx_size num_planes = 0; vx_uint32 image_width = 0, image_height = 0;
	ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_WIDTH, &image_width, sizeof(image_width)));
	ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_HEIGHT, &image_height, sizeof(image_height)));
	ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_FORMAT, &format, sizeof(format)));
	ERROR_CHECK(vxQueryImage(image, VX_IMAGE_ATTRIBUTE_PLANES, &num_planes, sizeof(num_planes)));
	// set pixel type and compute frame size in bytes
	vx_enum pixelType = VX_TYPE_UINT8; // default
	if (format == VX_DF_IMAGE_S16) pixelType = VX_TYPE_INT16;
	else if (format == VX_DF_IMAGE_U16) pixelType = VX_TYPE_UINT16;
	else if (format == VX_DF_IMAGE_S32) pixelType = VX_TYPE_INT32;
	else if (format == VX_DF_IMAGE_U32) pixelType = VX_TYPE_UINT32;
	else if (format == VX_DF_IMAGE_F32_AMD || format == VX_DF_IMAGE_F32x3_AMD) pixelType = VX_TYPE_FLOAT32;
	// compare plane by plane
	vx_size errorPixelCountTotal = 0;
	vx_uint8 * pRefPlane = refImage;
	for (vx_uint32 plane = 0; plane < (vx_uint32)num_planes; plane++) {
		vx_imagepatch_addressing_t addr = { 0 };
		vx_uint8 * base_ptr = nullptr;
		ERROR_CHECK(vxAccessImagePatch(image, rectRegion, plane, &addr, (void **)&base_ptr, VX_READ_ONLY));
		vx_uint32 region_width = ((addr.dim_x * addr.scale_x) / VX_SCALE_UNITY);
		vx_uint32 region_height = (addr.dim_y * addr.scale_y) / VX_SCALE_UNITY;
		vx_uint32 plane_width = ((image_width * addr.scale_x) / VX_SCALE_UNITY);
		vx_uint32 plane_height = ((image_height * addr.scale_y) / VX_SCALE_UNITY);
		vx_uint32 plane_width_in_bytes = (format == VX_DF_IMAGE_U1_AMD) ? ((plane_width + 7) >> 3) : (plane_width * addr.stride_x);
		vx_uint32 start_x = ((rectRegion->start_x * addr.scale_x) / VX_SCALE_UNITY);
		vx_uint32 start_y = ((rectRegion->start_y * addr.scale_y) / VX_SCALE_UNITY);
		vx_uint8 * pRef = pRefPlane + start_y * plane_width_in_bytes + start_x * addr.stride_x;
		vx_size errorPixelCount = 0;
		if (pixelType == VX_TYPE_INT16) {
			errorPixelCount = ComparePixels((vx_int16 *)base_ptr, addr.stride_y, (vx_int16 *)pRef, plane_width_in_bytes, region_width, region_height, (vx_int32)errLimitMin, (vx_int32)errLimitMax);
		}
		else if (pixelType == VX_TYPE_UINT16) {
			errorPixelCount = ComparePixels((vx_uint16 *)base_ptr, addr.stride_y, (vx_uint16 *)pRef, plane_width_in_bytes, region_width, region_height, (vx_int32)errLimitMin, (vx_int32)errLimitMax);
		}
		else if (pixelType == VX_TYPE_INT32) {
			errorPixelCount = ComparePixels((vx_int32 *)base_ptr, addr.stride_y, (vx_int32 *)pRef, plane_width_in_bytes, region_width, region_height, (vx_int64)errLimitMin, (vx_int64)errLimitMax);
		}
		else if (pixelType == VX_TYPE_UINT32) {
			errorPixelCount = ComparePixels((vx_uint32 *)base_ptr, addr.stride_y, (vx_uint32 *)pRef, plane_width_in_bytes, region_width, region_height, (vx_int64)errLimitMin, (vx_int64)errLimitMax);
		}
		else if (pixelType == VX_TYPE_FLOAT32) {
			errorPixelCount = ComparePixels((vx_float32 *)base_ptr, addr.stride_y, (vx_float32 *)pRef, plane_width_in_bytes, region_width, region_height, (vx_float32)errLimitMin, (vx_float32)errLimitMax);
		}
		else if (format == VX_DF_IMAGE_U1_AMD) {
			errorPixelCount = ComparePixelsU001((vx_uint8 *)base_ptr, addr.stride_y, (vx_uint8 *)pRef, plane_width_in_bytes, region_width, region_height);
		}
		else {
			errorPixelCount = ComparePixels((vx_uint8 *)base_ptr, addr.stride_y, (vx_uint8 *)pRef, plane_width_in_bytes, region_width, region_height, (vx_int32)errLimitMin, (vx_int32)errLimitMax);
		}
		ERROR_CHECK(vxCommitImagePatch(image, rectRegion, plane, &addr, base_ptr));
		// report results
		errorPixelCountTotal += errorPixelCount;
		if (errorPixelCount > 0) {
			char name[64]; vxGetReferenceName((vx_reference)image, name, sizeof(name));
			printf("ERROR: Image COMPARE MISMATCHED %s plane#%d " VX_FMT_SIZE "-pixel(s) with frame#%d of %s\n", name, plane, errorPixelCount, frameNumber, fileNameRef ? fileNameRef : "???");
		}
		// skip to begnning of next plane
		pRefPlane += plane_height * plane_width_in_bytes;
	}
	return errorPixelCountTotal;
}
Пример #3
0
// Assumes that an initial valid guess of change rectangle 'rect' is passed.
static void MinimizeChangeRectangle(const WebPPicture* const src,
                                    const WebPPicture* const dst,
                                    WebPFrameRect* const rect) {
  int i, j;
  // Sanity checks.
  assert(src->width == dst->width && src->height == dst->height);
  assert(rect->x_offset + rect->width <= dst->width);
  assert(rect->y_offset + rect->height <= dst->height);

  // Left boundary.
  for (i = rect->x_offset; i < rect->x_offset + rect->width; ++i) {
    const uint32_t* const src_argb =
        &src->argb[rect->y_offset * src->argb_stride + i];
    const uint32_t* const dst_argb =
        &dst->argb[rect->y_offset * dst->argb_stride + i];
    if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride,
                      rect->height)) {
      --rect->width;  // Redundant column.
      ++rect->x_offset;
    } else {
      break;
    }
  }
  if (rect->width == 0) goto End;

  // Right boundary.
  for (i = rect->x_offset + rect->width - 1; i >= rect->x_offset; --i) {
    const uint32_t* const src_argb =
        &src->argb[rect->y_offset * src->argb_stride + i];
    const uint32_t* const dst_argb =
        &dst->argb[rect->y_offset * dst->argb_stride + i];
    if (ComparePixels(src_argb, src->argb_stride, dst_argb, dst->argb_stride,
                      rect->height)) {
      --rect->width;  // Redundant column.
    } else {
      break;
    }
  }
  if (rect->width == 0) goto End;

  // Top boundary.
  for (j = rect->y_offset; j < rect->y_offset + rect->height; ++j) {
    const uint32_t* const src_argb =
        &src->argb[j * src->argb_stride + rect->x_offset];
    const uint32_t* const dst_argb =
        &dst->argb[j * dst->argb_stride + rect->x_offset];
    if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width)) {
      --rect->height;  // Redundant row.
      ++rect->y_offset;
    } else {
      break;
    }
  }
  if (rect->height == 0) goto End;

  // Bottom boundary.
  for (j = rect->y_offset + rect->height - 1; j >= rect->y_offset; --j) {
    const uint32_t* const src_argb =
        &src->argb[j * src->argb_stride + rect->x_offset];
    const uint32_t* const dst_argb =
        &dst->argb[j * dst->argb_stride + rect->x_offset];
    if (ComparePixels(src_argb, 1, dst_argb, 1, rect->width)) {
      --rect->height;  // Redundant row.
    } else {
      break;
    }
  }
  if (rect->height == 0) goto End;

  if (rect->width == 0 || rect->height == 0) {
 End:
    // TODO(later): This rare case can happen for a bad GIF. In such a case, the
    // frame should not be encoded at all and the duration of prev frame should
    // be increased instead. For now, we just create a 1x1 frame at zero offset.
    rect->x_offset = 0;
    rect->y_offset = 0;
    rect->width = 1;
    rect->height = 1;
  }
}