Проблема с черными отверстиями на изображениях после применения моделирования дальнейшей слепоты в C# и ASMC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Проблема с черными отверстиями на изображениях после применения моделирования дальнейшей слепоты в C# и ASM

Сообщение Anonymous »

Я работаю над университетским проектом, в котором пытаюсь реализовать алгоритм, имитирующий различные типы дальтонизма (дейтеранопию, протанопию, тританопию) на изображениях. Цель состоит в том, чтобы преобразовать цветные изображения RGB (24 бита на пиксель), чтобы имитировать то, как они будут выглядеть для людей с различными типами цветовой слепоты.
К сожалению, после применения преобразований для протанопии и дейтеранопии Полученные изображения показывают черные дыры. Изображение выглядит почти черным с некоторыми странными искажениями, напоминающими «дыры». Я подозреваю, что что-то не так с преобразованиями или масштабированием каналов RGB, но не могу точно определить причину.
Описание проблемы:
Я использую C# для обработки изображений и файлового ввода-вывода.
Я написал ассемблерный код (ASM) для имитации преобразований дальтонизма.
После запуска моделирования обработанное изображение почти полностью черное с странные «дырчатые» области.
Что я пробовал:
  • Дважды проверил преобразования для каждой тип дальтонизма (дейтеранопия, протанопия).
  • Убедился, что значения RGB правильно рассчитаны и зафиксированы в диапазоне 0–255.
  • Проверено, что изображение загружается и сохраняется правильно в C#.
