Beispiel #1
0
		// Point-sampling U/V sampler.
		static int EmitSampledRGB(VP8Io* io, WebPDecParams* p) {
		  WebPDecBuffer* output = p.output;
		  WebPRGBABuffer* buf = &output.u.RGBA;
		  byte* dst = buf.rgba + io.mb_y * buf.stride;
		  byte* y_src = io.y;
		  byte* u_src = io.u;
		  byte* v_src = io.v;
		  WebPSampleLinePairFunc sample =
			  io.a ? WebPSamplersKeepAlpha[output.colorspace]
					: WebPSamplers[output.colorspace];
		  int mb_w = io.mb_w;
		  int last = io.mb_h - 1;
		  int j;
		  for (j = 0; j < last; j += 2) {
			sample(y_src, y_src + io.y_stride, u_src, v_src,
				   dst, dst + buf.stride, mb_w);
			y_src += 2 * io.y_stride;
			u_src += io.uv_stride;
			v_src += io.uv_stride;
			dst += 2 * buf.stride;
		  }
		  if (j == last) {  // Just do the last line twice
			sample(y_src, y_src, u_src, v_src, dst, dst, mb_w);
		  }
		  return io.mb_h;
		}
Beispiel #2
0
        //------------------------------------------------------------------------------
        // "Into" decoding variants
        // Main flow
        static VP8StatusCode DecodeInto(byte* data, uint data_size,
										WebPDecParams* params)
        {
            VP8Decoder* dec = VP8New();
              VP8StatusCode status = VP8_STATUS_OK;
              VP8Io io;

              assert(params);
              if (dec == null) {
            return VP8_STATUS_INVALID_PARAM;
              }

              VP8InitIo(&io);
              io.data = data;
              io.data_size = data_size;
              WebPInitCustomIo(params, &io);  // Plug the I/O functions.

            #if WEBP_USE_THREAD
              dec.use_threads_ = params.options && (params.options.use_threads > 0);
            #else
              dec.use_threads_ = 0;
            #endif

              // Decode bitstream header, update io.width/io.height.
              if (!VP8GetHeaders(dec, &io)) {
            status = VP8_STATUS_BITSTREAM_ERROR;
              } else {
            // Allocate/check output buffers.
            status = WebPAllocateDecBuffer(io.width, io.height, params.options,
                                           params.output);
            if (status == VP8_STATUS_OK) {
              // Decode
              if (!VP8Decode(dec, &io)) {
                status = dec.status_;
              }
            }
              }
              VP8Delete(dec);
              if (status != VP8_STATUS_OK) {
            WebPFreeDecBuffer(params.output);
              }
              return status;
        }
Beispiel #3
0
		//------------------------------------------------------------------------------
		// Main YUV<.RGB conversion functions

		static int EmitYUV(VP8Io* io, WebPDecParams* p) {
		  WebPDecBuffer* output = p.output;
		  WebPYUVABuffer* buf = &output.u.YUVA;
		  byte* y_dst = buf.y + io.mb_y * buf.y_stride;
		  byte* u_dst = buf.u + (io.mb_y >> 1) * buf.u_stride;
		  byte* v_dst = buf.v + (io.mb_y >> 1) * buf.v_stride;
		  int mb_w = io.mb_w;
		  int mb_h = io.mb_h;
		  int uv_w = (mb_w + 1) / 2;
		  int uv_h = (mb_h + 1) / 2;
		  int j;
		  for (j = 0; j < mb_h; ++j) {
			memcpy(y_dst + j * buf.y_stride, io.y + j * io.y_stride, mb_w);
		  }
		  for (j = 0; j < uv_h; ++j) {
			memcpy(u_dst + j * buf.u_stride, io.u + j * io.uv_stride, uv_w);
			memcpy(v_dst + j * buf.v_stride, io.v + j * io.uv_stride, uv_w);
		  }
		  return io.mb_h;
		}
