Тёмная тема
Вот рабочий код декомпрессии RLE24 под Win64:
type PRGB24 = ^TRGB24; TRGB24 = packed record R, G, B: Byte; end; procedure StoreRGB24(ADest, ACount: QWord; AValue: TRGB24); asm .NOFRAME //ADest - rcx //ACount - rdx //AValue - r8 mov r10b, byte ptr [AValue] //R mov r11w, word ptr [AValue + 1] //G+B @N: mov byte ptr [ADest], r10b //R mov word ptr [ADest + 1], r11w //G+B add ADest, 3 dec ACount jnz @N end; function DecompressRLE24( ASrc, ADest: QWord; PackedSize, UnpackedSize: QWord): QWord; var NumBytes: QWord; Count: Byte; begin Result := 0; while ( Result <> UnpackedSize) do begin Count := PByte( ASrc)^; Inc( ASrc); //Смещение к цвету //RLE-пакет if ( Count >= 128) then begin //Кол-во повторений Count := ( Count and 127) + 1; //Пишем цепочку одинаковых значений StoreRGB24( ADest + Result, Count, PRGB24( ASrc)^); Inc( ASrc, 3); //Смещение к следующему пакету //Размер распакованных данных Inc( Result, Count * 3); if ( Result > UnpackedSize) then Exit( 0); end else //RAW-пакет begin //Байтов в строке NumBytes := ( Count + 1) * 3; MoveBytes( ASrc, ADest + Result, NumBytes); //Смещение к следующему пакету Inc( ASrc, NumBytes); //Кол-во распакованных байт Inc( Result, NumBytes); if ( Result > UnpackedSize) then Exit( 0); end; end;//while end;
Надеюсь по образцу вам не составит труда сделать код для 32-х бит и 8-и бит.
А вот код компрессии RLE24 под Win64:
type Ptr = Pointer; function RGB24_Equal(ASrc, ADest: Pointer): Boolean; asm .NOFRAME xor al, al mov r10b, byte ptr [ASrc] mov r11b, byte ptr [ADest] cmp r10b, r11b je @N ret @N: mov r10w, word ptr [ASrc + 1] mov r11w, word ptr [ADest + 1] cmp r10w, r11w je @Equal ret @Equal: mov al, 1 end; function CompressRLE24( const ASrc, ADest, AWidth: QWord): QWord; var SrcOffset: QWord; DestOffset: QWord; ChainStart: QWord; C3: QWord; ProcessedPixels: QWord; Count: Byte; EndLine: Boolean; Pixel: TRGB24; PixelPtr: Pointer; const MaxLen: Byte = 128; //Максимальная длина цепочки begin Count := 0; //Счетчик повторений Result := 0; //Кол-во байт после компрессии SrcOffset := 0; //Смещение в упакованном массиве DestOffset := 0; //Смещение в распакованном массиве ProcessedPixels := 0; //Счетчик обработанных байтов EndLine := False; //Флаг окончания строки PixelPtr := @Pixel; while ( ProcessedPixels <> AWidth) do begin //Адрес начала цепочки ChainStart := ( ASrc + SrcOffset); //Текущий пиксел - начало цепочки Pixel := PRGB24( ChainStart)^; //Смещение в сканлинии Inc( SrcOffset, 3); //Кол-во пикселов в цепочке Count := 1; //В конце строки может остаться всего 1 байт! if ( ProcessedPixels + Count) = AWidth then begin //Пишем счетчик PByte( ADest + DestOffset)^ := ( Count - 1); //Смещаемся после счетчика Inc( DestOffset); //Пишем один RAW-пиксел PRGB24( ADest + DestOffset)^ := Pixel; //Смещаемся после записи строки Inc( DestOffset, 3); //Кол-во упакованных данных Inc( Result, 4); //Общий счетчик байтов Inc( ProcessedPixels, Count); //Т.к. конец строки - выходим Continue; end; //RAW-данные if not RGB24_Equal( PixelPtr, Ptr( ASrc + SrcOffset)) then begin //Считаем пока байт не начнет повторяться while not RGB24_Equal( PixelPtr, Ptr( ASrc + SrcOffset)) do begin //Длина цепочки не может быть больше MaxLen if ( Count = MaxLen) or ( Count = AWidth) then Break; //Текущий равен следующему Pixel := PRGB24( ASrc + SrcOffset)^; //Смещение в сканлинии Inc( SrcOffset, 3); //Кол-во пикселей в цепочке Inc( Count); //Проверка на превышение длины строки if ( ProcessedPixels + Count) = AWidth then begin EndLine := True; //Конец строки Break; //Прервем цикл поиска end; end; //Если не конец линии if ( not EndLine) then begin //Исключаем 1 байт, т.к. он начал повторятся и это RLE-цепочка Dec( Count); //Т.к. исключили байт, то SrcOffset смещаем на 1 пиксел назад Dec( SrcOffset, 3); end; //Пишем счетчик PByte( ADest + DestOffset)^ := ( Count - 1); //Смещаемся после счетчика Inc( DestOffset); //Оптимизация C3 := ( Count * 3); //Пишем RAW-цепочку MoveBytes( ChainStart, ADest + DestOffset, C3); //Смещаемся после записи строки Inc( DestOffset, C3); //Кол-во упакованных данных Inc( Result, C3 + 1); //Общий счетчик пикселей Inc( ProcessedPixels, Count); end else //RLE-данные begin //Считаем пока байт повторяется while RGB24_Equal( PixelPtr, Ptr( ASrc + SrcOffset)) do begin //Длина цепочки не может быть больше MaxLen if ( Count = MaxLen) or ( Count = AWidth) then Break; //Смещение в сканлинии Inc( SrcOffset, 3); //Кол-во байт в цепочке Inc( Count); //Проверка на превышение длины строки if ( ProcessedPixels + Count) = AWidth then Break; end; //Пишем счетчик PByte( ADest + DestOffset)^ := MaxLen + ( Count - 1); //Смещаемся после счетчика Inc( DestOffset); //Пишем RLE-пиксел PRGB24( ADest + DestOffset)^ := Pixel; //Смещаемся после RLE-байта Inc( DestOffset, 3); //Кол-во упакованных данных Inc( Result, 4); //Счетчик обработанных байтов Inc( ProcessedPixels, Count); end; end; end;
Тема в архиве.