Код C#:
private void ProcessColorBlindnessAsm(int blindnessType)
{
if (_originalImage == null || _processedImage == null)
{
MessageBox.Show("Błąd: Image not loaded.");
return;
}

Rectangle rect = new Rectangle(0, 0, _originalImage.Width, _originalImage.Height);
BitmapData originalData = _originalImage.LockBits(rect, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
BitmapData processedData = _processedImage.LockBits(rect, ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

int pixelCount = _originalImage.Width * _originalImage.Height;
int stride = originalData.Stride;

IntPtr originalPtr = originalData.Scan0;
IntPtr processedPtr = processedData.Scan0;

try
{
Parallel.For(0, Environment.ProcessorCount, partition =>
{
int rowsPerPartition = _originalImage.Height / Environment.ProcessorCount;
int startRow = partition * rowsPerPartition;
int endRow = (partition == Environment.ProcessorCount - 1) ? _originalImage.Height : startRow + rowsPerPartition;

int partitionPixelCount = (endRow - startRow) * _originalImage.Width;
IntPtr originalPartitionPtr = IntPtr.Add(originalPtr, startRow * stride);
IntPtr processedPartitionPtr = IntPtr.Add(processedPtr, startRow * stride);

// Pass blindnessType to the ASM function
DeuteranopiaAsm(originalPartitionPtr, processedPartitionPtr, partitionPixelCount, stride, blindnessType);
});
}
catch (Exception ex)
{
MessageBox.Show($"Error while processing asm: {ex.Message}");
}
finally
{
_originalImage.UnlockBits(originalData);
_processedImage.UnlockBits(processedData);
}
}
< /code>
ASM Code: < /p>
.code
DeuteranopiaAsm proc

SimulateColorBlindnessASM:
; RCX = originalImage (pointer)
; RDX = processedImage (pointer)
; R8 = pixelCount (number of pixels)
; R9 = stride (bytes per row)
; R10 = blindnessType (0 = Deuteranopia, 1 = Protanopia, 2 = Tritanopia)

mov r11, rcx ; Save pointer to original image
mov r12, rdx ; Save pointer to processed image

xor rbx, rbx ; Use RBX as pixel counter

PixelLoop:
cmp rbx, r8 ; Check if all pixels are processed
jge EndLoop ; If rbx >= pixelCount, exit

mov rax, rbx ; Copy pixel counter to rax
shl rax, 1 ; rax = rbx * 2 (shift left by 1)
add rax, rbx ; rax = rax + rbx = rbx * 3

; Load color data (B, G, R)
mov al, byte ptr [r11 + rax] ; Load blue channel
mov cl, byte ptr [r11 + rax + 1] ; Load green channel
mov dl, byte ptr [r11 + rax + 2] ; Load red channel

; Select transformation based on blindnessType
cmp r10, 0 ; Check if Deuteranopia
je SimulateDeuteranopia
cmp r10, 1 ; Check if Protanopia
je SimulateProtanopia
cmp r10, 2 ; Check if Tritanopia
je SimulateTritanopia
jmp EndPixel ; Skip if invalid type

SimulateDeuteranopia:
; Transform for Deuteranopia
movzx r8d, dl ; Convert red channel to 32-bit
imul r8d, 625 ; R = R * 0.625
movzx r9d, cl ; Convert green channel to 32-bit
imul r9d, 375 ; G = G * 0.375
add r8d, r9d ; New Red = (R * 0.625 + G * 0.375)
shr r8d, 8 ; Divide by 256 to fit in byte range

; Green transformation (G = G * 0.7)
movzx r9d, cl ; Convert green channel to 32-bit
imul r9d, 700 ; G = G * 0.7
shr r9d, 10 ; Divide by 1024 to fit in byte range

; Blue transformation (B = B * 0.8)
movzx r10d, al ; Convert blue channel to 32-bit
imul r10d, 800 ; B = B * 0.8
shr r10d, 10 ; Divide by 1024 to fit in byte range

; Store processed pixel back into the image
mov byte ptr [r12 + rax], al ; Store blue channel
mov byte ptr [r12 + rax + 1], cl ; Store green channel
mov byte ptr [r12 + rax + 2], dl ; Store red channel

jmp EndPixel

SimulateProtanopia:
; Transform for Protanopia
movzx r8d, dl ; Convert red channel to 32-bit
imul r8d, 567 ; R = R * 0.567
movzx r9d, cl ; Convert green channel to 32-bit
imul r9d, 433 ; G = G * 0.433
add r8d, r9d ; New Red = (R * 0.567 + G * 0.433)
shr r8d, 8 ; Divide by 256

; Green transformation (G = G * 0.558)
movzx r9d, cl ; Convert green channel to 32-bit
imul r9d, 558 ; G = G * 0.558
shr r9d, 10 ; Divide by 1024 to fit in byte range

; Blue transformation (B = B * 0.0)
xor r10d, r10d ; Set blue channel to 0

; Store processed pixel back into the image
mov byte ptr [r12 + rax], al ; Store blue channel
mov byte ptr [r12 + rax + 1], cl ; Store green channel
mov byte ptr [r12 + rax + 2], dl ; Store red channel

jmp EndPixel

SimulateTritanopia:
; Transform for Tritanopia
movzx r8d, dl ; Convert red channel to 32-bit
imul r8d, 950 ; R = R * 0.95
movzx r9d, cl ; Convert green channel to 32-bit
imul r9d, 433 ; G = G * 0.433
add r8d, r9d ; New Red = (R * 0.95 + G * 0.433)
shr r8d, 8 ; Divide by 256

movzx r9d, cl ; Convert green channel to 32-bit
imul r9d, 433 ; G = G * 0.433
shr r9d, 10 ; Divide by 1024 to fit in byte range

; Blue transformation (B = B * 0.567)
movzx r10d, al ; Convert blue channel to 32-bit
imul r10d, 567 ; B = B * 0.567
shr r10d, 10 ; Divide by 1024 to fit in byte range

; Store processed pixel back into the image
mov byte ptr [r12 + rax], al ; Store blue channel
mov byte ptr [r12 + rax + 1], cl ; Store green channel
mov byte ptr [r12 + rax + 2], dl ; Store red channel

jmp EndPixel

EndPixel:
; Store processed pixel back into the image
mov byte ptr [r12 + rax], al ; Store blue channel
mov byte ptr [r12 + rax + 1], cl ; Store green channel
mov byte ptr [r12 + rax + 2], dl ; Store red channel

inc rbx ; Increment pixel counter
jmp PixelLoop ; Repeat for next pixel

EndLoop:
ret
DeuteranopiaAsm endp
end
< /code>
Можете ли вы мне помочь? = "https://i.sstatic.net/jtp9wmkf.png"/>
Как это должно выглядеть:

my asm output:


Подробнее здесь: https://stackoverflow.com/questions/792 ... ulation-in
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»