Beispiel #4
0
		//------------------------------------------------------------------------------
		// YUV444 . RGB conversion

		#if false   // TODO(skal): this is for future rescaling.
		static int EmitRGB(VP8Io* io, WebPDecParams* p) {
		  WebPDecBuffer* output = p.output;
		  WebPRGBABuffer* buf = &output.u.RGBA;
		  byte* dst = buf.rgba + io.mb_y * buf.stride;
		  byte* y_src = io.y;
		  byte* u_src = io.u;
		  byte* v_src = io.v;
		  WebPYUV444Converter convert = WebPYUV444Converters[output.colorspace];
		  int mb_w = io.mb_w;
		  int last = io.mb_h;
		  int j;
		  for (j = 0; j < last; ++j) {
			convert(y_src, u_src, v_src, dst, mb_w);
			y_src += io.y_stride;
			u_src += io.uv_stride;
			v_src += io.uv_stride;
			dst += buf.stride;
		  }
		  return io.mb_h;
		}
Beispiel #5
0
		static int EmitRescaledRGB(VP8Io* io, WebPDecParams* p) {
		  int mb_h = io.mb_h;
		  int uv_mb_h = (mb_h + 1) >> 1;
		  int j = 0, uv_j = 0;
		  int num_lines_out = 0;
		  while (j < mb_h) {
			int y_lines_in = Import(io.y + j * io.y_stride, io.y_stride,
										  mb_h - j, &p.scaler_y);
			int u_lines_in = Import(io.u + uv_j * io.uv_stride, io.uv_stride,
										  uv_mb_h - uv_j, &p.scaler_u);
			int v_lines_in = Import(io.v + uv_j * io.uv_stride, io.uv_stride,
										  uv_mb_h - uv_j, &p.scaler_v);
			(void)v_lines_in;   // remove a gcc warning
			assert(u_lines_in == v_lines_in);
			j += y_lines_in;
			uv_j += u_lines_in;
			num_lines_out += ExportRGB(p, num_lines_out);
		  }
		  return num_lines_out;
		}
Beispiel #6
0
		//------------------------------------------------------------------------------
		// Fancy upsampling

		#if FANCY_UPSAMPLING
		static int EmitFancyRGB(VP8Io* io, WebPDecParams* p) {
		  int num_lines_out = io.mb_h;   // a priori guess
		  WebPRGBABuffer* buf = &p.output.u.RGBA;
		  byte* dst = buf.rgba + io.mb_y * buf.stride;
		  WebPUpsampleLinePairFunc upsample =
			  io.a ? WebPUpsamplersKeepAlpha[p.output.colorspace]
					: WebPUpsamplers[p.output.colorspace];
		  byte* cur_y = io.y;
		  byte* cur_u = io.u;
		  byte* cur_v = io.v;
		  byte* top_u = p.tmp_u;
		  byte* top_v = p.tmp_v;
		  int y = io.mb_y;
		  int y_end = io.mb_y + io.mb_h;
		  int mb_w = io.mb_w;
		  int uv_w = (mb_w + 1) / 2;

		  if (y == 0) {
			// First line is special cased. We mirror the u/v samples at boundary.
			upsample(null, cur_y, cur_u, cur_v, cur_u, cur_v, null, dst, mb_w);
		  } else {
			// We can finish the left-over line from previous call.
			// Warning! Don't overwrite the alpha values (if any), as they
			// are not lagging one line behind but are already written.
			upsample(p.tmp_y, cur_y, top_u, top_v, cur_u, cur_v,
					 dst - buf.stride, dst, mb_w);
			++num_lines_out;
		  }
		  // Loop over each output pairs of row.
		  for (; y + 2 < y_end; y += 2) {
			top_u = cur_u;
			top_v = cur_v;
			cur_u += io.uv_stride;
			cur_v += io.uv_stride;
			dst += 2 * buf.stride;
			cur_y += 2 * io.y_stride;
			upsample(cur_y - io.y_stride, cur_y,
					 top_u, top_v, cur_u, cur_v,
					 dst - buf.stride, dst, mb_w);
		  }
		  // move to last row
		  cur_y += io.y_stride;
		  if (io.crop_top + y_end < io.crop_bottom) {
			// Save the unfinished samples for next call (as we're not done yet).
			memcpy(p.tmp_y, cur_y, mb_w * sizeof(*p.tmp_y));
			memcpy(p.tmp_u, cur_u, uv_w * sizeof(*p.tmp_u));
			memcpy(p.tmp_v, cur_v, uv_w * sizeof(*p.tmp_v));
			// The fancy upsampler leaves a row unfinished behind
			// (except for the very last row)
			num_lines_out--;
		  } else {
			// Process the very last row of even-sized picture
			if (!(y_end & 1)) {
			  upsample(cur_y, null, cur_u, cur_v, cur_u, cur_v,
					  dst + buf.stride, null, mb_w);
			}
		  }
		  return num_lines_out;
		}
