0

我是这个社区的新手。我们在大学里编程 mips,我需要一个解决我作业中的问题的方法。我们必须打开一个 .pgm 文件并读取所谓的标头(在本例中为 p5 格式和可变长度 x 宽)。当你打开你读过的文件时,你会得到 4 行第 1 行。p5; 第二。长x宽;第三个颜色深度和第四个 ascii 代码的长期。我现在的工作是转换这个 ascii,我想我必须知道这个 ascii 的大小。以前,我有一个用于转换 ascii 的 mips 代码,但这里的问题是,此代码仅转换我的 ascii 术语的一部分,如下所示(评论是德语 - 对此感到抱歉):

.data
str:    .ascii "GV_]VTI=97:@JPH<1-/6;L\pz ­¶³¶»ÃËËÄ»°y{xzk`L@@?>9326<DD:1.--++*-./-//000002222344///35;@LVau ¥´¬§»Çĸ³³»ª °¿Åù±¯¦||x{{yttw{sv}¡°¸±¡¡£¢£p_Z[_hfYUW^accacdehhhhdghjjlnnonnnljifjgfdggfdiiiillllglrvtkiltzx~«ÀÖ¿°©´¾ÃÇÈ×ßãÖÇ»º­¡±¼ËÙENSOIHD>;>CHTPB4/+.6<JWizª¯®°¸ÃËËÄ»¶xvj\NECDB<735:?:40//---,+,--./00000222235400259=DNXdw£­®³½Á½³¯¯²¢¥§°»ÃÆõ©«}z{|xtmmqus¡±À¹¦m`ZZ^ce\WZ^abcacdehhhhdghjjlnnonnnlljijhggihhfiiiillmljnuxvnlqw~|¤¶ÐáÕÉÅÇÈÇÉÌÝàÒľ³µª¡¡¤±¼ËÙBGIHB@??DILNRI=1,*-6=ISao §¨­·ÃËËÄ»º¯wpg\SIEDC>83359520110//.--,-//0000022224751139=CGOXfx£®¼¶®¨¤£¥°»À»¾¼³©¥vnjjmsz¬ÅÅƳxxttxuja[Y[_c`^]^abcacdfhhhhdghjjlnnnnnnonkjlkihjjhghhhhkkjknsy}vpqw~¸ÏãéáÝ×ÓÌÁÂÈÙ඲ª¬¥¦¢§ ¡¨±¼ÌÙ@DFKC?=@CFFA<82.+)-6>IO[e| £«´ÅËËļÁ¹­vndbVKACA<632247322321011/.-.//000022225772/4<AFIQYhx¢°½­{¡±½½±²¶´®|lmos¸ÍÌ®tpmjgnnjc[XX[`a`_^abcacdfhjhhdghjjlnoonnnpomknmkjljihggggjjjjsv{wrs}¸ÑãíêÝß×ÏǸ´½ÐÛµ²§¡¨¡ª ¢«²¤¡«±ºÌÙ:ADEA>:5;94268501051"
# it converts just to: GV_]VTI=97:@JPH<1 
        .text
main:


addi $s0, $zero, 0  # $s0 :=0; hier wird das Ergebnis aufsummiert
la $s1,str          # $s1 := &str; hier wird der Zeiger auf das nächste Zeichen gehalten
addi $s2, $zero, 10 # $s2 := 10; hier steht konstand die 10 zur Multiplikaton
addi $s3, $zero, 48 # s3 := 48; hier 48, um die ASCII "0" in den Wert 0 umzuwandeln

loop:
lb $s4,($s1)        # Lade nächstes Zeichen des
sub $s4, $s4, $s3   #Bilde ASCII-Ziffer auf Integer-Wert [0..9] ab
bltz $s4,terminate  # Wenn Zeichen <0,
mult $s0, $s2
mflo $s0            # §s0 := §s0 *10
add $s0, $s0, $s4   # s0= s0 + Ziffernwert
addi $s1, $s1, 1    # s1= s1+1; also auf die nächstes Zeichn im String
j loop

terminate:
li $v0,1            # Resultat ausgeben
or $a0, $zero, $s0  # in ss0 stand das Ergebnis
syscall
li $v0,10
syscall

希望你能给我一个提示。

4

1 回答 1

0

起初我误解了你的问题,但我仍然认为我的回答也是真实答案的一部分,所以首先:

一个问题应该是“如何找到标题的结尾和图像数据的开头”

PGM 标头的最后一个字符是“最大灰度值之后的第一个空白字符”。因此,您必须逐个解析整个标头值,直到解析gray-max,然后下一个字节应该是空格(32(空格),9(TAB),13(CR),10(LF),11(VT),12(FF) ),然后像素数据开始。

恕我直言,这是一种非常愚蠢的格式,因为我敢打赌 DOS 中的某个人在灰度最大值之后确实生成了一些带有“13、10”CR+LF 的图像,但是......不是你的问题(或者在加载到内存后检查你的文件,它读到了什么)。

现在回到你真正的问题......

首先,这些数据不是 ASCII。它们是二进制像素数据。您的“GV”已经是值 71 和 86 的两个像素。当您将其显示为 ASCII 字符串时,当然 71 显示为“G”,但这与任何方式都无关。关于 PGM 的所有“ASCII”都只是标头,在您检测到标头结束后,二进制数据就会涌入。

而这些二进制数据的大小是width*height*bytes_per_pixelBytes_per_pixel为 1 ,在 256..65535 范围内gray_max < 256为 2 。gray_max

当每个像素使用 2 个字节时,最重要的字节是第一个(因此 value4097被编码为 bytes:16, 1并且 value 71 被编码为: 0, 71)。

如果您有一些 0-255 灰度图像,标题中的“最大灰度”设置为 255,那么您只需将文件的剩余(width*height)字节读取为二进制数据(在最后一个标题字符之后),就是这样,这些就是您的像素数据,一行一行,从上到下。

如果 max_gray 是其他值,例如 40 或 15000,那么您是否应该以某种方式将像素数据转换为 0-255 8 位范围(在第一种情况下“放大”它们,在第二次“缩小”中,可能通过一些 gamma如果这想成为专业的 PGM 阅读器,请进行转换)。但我希望你的学校任务只有大约 0-255 张图像,而没有实施伽马校正。

于 2017-01-18T07:12:10.320 回答