@@ -22,7 +22,7 @@ internal static class HorizontalPredictor
2222 /// <param name="pixelBytes">Buffer with decompressed pixel data.</param>
2323 /// <param name="width">The width of the image or strip.</param>
2424 /// <param name="colorType">The color type of the pixel data.</param>
25- /// <param name="isBigEndian">if set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
25+ /// <param name="isBigEndian">If set to <c>true</c> decodes the pixel data as big endian, otherwise as little endian.</param>
2626 public static void Undo ( Span < byte > pixelBytes , int width , TiffColorType colorType , bool isBigEndian )
2727 {
2828 switch ( colorType )
@@ -43,12 +43,21 @@ public static void Undo(Span<byte> pixelBytes, int width, TiffColorType colorTyp
4343 case TiffColorType . Rgb888 :
4444 UndoRgb24Bit ( pixelBytes , width ) ;
4545 break ;
46+ case TiffColorType . Rgba8888 :
47+ UndoRgba32Bit ( pixelBytes , width ) ;
48+ break ;
4649 case TiffColorType . Rgb161616 :
4750 UndoRgb48Bit ( pixelBytes , width , isBigEndian ) ;
4851 break ;
52+ case TiffColorType . Rgba16161616 :
53+ UndoRgba64Bit ( pixelBytes , width , isBigEndian ) ;
54+ break ;
4955 case TiffColorType . Rgb323232 :
5056 UndoRgb96Bit ( pixelBytes , width , isBigEndian ) ;
5157 break ;
58+ case TiffColorType . Rgba32323232 :
59+ UndoRgba128Bit ( pixelBytes , width , isBigEndian ) ;
60+ break ;
5261 }
5362 }
5463
@@ -243,6 +252,33 @@ private static void UndoRgb24Bit(Span<byte> pixelBytes, int width)
243252 }
244253 }
245254
255+ private static void UndoRgba32Bit ( Span < byte > pixelBytes , int width )
256+ {
257+ int rowBytesCount = width * 4 ;
258+ int height = pixelBytes . Length / rowBytesCount ;
259+ for ( int y = 0 ; y < height ; y ++ )
260+ {
261+ Span < byte > rowBytes = pixelBytes . Slice ( y * rowBytesCount , rowBytesCount ) ;
262+ Span < Rgba32 > rowRgb = MemoryMarshal . Cast < byte , Rgba32 > ( rowBytes ) . Slice ( 0 , width ) ;
263+ ref Rgba32 rowRgbBase = ref MemoryMarshal . GetReference ( rowRgb ) ;
264+ byte r = rowRgbBase . R ;
265+ byte g = rowRgbBase . G ;
266+ byte b = rowRgbBase . B ;
267+ byte a = rowRgbBase . A ;
268+
269+ for ( int x = 1 ; x < rowRgb . Length ; x ++ )
270+ {
271+ ref Rgba32 pixel = ref rowRgb [ x ] ;
272+ r += pixel . R ;
273+ g += pixel . G ;
274+ b += pixel . B ;
275+ a += pixel . A ;
276+ var rgb = new Rgba32 ( r , g , b , a ) ;
277+ pixel . FromRgba32 ( rgb ) ;
278+ }
279+ }
280+ }
281+
246282 private static void UndoRgb48Bit ( Span < byte > pixelBytes , int width , bool isBigEndian )
247283 {
248284 int rowBytesCount = width * 6 ;
@@ -319,6 +355,98 @@ private static void UndoRgb48Bit(Span<byte> pixelBytes, int width, bool isBigEnd
319355 }
320356 }
321357
358+ private static void UndoRgba64Bit ( Span < byte > pixelBytes , int width , bool isBigEndian )
359+ {
360+ int rowBytesCount = width * 8 ;
361+ int height = pixelBytes . Length / rowBytesCount ;
362+ if ( isBigEndian )
363+ {
364+ for ( int y = 0 ; y < height ; y ++ )
365+ {
366+ int offset = 0 ;
367+ Span < byte > rowBytes = pixelBytes . Slice ( y * rowBytesCount , rowBytesCount ) ;
368+ ushort r = TiffUtils . ConvertToUShortBigEndian ( rowBytes . Slice ( offset , 2 ) ) ;
369+ offset += 2 ;
370+ ushort g = TiffUtils . ConvertToUShortBigEndian ( rowBytes . Slice ( offset , 2 ) ) ;
371+ offset += 2 ;
372+ ushort b = TiffUtils . ConvertToUShortBigEndian ( rowBytes . Slice ( offset , 2 ) ) ;
373+ offset += 2 ;
374+ ushort a = TiffUtils . ConvertToUShortBigEndian ( rowBytes . Slice ( offset , 2 ) ) ;
375+ offset += 2 ;
376+
377+ for ( int x = 1 ; x < width ; x ++ )
378+ {
379+ Span < byte > rowSpan = rowBytes . Slice ( offset , 2 ) ;
380+ ushort deltaR = TiffUtils . ConvertToUShortBigEndian ( rowSpan ) ;
381+ r += deltaR ;
382+ BinaryPrimitives . WriteUInt16BigEndian ( rowSpan , r ) ;
383+ offset += 2 ;
384+
385+ rowSpan = rowBytes . Slice ( offset , 2 ) ;
386+ ushort deltaG = TiffUtils . ConvertToUShortBigEndian ( rowSpan ) ;
387+ g += deltaG ;
388+ BinaryPrimitives . WriteUInt16BigEndian ( rowSpan , g ) ;
389+ offset += 2 ;
390+
391+ rowSpan = rowBytes . Slice ( offset , 2 ) ;
392+ ushort deltaB = TiffUtils . ConvertToUShortBigEndian ( rowSpan ) ;
393+ b += deltaB ;
394+ BinaryPrimitives . WriteUInt16BigEndian ( rowSpan , b ) ;
395+ offset += 2 ;
396+
397+ rowSpan = rowBytes . Slice ( offset , 2 ) ;
398+ ushort deltaA = TiffUtils . ConvertToUShortBigEndian ( rowSpan ) ;
399+ a += deltaA ;
400+ BinaryPrimitives . WriteUInt16BigEndian ( rowSpan , a ) ;
401+ offset += 2 ;
402+ }
403+ }
404+ }
405+ else
406+ {
407+ for ( int y = 0 ; y < height ; y ++ )
408+ {
409+ int offset = 0 ;
410+ Span < byte > rowBytes = pixelBytes . Slice ( y * rowBytesCount , rowBytesCount ) ;
411+ ushort r = TiffUtils . ConvertToUShortLittleEndian ( rowBytes . Slice ( offset , 2 ) ) ;
412+ offset += 2 ;
413+ ushort g = TiffUtils . ConvertToUShortLittleEndian ( rowBytes . Slice ( offset , 2 ) ) ;
414+ offset += 2 ;
415+ ushort b = TiffUtils . ConvertToUShortLittleEndian ( rowBytes . Slice ( offset , 2 ) ) ;
416+ offset += 2 ;
417+ ushort a = TiffUtils . ConvertToUShortLittleEndian ( rowBytes . Slice ( offset , 2 ) ) ;
418+ offset += 2 ;
419+
420+ for ( int x = 1 ; x < width ; x ++ )
421+ {
422+ Span < byte > rowSpan = rowBytes . Slice ( offset , 2 ) ;
423+ ushort deltaR = TiffUtils . ConvertToUShortLittleEndian ( rowSpan ) ;
424+ r += deltaR ;
425+ BinaryPrimitives . WriteUInt16LittleEndian ( rowSpan , r ) ;
426+ offset += 2 ;
427+
428+ rowSpan = rowBytes . Slice ( offset , 2 ) ;
429+ ushort deltaG = TiffUtils . ConvertToUShortLittleEndian ( rowSpan ) ;
430+ g += deltaG ;
431+ BinaryPrimitives . WriteUInt16LittleEndian ( rowSpan , g ) ;
432+ offset += 2 ;
433+
434+ rowSpan = rowBytes . Slice ( offset , 2 ) ;
435+ ushort deltaB = TiffUtils . ConvertToUShortLittleEndian ( rowSpan ) ;
436+ b += deltaB ;
437+ BinaryPrimitives . WriteUInt16LittleEndian ( rowSpan , b ) ;
438+ offset += 2 ;
439+
440+ rowSpan = rowBytes . Slice ( offset , 2 ) ;
441+ ushort deltaA = TiffUtils . ConvertToUShortLittleEndian ( rowSpan ) ;
442+ a += deltaA ;
443+ BinaryPrimitives . WriteUInt16LittleEndian ( rowSpan , a ) ;
444+ offset += 2 ;
445+ }
446+ }
447+ }
448+ }
449+
322450 private static void UndoRgb96Bit ( Span < byte > pixelBytes , int width , bool isBigEndian )
323451 {
324452 int rowBytesCount = width * 12 ;
@@ -394,5 +522,97 @@ private static void UndoRgb96Bit(Span<byte> pixelBytes, int width, bool isBigEnd
394522 }
395523 }
396524 }
525+
526+ private static void UndoRgba128Bit ( Span < byte > pixelBytes , int width , bool isBigEndian )
527+ {
528+ int rowBytesCount = width * 16 ;
529+ int height = pixelBytes . Length / rowBytesCount ;
530+ if ( isBigEndian )
531+ {
532+ for ( int y = 0 ; y < height ; y ++ )
533+ {
534+ int offset = 0 ;
535+ Span < byte > rowBytes = pixelBytes . Slice ( y * rowBytesCount , rowBytesCount ) ;
536+ uint r = TiffUtils . ConvertToUIntBigEndian ( rowBytes . Slice ( offset , 4 ) ) ;
537+ offset += 4 ;
538+ uint g = TiffUtils . ConvertToUIntBigEndian ( rowBytes . Slice ( offset , 4 ) ) ;
539+ offset += 4 ;
540+ uint b = TiffUtils . ConvertToUIntBigEndian ( rowBytes . Slice ( offset , 4 ) ) ;
541+ offset += 4 ;
542+ uint a = TiffUtils . ConvertToUIntBigEndian ( rowBytes . Slice ( offset , 4 ) ) ;
543+ offset += 4 ;
544+
545+ for ( int x = 1 ; x < width ; x ++ )
546+ {
547+ Span < byte > rowSpan = rowBytes . Slice ( offset , 4 ) ;
548+ uint deltaR = TiffUtils . ConvertToUIntBigEndian ( rowSpan ) ;
549+ r += deltaR ;
550+ BinaryPrimitives . WriteUInt32BigEndian ( rowSpan , r ) ;
551+ offset += 4 ;
552+
553+ rowSpan = rowBytes . Slice ( offset , 4 ) ;
554+ uint deltaG = TiffUtils . ConvertToUIntBigEndian ( rowSpan ) ;
555+ g += deltaG ;
556+ BinaryPrimitives . WriteUInt32BigEndian ( rowSpan , g ) ;
557+ offset += 4 ;
558+
559+ rowSpan = rowBytes . Slice ( offset , 4 ) ;
560+ uint deltaB = TiffUtils . ConvertToUIntBigEndian ( rowSpan ) ;
561+ b += deltaB ;
562+ BinaryPrimitives . WriteUInt32BigEndian ( rowSpan , b ) ;
563+ offset += 4 ;
564+
565+ rowSpan = rowBytes . Slice ( offset , 4 ) ;
566+ uint deltaA = TiffUtils . ConvertToUIntBigEndian ( rowSpan ) ;
567+ a += deltaA ;
568+ BinaryPrimitives . WriteUInt32BigEndian ( rowSpan , a ) ;
569+ offset += 4 ;
570+ }
571+ }
572+ }
573+ else
574+ {
575+ for ( int y = 0 ; y < height ; y ++ )
576+ {
577+ int offset = 0 ;
578+ Span < byte > rowBytes = pixelBytes . Slice ( y * rowBytesCount , rowBytesCount ) ;
579+ uint r = TiffUtils . ConvertToUIntLittleEndian ( rowBytes . Slice ( offset , 4 ) ) ;
580+ offset += 4 ;
581+ uint g = TiffUtils . ConvertToUIntLittleEndian ( rowBytes . Slice ( offset , 4 ) ) ;
582+ offset += 4 ;
583+ uint b = TiffUtils . ConvertToUIntLittleEndian ( rowBytes . Slice ( offset , 4 ) ) ;
584+ offset += 4 ;
585+ uint a = TiffUtils . ConvertToUIntLittleEndian ( rowBytes . Slice ( offset , 4 ) ) ;
586+ offset += 4 ;
587+
588+ for ( int x = 1 ; x < width ; x ++ )
589+ {
590+ Span < byte > rowSpan = rowBytes . Slice ( offset , 4 ) ;
591+ uint deltaR = TiffUtils . ConvertToUIntLittleEndian ( rowSpan ) ;
592+ r += deltaR ;
593+ BinaryPrimitives . WriteUInt32LittleEndian ( rowSpan , r ) ;
594+ offset += 4 ;
595+
596+ rowSpan = rowBytes . Slice ( offset , 4 ) ;
597+ uint deltaG = TiffUtils . ConvertToUIntLittleEndian ( rowSpan ) ;
598+ g += deltaG ;
599+ BinaryPrimitives . WriteUInt32LittleEndian ( rowSpan , g ) ;
600+ offset += 4 ;
601+
602+ rowSpan = rowBytes . Slice ( offset , 4 ) ;
603+ uint deltaB = TiffUtils . ConvertToUIntLittleEndian ( rowSpan ) ;
604+ b += deltaB ;
605+ BinaryPrimitives . WriteUInt32LittleEndian ( rowSpan , b ) ;
606+ offset += 4 ;
607+
608+ rowSpan = rowBytes . Slice ( offset , 4 ) ;
609+ uint deltaA = TiffUtils . ConvertToUIntLittleEndian ( rowSpan ) ;
610+ a += deltaA ;
611+ BinaryPrimitives . WriteUInt32LittleEndian ( rowSpan , a ) ;
612+ offset += 4 ;
613+ }
614+ }
615+ }
616+ }
397617 }
398618}
0 commit comments