Beispiel #7
0
		//------------------------------------------------------------------------------
		// Main entry point

		void WebPInitCustomIo(WebPDecParams* params, VP8Io* io) {
		  io.put      = CustomPut;
		  io.setup    = CustomSetup;
		  io.teardown = CustomTeardown;
		  io.opaque   = params;
		}
Beispiel #8
0
		static int EmitRescaledAlphaRGB(VP8Io* io, WebPDecParams* p) {
		  if (io.a != null) {
			int (* output_func)(WebPDecParams* const, int) =
				(p.output.colorspace == MODE_RGBA_4444) ? ExportAlphaRGBA4444
														  : ExportAlpha;
			WebPRescaler* scaler = &p.scaler_a;
			int j = 0, pos = 0;
			while (j < io.mb_h) {
			  j += Import(io.a + j * io.width, io.width, io.mb_h - j, scaler);
			  pos += output_func(p, pos);
			}
		  }
		  return 0;
		}
Beispiel #9
0
		static int InitRGBRescaler(VP8Io* io, WebPDecParams* p) {
		  int has_alpha = IsAlphaMode(p.output.colorspace);
		  int out_width  = io.scaled_width;
		  int out_height = io.scaled_height;
		  int uv_in_width  = (io.mb_w + 1) >> 1;
		  int uv_in_height = (io.mb_h + 1) >> 1;
		  uint work_size = 2 * out_width;   // scratch memory for one rescaler
		  int* work;  // rescalers work area
		  byte* tmp;   // tmp storage for scaled YUV444 samples before RGB conversion
		  uint tmp_size1, tmp_size2;

		  tmp_size1 = 3 * work_size;
		  tmp_size2 = 3 * out_width;
		  if (has_alpha) {
			tmp_size1 += work_size;
			tmp_size2 += out_width;
		  }
		  p.memory =
			  calloc(1, tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp));
		  if (p.memory == null) {
			return 0;   // memory error
		  }
		  work = (int*)p.memory;
		  tmp = (byte*)(work + tmp_size1);
		  InitRescaler(&p.scaler_y, io.mb_w, io.mb_h,
					   tmp + 0 * out_width, out_width, out_height, 0,
					   io.mb_w, out_width, io.mb_h, out_height,
					   work + 0 * work_size);
		  InitRescaler(&p.scaler_u, uv_in_width, uv_in_height,
					   tmp + 1 * out_width, out_width, out_height, 0,
					   io.mb_w, 2 * out_width, io.mb_h, 2 * out_height,
					   work + 1 * work_size);
		  InitRescaler(&p.scaler_v, uv_in_width, uv_in_height,
					   tmp + 2 * out_width, out_width, out_height, 0,
					   io.mb_w, 2 * out_width, io.mb_h, 2 * out_height,
					   work + 2 * work_size);
		  p.emit = EmitRescaledRGB;

		  if (has_alpha) {
			InitRescaler(&p.scaler_a, io.mb_w, io.mb_h,
						 tmp + 3 * out_width, out_width, out_height, 0,
						 io.mb_w, out_width, io.mb_h, out_height,
						 work + 3 * work_size);
			p.emit_alpha = EmitRescaledAlphaRGB;
		  }
		  return 1;
		}
Beispiel #10
0
		// FANCY_UPSAMPLING 

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

		static int EmitAlphaYUV(VP8Io* io, WebPDecParams* p) {
		  byte* alpha = io.a;
		  if (alpha != null) {
			int j;
			int mb_w = io.mb_w;
			int mb_h = io.mb_h;
			WebPYUVABuffer* buf = &p.output.u.YUVA;
			byte* dst = buf.a + io.mb_y * buf.a_stride;
			for (j = 0; j < mb_h; ++j) {
			  memcpy(dst, alpha, mb_w * sizeof(*dst));
			  alpha += io.width;
			  dst += buf.a_stride;
			}
		  }
		  return 0;
		}
