public static void TransformPlanar(Image src, Image dst, Codec.TransformationQuality quality) { //Source is planar RGB //1x4 image // RRRR // GGGG // BBBB }
public static void TransformSemiPlanar(Image src, Image dst, Codec.TransformationQuality quality) { //Source is semi planar RGB???? //1x4 image // RRRR // GBGB // GBGB }
/// <summary> /// /// </summary> /// <param name="source"></param> /// <param name="dest"></param> /// <param name="quality"></param> /// <param name="shouldDispose"></param> public AudioTransformation(AudioBuffer source, AudioBuffer dest, Codec.TransformationQuality quality = Codec.TransformationQuality.Unspecified, bool shouldDispose = true) : this(quality, shouldDispose) { if (Common.IDisposedExtensions.IsNullOrDisposed(source)) { throw new System.ArgumentNullException("source"); } m_Source = source; if (Common.IDisposedExtensions.IsNullOrDisposed(dest)) { throw new System.ArgumentNullException("dest"); } m_Dest = dest; }
/// <summary> /// /// </summary> /// <param name="quality"></param> /// <param name="shouldDispose"></param> protected AudioTransformation(Codec.TransformationQuality quality = Codec.TransformationQuality.Unspecified, bool shouldDispose = true) : base(Codec.MediaType.Audio, quality, shouldDispose) { }
public static void TransformPacked(Image src, Image dst, Codec.TransformationQuality quality) { //Source is packed RGB in any possible format //For example a 1x4 image assuming 8 bpp //RGB // RGBR // GBRG // BRGB //ARGB // ARGB // ARGB // ARGB // ARGB //BGRA // BGRA // BGRA // BGRA // BGRA //Some other format... with or without equal bit sizes for the alpha or other components. //Not the alpha component may have less bits than the others // BRAG // BRAG // BRAG // BRAG //Another hypothetical format.. // GRAB // GRAB // GRAB // GRAB //Scope references to the data Common.MemorySegment source = src.Data, dest = dst.Data; //Create cache of 3 8 bit RGB values * 4 pixels //byte[] cache = new byte[12]; //Setup variables int offChr = 0, offLuma = 0, offSrc = 0, strideSrc = src.Width * src.ImageFormat.Length, strideDst = dst.Width, dstComponentOffset = dst.MediaFormat.Length; //Could probably handle packed or semi planar YUV by making a small offset change if (dst.ImageFormat.DataLayout == Codec.DataLayout.Packed || dst.ImageFormat.DataLayout == Codec.DataLayout.SemiPlanar) { strideDst = dst.MediaFormat.Length; dstComponentOffset = 1; } //Should also have a way to write the components of dst //Keeps the offset in bits of the current byte //int bitOffset = 0; //1 pixel images... //Should actualy use width or height and check after each operation //Should definitely use PlaneHeight of the source to determine if Upsamlping is needed? //E.g. 4:1:1 RGB to 4:2:0 YUV //Although I am not sure how you would have 4:1:1 rgb, it would just be different size R, B and G Components... int halfHeight = src.Height >> 1, halfWidth = src.Width >> 1; //Do in parallel Parallel.For(0, halfHeight, (i) => { Parallel.For(0, halfWidth, (j) => { //Use local variables based on i and j. //Create cache of 3 8 bit RGB values * 4 pixels byte[] cache = new byte[12]; int currentLuma = i * j, currentChroma = src.Height + halfHeight + j, currentSrc = i + j * src.ImageFormat.Length, currentBsrc = i + j * src.ImageFormat.Size % Common.Binary.BitsPerByte; //Read and convert component ReadAndConvertRGBComponentsToYUV(src, ref currentSrc, ref currentBsrc, cache, 0); //if (++j >= src.Width) break; //Write Luma dest[currentLuma] = cache[0]; //Read and convert component ReadAndConvertRGBComponentsToYUV(src, ref currentSrc, ref currentBsrc, cache, 3); //Write Luma and move offset dest[currentLuma++ + strideDst] = cache[3]; //Read and convert component ReadAndConvertRGBComponentsToYUV(src, ref currentSrc, ref currentBsrc, cache, 6); //Write Luma dest[currentLuma] = cache[6]; //Read and convert component ReadAndConvertRGBComponentsToYUV(src, ref currentSrc, ref currentBsrc, cache, 9); //Write Luma and move offset dest[currentLuma++ + strideDst] = cache[9]; //If dest is not sub sampled then just write the components... //Otherwise this will need to ensure its taking the correct amount of components for the dest SubSampling. //Also needs to write in the correct plane, this assumes YUV, needs to actually write in the correct order. //Needs Common.Binary.WriteBinaryInteger //Determine how to write the Chroma data depending on the SubSampling. switch (dst.ImageFormat.Widths[1]) { //No plane data case -1: break; case 0: //No sub sampling in plane 1, components map 1 : 1 { //Needs to be written to the correct offset, this assumes YUV //Cb dest[currentChroma++] = cache[1]; dest[currentChroma + dstComponentOffset] = cache[4]; //Cr dest[currentChroma++] = cache[7]; dest[currentChroma + dstComponentOffset] = cache[10]; break; } case 1: //Half samples in plane 1, components map 1 : 2 { //Write averaged Chroma Major dest[currentChroma] = AverageCb(cache, quality); //Write averaged Chroma Minor dest[currentChroma + dstComponentOffset] = AverageCr(cache, quality); //Move the Chroma offset ++offChr; break; } case 2: //Quarter samples in plane 1, components map 4 : 1 { byte average = (byte)(AverageCb(cache, quality) + AverageCr(cache, quality)); if (average > 0) { average >>= 1; } //Write averaged Chroma value dest[currentChroma++] = average; //Move the Chroma offset ++currentChroma; break; } } }); }); ////Loop half height //for (int i = 0, ie = src.Height >> 1; i < ie; ++i) //{ // //Loop for half width // for (int j = 0, je = src.Width >> 1; j < je; ++j) // { // //Read and convert component // ReadAndConvertRGBComponentsToYUV(src, ref offSrc, ref bitOffset, cache, 0); // //if (++j >= src.Width) break; // //Write Luma // dest[offLuma] = cache[0]; // //Read and convert component // ReadAndConvertRGBComponentsToYUV(src, ref offSrc, ref bitOffset, cache, 3); // //Write Luma and move offset // dest[offLuma++ + strideDst] = cache[3]; // //Read and convert component // ReadAndConvertRGBComponentsToYUV(src, ref offSrc, ref bitOffset, cache, 6); // //Write Luma // dest[offLuma] = cache[6]; // //Read and convert component // ReadAndConvertRGBComponentsToYUV(src, ref offSrc, ref bitOffset, cache, 9); // //Write Luma and move offset // dest[offLuma++ + strideDst] = cache[9]; // //If dest is not sub sampled then just write the components... // //Otherwise this will need to ensure its taking the correct amount of components for the dest SubSampling. // //Also needs to write in the correct plane, this assumes YUV, needs to actually write in the correct order. // //Needs Common.Binary.WriteBinaryInteger // //Determine how to write the Chroma data depending on the SubSampling. // switch (dst.ImageFormat.Widths[1]) // { // //No plane data // case -1: break; // case 0: //No sub sampling in plane 1, components map 1 : 1 // { // //Needs to be written to the correct offset, this assumes YUV // //Cb // dest[offChr++] = cache[1]; // dest[offChr + dstComponentOffset] = cache[4]; // //Cr // dest[offChr++] = cache[7]; // dest[offChr + dstComponentOffset] = cache[10]; // break; // } // case 1: //Half samples in plane 1, components map 1 : 2 // { // //Write averaged Chroma Major // dest[offChr] = AverageCb(cache, quality); // //Write averaged Chroma Minor // dest[offChr + dstComponentOffset] = AverageCr(cache, quality); // //Move the Chroma offset // ++offChr; // break; // } // case 2: //Quarter samples in plane 1, components map 4 : 1 // { // byte average = (byte)(AverageCb(cache, quality) + AverageCr(cache, quality)); // if (average > 0) average >>= 1; // //Write averaged Chroma value // dest[offChr++] = average; // //Move the Chroma offset // ++offChr; // break; // } // } // } // //should only be done when dst.ImageFormat is Planar!!! // //Move the Luma offset // offLuma += strideDst; //} //cache = null; source = dest = null; }