Beispiel #11
0
		static int ExportAlphaRGBA4444(WebPDecParams* p, int y_pos) {
		  WebPRGBABuffer* buf = &p.output.u.RGBA;
		  byte* dst = buf.rgba + (p.last_y + y_pos) * buf.stride + 1;
		  int num_lines_out = 0;
		  while (p.scaler_a.y_accum <= 0) {
			int i;
			assert(p.last_y + y_pos + num_lines_out < p.output.height);
			ExportRow(&p.scaler_a);
			for (i = 0; i < p.scaler_a.dst_width; ++i) {
			  // Fill in the alpha value (converted to 4 bits).
			  uint alpha_val = clip((p.scaler_a.dst[i] + 8) >> 4, 15);
			  dst[2 * i] = (dst[2 * i] & 0xf0) | alpha_val;
			}
			dst += buf.stride;
			++num_lines_out;
		  }
		  return num_lines_out;
		}
Beispiel #12
0
		static int ExportRGB(WebPDecParams* p, int y_pos) {
		  WebPYUV444Converter convert =
			  WebPYUV444Converters[p.output.colorspace];
		  WebPRGBABuffer* buf = &p.output.u.RGBA;
		  byte* dst = buf.rgba + (p.last_y + y_pos) * buf.stride;
		  int num_lines_out = 0;
		  // For RGB rescaling, because of the YUV420, current scan position
		  // U/V can be +1/-1 line from the Y one.  Hence the double test.
		  while (p.scaler_y.y_accum <= 0 && p.scaler_u.y_accum <= 0) {
			assert(p.last_y + y_pos + num_lines_out < p.output.height);
			assert(p.scaler_u.y_accum == p.scaler_v.y_accum);
			ExportRow(&p.scaler_y);
			ExportRow(&p.scaler_u);
			ExportRow(&p.scaler_v);
			convert(p.scaler_y.dst, p.scaler_u.dst, p.scaler_v.dst,
					dst, p.scaler_y.dst_width);
			dst += buf.stride;
			++num_lines_out;
		  }
		  return num_lines_out;
		}
Beispiel #13
0
 //------------------------------------------------------------------------------
 // WebPDecParams
 void WebPResetDecParams(WebPDecParams* params)
 {
     if (params) {
     memset(params, 0, sizeof(*params));
       }
 }
Beispiel #14
0
		static int InitYUVRescaler(VP8Io* io, WebPDecParams* p) {
		  int has_alpha = IsAlphaMode(p.output.colorspace);
		  WebPYUVABuffer* buf = &p.output.u.YUVA;
		  int out_width  = io.scaled_width;
		  int out_height = io.scaled_height;
		  int uv_out_width  = (out_width + 1) >> 1;
		  int uv_out_height = (out_height + 1) >> 1;
		  int uv_in_width  = (io.mb_w + 1) >> 1;
		  int uv_in_height = (io.mb_h + 1) >> 1;
		  uint work_size = 2 * out_width;   // scratch memory for luma rescaler
		  uint uv_work_size = 2 * uv_out_width;  // and for each u/v ones
		  uint tmp_size;
		  int* work;

		  tmp_size = work_size + 2 * uv_work_size;
		  if (has_alpha) {
			tmp_size += work_size;
		  }
		  p.memory = calloc(1, tmp_size * sizeof(*work));
		  if (p.memory == null) {
			return 0;   // memory error
		  }
		  work = (int*)p.memory;
		  InitRescaler(&p.scaler_y, io.mb_w, io.mb_h,
					   buf.y, out_width, out_height, buf.y_stride,
					   io.mb_w, out_width, io.mb_h, out_height,
					   work);
		  InitRescaler(&p.scaler_u, uv_in_width, uv_in_height,
					   buf.u, uv_out_width, uv_out_height, buf.u_stride,
					   uv_in_width, uv_out_width,
					   uv_in_height, uv_out_height,
					   work + work_size);
		  InitRescaler(&p.scaler_v, uv_in_width, uv_in_height,
					   buf.v, uv_out_width, uv_out_height, buf.v_stride,
					   uv_in_width, uv_out_width,
					   uv_in_height, uv_out_height,
					   work + work_size + uv_work_size);
		  p.emit = EmitRescaledYUV;
		  if (has_alpha) {
			InitRescaler(&p.scaler_a, io.mb_w, io.mb_h,
						 buf.a, out_width, out_height, buf.a_stride,
						 io.mb_w, out_width, io.mb_h, out_height,
						 work + work_size + 2 * uv_work_size);
			p.emit_alpha = EmitRescaledAlphaYUV;
		  }
		  return 1;
		}
Beispiel #15
0
		static int EmitAlphaRGB(VP8Io* io, WebPDecParams* p) {
		  int mb_w = io.mb_w;
		  int mb_h = io.mb_h;
		  int i, j;
		  WebPRGBABuffer* buf = &p.output.u.RGBA;
		  byte* dst = buf.rgba + io.mb_y * buf.stride +
						 (p.output.colorspace == MODE_ARGB ? 0 : 3);
		  byte* alpha = io.a;
		  if (alpha) {
			for (j = 0; j < mb_h; ++j) {
			  for (i = 0; i < mb_w; ++i) {
				dst[4 * i] = alpha[i];
			  }
			  alpha += io.width;
			  dst += buf.stride;
			}
		  }
		  return 0;
		}
Beispiel #16
0
		static int EmitRescaledAlphaYUV(VP8Io* io, WebPDecParams* p) {
		  if (io.a != null) {
			Rescale(io.a, io.width, io.mb_h, &p.scaler_a);
		  }
		  return 0;
		}
Beispiel #17
0
		static int EmitRescaledYUV(VP8Io* io, WebPDecParams* p) {
		  int mb_h = io.mb_h;
		  int uv_mb_h = (mb_h + 1) >> 1;
		  int num_lines_out = Rescale(io.y, io.y_stride, mb_h, &p.scaler_y);
		  Rescale(io.u, io.uv_stride, uv_mb_h, &p.scaler_u);
		  Rescale(io.v, io.uv_stride, uv_mb_h, &p.scaler_v);
		  return num_lines_out;
		}
Beispiel #18
0
		static int EmitAlphaRGBA4444(VP8Io* io, WebPDecParams* p) {
		  int mb_w = io.mb_w;
		  int mb_h = io.mb_h;
		  int i, j;
		  WebPRGBABuffer* buf = &p.output.u.RGBA;
		  byte* dst = buf.rgba + io.mb_y * buf.stride + 1;
		  byte* alpha = io.a;
		  if (alpha) {
			for (j = 0; j < mb_h; ++j) {
			  for (i = 0; i < mb_w; ++i) {
				// Fill in the alpha value (converted to 4 bits).
				uint alpha_val = clip((alpha[i] + 8) >> 4, 15);
				dst[2 * i] = (dst[2 * i] & 0xf0) | alpha_val;
			  }
			  alpha += io.width;
			  dst += buf.stride;
			}
		  }
		  return 0;
		}
Beispiel #19
0
        int VP8_FRAME_HEADER_SIZE = 10; // Size of the frame header within VP8 data.

        #endregion Fields

        #region Methods

        // Should be called first, before any use of the WebPDecParams object.
        void WebPResetDecParams(WebPDecParams* params);
Beispiel #20
0
		static int ExportAlpha(WebPDecParams* p, int y_pos) {
		  WebPRGBABuffer* buf = &p.output.u.RGBA;
		  byte* dst = buf.rgba + (p.last_y + y_pos) * buf.stride +
						 (p.output.colorspace == MODE_ARGB ? 0 : 3);
		  int num_lines_out = 0;
		  while (p.scaler_a.y_accum <= 0) {
			int i;
			assert(p.last_y + y_pos + num_lines_out < p.output.height);
			ExportRow(&p.scaler_a);
			for (i = 0; i < p.scaler_a.dst_width; ++i) {
			  dst[4 * i] = p.scaler_a.dst[i];
			}
			dst += buf.stride;
			++num_lines_out;
		  }
		  return num_lines_out;
		}