| Разработка и ромхакинг > Ромхакинг |
| Софт для ромхакинга |
| << < (2/3) > >> |
| Guyver(X.B.M.):
SeregaZ, у тебя изначально картинка кривая. Попробуй свой аватар этой прогой пропустить - и увидишь 15 цветов. |
| Sharpnull:
SeregaZ, я когда пытался конвертировать картинки в PNG для SGDK, понял что ImaGenesis - дикий мусор (сами видите), XnView и PIL (библиотека для Python) - дают не очень хороший результат, ImageMagick - кажется тоже не устроило, но я до конца не разобрался в настройках, Photoshop - хороший результат, узнать бы алгоритм, чтобы автоматически несколько картинок конвертировать. Кстати, почему-то не нашёл программы для перестановки цветов в палитре в PNG, то есть чтобы менялся порядок, но цвета на изображении оставались на своём месте. В Photoshop'е с перестановкой цветов в палитре всё плохо, вручную если только. Смотрел в программах для пиксель арта, ничего такого нет, либо плохо смотрел. Возможно гуру графики делают это как-то по-другому или потому что это самому пишется легко (в том же PIL). Вообще для Genesis есть настолько мощная графическая программа, что я с ходу не вкурил и забил. -------- Забыл сказать, что хотя у Photoshop хороший результат, при импорте всё равно будет уменьшение диапазона цветов и некоторые могут совпадать, поэтому в идеале нужно самому выстраивать доступную палитру и перерисовывать. |
| SeregaZ:
Guyver(X.B.M.), да, с аватарой вышло лучше. порассматривал результаты: эта программа делает чуть светлее, моя соответственно темнее. плюс еще у себя в настройках функции нашел параметр Dither что-то такое. какая-то зернистость с ним добавляется. отключил во всех импортах изображений, кажется стало более плавнее. Sharpnull, по моему у меня проблем, с изменением нумерации цветов возникнуть недолжно. другое дело, что у меня не графический редактор, а редактор для Дюны с элементами графического редактора... и изображение надо будет перевставить. то есть первая вставка создаст палитру этого изображения. потом меняем нужные цвета... эм... видимо вручную придется, перебивая значения RGB (точнее BGR), и после вставляя изображения со "вписыванием" в существующую палитру. то есть у меня два варианта импорта - со своей палитрой, и со "вписыванием" в существующую. тогда порядок в палитре будет изменен, изображение же сохранится. только номера цветов изменятся в самом изображении. Добавлено позже: и тем не менее вопрос с импортом своей палитры, с условием что два цвета из палитры должны быть не изменяемые - так и висит :) без него не получится правильно сделать импорт изображений для регионов. только если сохранять старую палитру и при вставке "вписывать" новое изображение в эту палитру. |
| Sharpnull:
SeregaZ, вот кстати, Photoshop справа (адаптивные 16 цветов, маджента сама встала первой) и слева как импорт сделал SGDK. Почти как ваш вариант, может деталей чуть больше. -------- Обновил картинку, добавил оригинал справа для сравнения. -------- --- Цитата: SeregaZ от 04 Сентябрь 2018, 20:24:57 ---нашел параметр Dither что-то такое. какая-то зернистость с ним добавляется. --- Конец цитаты --- У вас как раз было с Dither, картинка получается с ним более реалистичная, а без него получается обычная убогая постеризация: |
| Sharpnull:
--- Цитата: SeregaZ от 04 Сентябрь 2018, 16:43:04 ---есть чтоб на выходе было два постоянных цвета и только 7 те цвета, --- Конец цитаты --- В Photoshop и некоторых других программах можно выбрать произвольное количество цветов, вот результат с 7 цветами: Также Photoshop адаптирует цвета картинки при вставке к палитре, если вставляете в индексируемую картинку (Image -> Mode -> Indexed Color), но можно просто экспортировть (File -> Export -> Save for Web) с 9 цветами (+1 для прозрачности, полагаю) и прям там изменить близкие цвета на те 2. Или проблема в импорте именно в вашем редакторе Dune? |
| SeregaZ:
так ежели ужимать до 7 цветов - тот-же самый черный может потеряться, и стать скажем серым цветом. поэтому и хотелось бы подобрать какую-то dll или на худой конец консольную программу, которая могла бы подобное делать. типа назначаешь выходную палитру: 0 цвет фиолетовый, 8 цвет черный. с 1 по 7 программа может как угодно изменять. в моем же случае программа либо как хочет может изменять все цвета, либо ежели я резервирую тот нулевой цвет как фиолетовый - то программа по пастеризации его тупо не использует, создавая второй фиолетовый, по сути выкидывая один цвет. вот надо чтоб программа могла использовать уже заранее подготовленные 2 цвета, которые нельзя изменять, но можно использовать для выходной палитры и потом еще дописывать оставшиеся "динамические" цвета в эти слоты с 1 по 7. несколько сумбурно написал :) но это было бы наиболее верный подход к импорту изображения. можно, конечно, выкрутится вручную подкрашивая элементы на изображении в существующие цвета. например трамп. фиолетовый фон будет прозрачным, но ведь надо его как-то обозначить. и это убьет один из цветов, если я буду импортировать в своем редакторе. получится трамп конвертится в 14, а не в 15 цветов. что можно сделать - взять этого самого трампа, пипеткой взять цвет из галстука - красный. и залить фиолетовый фон красным. после в редакторе залить этот красный на фоне фиолетовым-прозрачным. в итоге потерянный цвет спасен :) (картинки с отключенным Dither - выше он был включен, что придавало зернистости изображению.) но это лишние телодвижения мышкой. хотелось бы чтоб программа сама это все делала. но код там замудреный, я смотрю и вижу фигу. что там происходит без малейшего понятия :) уж тем более теорию цветности я не знаю. в принципе с черным можно сделать точно так-же, но опять таки это ручная работа, что убивает весь мой замысел. хочется однокликовости. |
| Ogr:
--- Цитата: SeregaZ от 04 Сентябрь 2018, 22:01:26 ---хочется однокликовости. --- Конец цитаты --- угу. а еще чтобы кто то твою задумку за тебя тебе реализовал. :lol: |
| SeregaZ:
ну... я не столько программист, сколько менеджер, собирающий в кучу то, что по плану должно быть в этом приложении :) и конца и края пока еще не видно. еще вагон и маленькую тележку ваять... |
| Guyver(X.B.M.):
Ну дык как кто-то должен понять, как работает конвертация в твоём редакторе? Хоть бы участки кода выложил, может, кто-то тебе и помог бы... :neznayu: Или ты там ничего не конвертируешь, а берёшь уже готовую картинку с нужным количеством цветов? |
| SeregaZ:
я беру готовый код, как бы модуль, запиленный юзерами с буржуйского форума для своего горе-языка. и с помощью него импортирую изображение в свой редактор. сам код выкладывать как бы толку мало, ведь он не на популярных языках запилен :) и пока спал - думал. там среди функций есть некая POPULARITY_PALETTE, то есть согласно моему диванно-икспердному мнению там происходит подсчет количества пикселов одного цвета, и тем самым выставляется некий рейтинг цветов чтоль. какого цвета больше - того и тапки. тогда, опять таки согласно моей диванно-икспердной теории, если я заранее, каким-то образом, втолкаю в итоговый результат работы этой функции фиолетовый и черный с очень большим значением этого самого рейтинга, то эти цвета всегда будут на выходе, а сама функция будет подтягивать ближайшие цвета к этим двум, без их изменения. --- Код: ---CompilerIf #PB_Compiler_IsMainFile Enumeration #Pal512 EndEnumeration UsePNGImageDecoder() UseOGGSoundDecoder() ;{ глобальная палитра Global Dim FullPalette.l(513) Dim col.a(8) col(1) = 0 col(2) = 36 col(3) = 72 col(4) = 109 col(5) = 145 col(6) = 181 col(7) = 219 col(8) = 255 x = 0 y = 0 If CreateImage(#Pal512, 256, 32) If StartDrawing(ImageOutput(#Pal512)) For i = 1 To 8 For l = 1 To 8 For k = 1 To 8 Box(x,y,4,4, RGB(col(k),col(l),col(i))) num + 1 FullPalette(num) = RGB(col(k),col(l),col(i)) x + 4 Next x - 32 y + 4 Next x + 32 y - 32 Next StopDrawing() EndIf EndIf ;} ; NearestColor module by Wilbert ; Latest updated : Jan 27, 2016 ; Color distance formula based on: ; http://www.compuphase.com/cmetric.htm ; Dithering method: ; Sierra Lite DeclareModule NearestColor Prototype ProtoProgressCallback(PercentProgress.i) Declare CatchPalette(*MemoryAddress.Long, NumColors.i) Declare CopyPalette(Array DestinationArray.l(1)) Declare.i DitheredImage(Image.i, DitherLevel.a = 220, Brightness.b = 0, Contrast.b = 0, ProgressCallback.ProtoProgressCallback = 0) Declare.l FindNearest(Color.l) Declare.i PaletteColorCount() Declare SetPalette(PaletteImage.i) EndDeclareModule Module NearestColor EnableASM ;EnableExplicit ;DisableDebugger Structure ColorScan l.l[524288] EndStructure Global ColorScan.ColorScan Global Dim IndexG.l(255) Global Dim Palette.l(1) CompilerIf #PB_Compiler_Processor = #PB_Processor_x86 Macro rdx : edx : EndMacro CompilerEndIf Procedure.i PaletteColorCount() ; Return amount of colors the palette contains ProcedureReturn ArraySize(Palette()) - 1 EndProcedure Procedure CopyPalette(Array DestinationArray.l(1)) ; Copy the current palette into a supplied array Protected.i cnt = ArraySize(Palette()) - 1 ReDim DestinationArray(cnt - 1) CopyMemory(@Palette(1), @DestinationArray(0), cnt << 2) EndProcedure Procedure CatchPalette(*MemoryAddress.Long, NumColors.i) ; Catch a palette from memory Protected.i i, j = 1 ReDim Palette(NumColors + 1) Palette(0) = 0 : Palette(NumColors + 1) = 0 For i = 1 To NumColors Palette(i) = $ff000000 | *MemoryAddress\l *MemoryAddress + 4 Next SortStructuredArray(Palette(), 0, 0, #PB_Unicode, 1, NumColors) For i = 0 To 255 IndexG(i) = j While ((Palette(j) >> 8) & $ff) = i And j < NumColors j + 1 Wend IndexG(i) = (IndexG(i) + j) >> 1 Next EndProcedure Procedure SetPalette(PaletteImage.i) ; Set a palette from an image Protected.i i, j, b, x, y, cnt Protected.l c, c_ If StartDrawing(ImageOutput(PaletteImage)) FillMemory(@ColorScan, SizeOf(ColorScan)) j = OutputHeight() - 1 i = OutputWidth() - 1 ; count all used colors For y = 0 To j For x = 0 To i c = Point(x, y) !mov eax, [p.v_c] !rol ax, 8 !bswap eax !shr eax, 8 lea rdx, [nearestcolor.v_ColorScan] bts [rdx], eax !jc nearestcolor.setpalette_cont0 inc cnt !nearestcolor.setpalette_cont0: Next Next StopDrawing() ; redim palette with room at top and bottom for zero entry ReDim Palette(cnt + 1) Palette(0) = 0 : Palette(cnt + 1) = 0 ; set palette sorted on G, R, B and index on G i = 0 : j = 1 For y = 0 To 255 IndexG(y) = j For x = 0 To 2047 b = 0 : c_ = ColorScan\l[i] While c_ shr c_, 1 !jnc nearestcolor.setpalette_cont1 !mov eax, [p.v_i] !shl eax, 5 !or eax, [p.v_b] !shl eax, 8 !or eax, 0xff !bswap eax !rol ax, 8 !mov [p.v_c], eax Palette(j) = c : j + 1 !nearestcolor.setpalette_cont1: b + 1 Wend i + 1 Next IndexG(y) = (IndexG(y) + j) >> 1 Next EndIf EndProcedure Macro M_FindNearest(i, st) !nearestcolor.findnearest#i#_loop: !mov ecx, [p.v_c#i#] !test ecx, ecx !jz nearestcolor.findnearest#i#_cont2 !movzx eax, byte [p.v_Color + 1] !movzx ecx, ch !sub eax, ecx !imul eax, eax !shl eax, 11 !cmp eax, [p.v_bestd] !jnc nearestcolor.findnearest#i#_cont1 !mov [p.v_d], eax !movzx eax, byte [p.v_Color] !movzx ecx, byte [p.v_c#i#] !lea edx, [eax + ecx] ; edx = rsum !sub eax, ecx !imul eax, eax ; eax = r*r !lea ecx, [edx + 0x400] ; ecx = $400 + rsum !imul eax, ecx ; eax = ($400+rsum)*r*r !add [p.v_d], eax !movzx eax, byte [p.v_Color + 2] !movzx ecx, byte [p.v_c#i# + 2] !sub eax, ecx !imul eax, eax ; eax = b*b !neg edx !add edx, 0x5fe ; edx = $5fe - rsum !imul eax, edx ; eax = ($5fe-rsum)*b*b !add eax, [p.v_d] !cmp eax, [p.v_bestd] !jnc nearestcolor.findnearest#i#_cont0 !mov [p.v_bestd], eax !mov eax, [p.v_c#i#] !mov [p.v_c], eax !nearestcolor.findnearest#i#_cont0: mov rdx, *p#i add rdx, st mov *p#i, rdx mov eax, [rdx] !mov [p.v_c#i#], eax CompilerIf i = 1 !jmp nearestcolor.findnearest0_loop CompilerElse !jmp nearestcolor.findnearest1_loop CompilerEndIf !nearestcolor.findnearest#i#_cont1: !mov dword [p.v_c#i#], 0 !nearestcolor.findnearest#i#_cont2: CompilerIf i = 1 !cmp dword [p.v_c0], 0 !jnz nearestcolor.findnearest0_loop CompilerEndIf EndMacro Procedure.l FindNearest(Color.l) ; Find the nearest color Protected.l c, c0, c1, d, bestd = $12000000 Protected.Long *p0, *p1 !movzx eax, byte [p.v_Color + 1] !mov [p.v_d], eax *p1 = @Palette(IndexG(d)) : *p0 = *p1 - 4 c0 = *p0\l : c1 = *p1\l M_FindNearest(0, -4) M_FindNearest(1, 4) ProcedureReturn c EndProcedure Macro M_DitherImage(offset, n = 1) !movsx ecx, byte [p.v_err + offset] !movsx eax, byte [p.v_err50 + offset] !add ecx, eax !imul ecx, edx !sar ecx, 8 !movzx eax, byte [p.v_c0 + offset] !add eax, [p.v_badd] !imul eax, [p.v_cmul] !sar eax, 8 !lea eax, [eax + ecx + 128] !neg ah !setz cl !neg cl !and al, cl !sar ah, 7 !or al, ah !mov [p.v_c0 + offset], al EndMacro Procedure.i DitheredImage(Image.i, DitherLevel.a = 220, Brightness.b = 0, Contrast.b = 0, ProgressCallback.ProtoProgressCallback = 0) ; Return a dithered image ; DitherLevel : 0 - 255 ; Brightness : -128 - 127 ; Contrast : -128 - 127 Protected.i result, x, y, w, h Protected.l c0, c1, badd, cmul, err50, err If ProgressCallback : ProgressCallback(0) : EndIf result = CopyImage(Image, #PB_Any) If result And StartDrawing(ImageOutput(result)) h = OutputHeight() w = OutputWidth() If DitherLevel = 0 And Brightness = 0 And Contrast = 0 While y < h x = 0 While x < w Plot(x, y, FindNearest(Point(x, y))) x + 1 Wend y + 1 If ProgressCallback ProgressCallback(100 * y / h) EndIf Wend Else badd = Brightness - 128 cmul = (33280 * Contrast + 4259840) / (16640 - Contrast << 7) Dim d_error.l(w) While y < h x = 0 : err50 = 0 While x < w c0 = Point(x, y) ; add previous error err = d_error(x) !movzx edx, byte [p.v_DitherLevel] M_DitherImage(0) M_DitherImage(1) M_DitherImage(2) c1 = FindNearest(c0) Plot(x, y, c1) ; calculate 50% error !mov eax, [p.v_c0] !mov ecx, [p.v_c1] !mov edx, eax !not edx !and edx, ecx !and edx, 0x01010101 !or eax, 0x01010101 !and ecx, 0xfefefefe !sub eax, ecx !xor eax, 0x01010101 !shr eax, 1 !sub eax, edx !mov ecx, [p.v_err50] !mov [p.v_err50], eax ; mix with previous error !xor eax, 0x80808080 !xor ecx, 0x80808080 !mov edx, eax !and edx, ecx !and edx, 0x01010101 !and eax, 0xfefefefe !and ecx, 0xfefefefe !add eax, ecx !shr eax, 1 !add eax, edx !xor eax, 0x80808080 !mov [p.v_err], eax d_error(x) = err x + 1 Wend d_error(0) << 1 y + 1 If ProgressCallback ProgressCallback(100 * y / h) EndIf Wend EndIf StopDrawing() EndIf ProcedureReturn result EndProcedure DisableASM DataSection CGAPalette: Data.l $000000, $AA0000, $00AA00, $AAAA00, $0000AA, $AA00AA, $0055AA, $AAAAAA Data.l $555555, $FF5555, $55FF55, $FFFF55, $5555FF, $FF55FF, $55FFFF, $FFFFFF EndDataSection ; Set default palette CatchPalette(?CGAPalette, 16) EndModule CompilerEndIf Structure PopType ; used in POPULARITY_PALETTE() procedure clr.l ; color pop.i ; popularity EndStructure Global Dim WK_Pal.l(0) ; <--- this array will contain the final palette Procedure SCAN_FOR_PALETTE(image.i) ; obtain the palette of all colors used in an image ; stops if number of colors exceeds 512 Static NewMap Pmap.i(1024) Static Dim Palette.l(0) Protected c,i,x,y,Xmax,Ymax Xmax = ImageWidth(image)-1 Ymax = ImageHeight(image)-1 StartDrawing(ImageOutput(image)) For y = 0 To Ymax For x = 0 To Xmax c = Point(x,y) If MapSize(Pmap()) > 512 Break 2 EndIf Pmap(Str(c)) = c Next Next StopDrawing() ReDim palette(MapSize(Pmap())-1) i = 0 ForEach Pmap() palette(i) = Pmap() i + 1 Next ClearMap(Pmap()) ;Debug ArraySize(WK_Pal()) ;For i = 0 To ArraySize(palette());ArraySize(WK_Pal()) ; Debug Str(palette(i)); + " " + Str(WK_Pal(i)) ;Next ;SHOW_PALETTE(Palette()) EndProcedure Procedure ASSEMBLE_TO_PALETTE(Array palette.l(1), ImgRef.i, dither.i) ; assign each pixel of an image to the defined palette using NearestColor module ; ImgRef = the source image ; dither: 0 = no dither, 1 = dither ; A new image is created, the return value is the new image number. NearestColor::CatchPalette(@palette(), ArraySize(palette())+1) ProcedureReturn NearestColor::DitheredImage(ImgRef, dither*128) EndProcedure Procedure COUNT_COLORS(image.i) ; returns the number of unique colors in an image (24 bit) Protected.i x, y, max_x, max_y, c, count, m Dim m.a($1FFFFF) StartDrawing(ImageOutput(image)) max_x = ImageWidth(image) - 1 max_y = ImageHeight(image) - 1 For y = 0 To max_y For x = 0 To max_x c = Point(x, y) & $FFFFFF If m(c >> 3) & 1 << (c & 7) = 0 m(c >> 3) | 1 << (c & 7) count + 1 EndIf Next Next StopDrawing() ProcedureReturn count EndProcedure Procedure POPULARITY_PALETTE(ImgRef.i,limit.i) ; Create a color palette with a modified popularity approach. ; ImgRef = the source image. ; Limit = the maximum number of colors in result. ; Limit count can be specified from 2 to 512. (512 is arbitrary limit) ; Required support procedures are: ; 'COUNT_COLORS', and 'ASSEMBLE_TO_PALETTE'. ; Finished palette is placed in the global array WK_Pal(). ; This algorithm was created by BasicallyPure. Static.i kb = $FF0000, kg = $00FF00, kr = $0000FF Protected.i ImgWork, count, Xmin,Ymin,Xmax, Ymax, i, x, y, lum, d, br, da, mb, md If IsImage(ImgRef) ImgWork = CopyImage(ImgRef,#PB_Any) If ImgWork count = COUNT_COLORS(ImgWork) If count <= limit : limit = count : EndIf Else ProcedureReturn 0 EndIf Else ProcedureReturn 0 EndIf Xmax = ImageWidth(ImgWork) - 1 Ymax = ImageHeight(ImgWork) - 1 ; 1) if color count is > 512 color count will be reduced. ; and palette colors may be altered. If count > 512 ; simple bitmask color reduction method StartDrawing(ImageOutput(ImgWork)) For y = Ymin To yMax For x = Xmin To xMax Plot(x, y, Point(x,y) & $E0E0E0 | $0F0F0F) Next x Next y StopDrawing() EndIf ; 2) gather popularity data NewMap Pmap.i() StartDrawing(ImageOutput(ImgWork)) For y = Ymin To Ymax For x = Xmin To Xmax Pmap(Str(Point(x,y))) + 1 Next Next StopDrawing() If MapSize(Pmap()) < limit : limit = MapSize(Pmap()) : EndIf ; 3) subdivide colors into 4 brightness lists NewList bright.PopType() NewList MedBri.PopType() NewList MedDrk.PopType() NewList dark.PopType() ForEach Pmap() d = Val(MapKey(Pmap())) lum = (d & kr)<<1 + (d & kg) >> 6 + (d & kb) >> 16 If lum > 1338 AddElement(bright()) : bright()\clr = d : bright()\pop = Pmap() ElseIf lum > 892 AddElement(MedBri()) : MedBri()\clr = d : MedBri()\pop = Pmap() ElseIf lum > 446 AddElement(MedDrk()) : MedDrk()\clr = d : MedDrk()\pop = Pmap() Else AddElement(dark()) : dark()\clr = d : dark()\pop = Pmap() EndIf Next ; 4) sort each brightness lists by popularity SortStructuredList(bright(),#PB_Sort_Descending,OffsetOf(PopType\pop),#PB_Integer) SortStructuredList(MedBri(),#PB_Sort_Descending,OffsetOf(PopType\pop),#PB_Integer) SortStructuredList(MedDrk(),#PB_Sort_Descending,OffsetOf(PopType\pop),#PB_Integer) SortStructuredList(dark() ,#PB_Sort_Descending,OffsetOf(PopType\pop),#PB_Integer) ; 5) create the final palette FirstElement(bright()) : br = ListSize(bright()) FirstElement(MedBri()) : mb = ListSize(MedBri()) FirstElement(MedDrk()) : md = ListSize(MedDrk()) FirstElement(dark()) : da = ListSize(dark()) limit - 1 ReDim WK_Pal(limit) i = 0 : d = %00 Repeat ; pick from each list in turn the most popular color If d = %00 And br > 0 WK_Pal(i) = bright()\clr NextElement(bright()) i + 1 : br - 1 ElseIf d = %01 And da > 0 WK_Pal(i) = dark()\clr NextElement(dark()) i + 1 : da - 1 ElseIf d = %10 And mb > 0 WK_Pal(i) = MedBri()\clr NextElement(MedBri()) i + 1 : mb - 1 ElseIf d = %11 And md > 0 WK_Pal(i) = MedDrk()\clr NextElement(MedDrk()) i + 1 : md - 1 EndIf d = (d + %01) & %11 Until i > limit If IsImage(ImgWork) ;CopyImage(ImgWork, ImgRef) FreeImage(ImgWork) EndIf ProcedureReturn 1 EndProcedure Procedure.a ImportImageWithPallete(ImgRef.l, limit, dither.i) ret.a = 0 ; repaint into 512 allow colors NearestColor::CatchPalette(@FullPalette(), 513) CBWidth = ImageWidth(ImgRef) CBHeight = ImageHeight(ImgRef) x = 0 y = 0 If StartDrawing(ImageOutput(ImgRef)) While y < CBHeight x = 0 While x < CBWidth Plot(x, y, NearestColor::FindNearest(Point(x, y))) x + 1 Wend y + 1 Wend StopDrawing() If POPULARITY_PALETTE(ImgRef, limit) ;generate the palette Qimage = ASSEMBLE_TO_PALETTE(WK_Pal(), ImgRef, dither) ;build the final image If IsImage(Qimage) ;ImageGadget(#PB_Any,0,0,w,h,ImageID(Qimage)) ;display the result SCAN_FOR_PALETTE(Qimage) ; show the palette in a separate window If IsImage(ImgRef) FreeImage(ImgRef) EndIf CopyImage(Qimage, ImgRef) FreeImage(Qimage) ret = 1 EndIf EndIf EndIf ProcedureReturn ret EndProcedure CompilerIf #PB_Compiler_IsMainFile GetClipboardImage(ImgRef, 32) ImportImageWithPallete(ImgRef, 14, #True) SaveImage(ImgRef, "D:\test.png") ;For i = 0 To ArraySize(WK_Pal()) ; Debug WK_Pal(i) ;Next CompilerEndIf --- Конец кода --- |
| Guyver(X.B.M.):
Да, код просто монстрический. Я попробовал ради прикола один из алгоритмов реализовать, но у меня картинка сильно тёмная получается. И даже если осветлить её - цвета на оригинальные не всегда похожи... Хотя сам алгоритм похож на твой, с выборкой... П.С. Опять нас ждёт хак "Трамп против @#тина"? |
| SeregaZ:
не :) просто более менее фотография Трампа попалась с нужным освещением, чтоб похожа, как освещение ментатов в дюне. а так у него глаза плохие - щелочки. анимацию рисовать для моргания глаз будет не удобно. оригинальные ментаты то с большими глазами, видно как зрачок влево-вправо двигается. а тут-же ничерта невидать :) сам код из трех частей - моя криворукая часть, в том месте где я создаю палитру, как на приставке из 512 цветов. после там код с асм вставками - это другого товарища, который растаскивает цвета на изображении к ближайшим разрешенным из 512. третья часть уже сам код пастеризации второго товарища, с уменьшением количества цветов. вот видимо монструазность в виду подключения этого некоего фильтра или как он по научному - Dither. я думаю что с включенным этим Dither как-то квадратично. без него более плавно, а Sharpnull наоборот пишет что с Dither лучше. по поводу яркости что-то я не знаю а будут ли соответствовать цвета, после такого изменения яркости тем, что разрешены? в смысле сеговские 512? |
| Guyver(X.B.M.):
Будут соответствовать, если изменение яркости происходит в пределах этих цветов разрешённых. У тебя в результате палитра получается отдельным файлом? В бмп 16 цветов же не включается палитра, да? Имхо, Dither - это вообще шляпа. Никогда не использую в своих работах и стараюсь избавляться от этого шакального эффекта в изображениях... |
| SeregaZ:
палитру выковыривает из bmp изображения. а дальше можно поступить как угодно. в данном коде не сохраняет. там для себя выводил лист получившейся палитры: --- Код: ---;For i = 0 To ArraySize(WK_Pal()) ; Debug WK_Pal(i) ;Next --- Конец кода --- сохранение у меня в других местах :) не в этом коде. там где сохраняются регионы, где ментаты, где экраны и где большие иконки. там цвет надо перевернуть, так сказать, и потом сохранять. для переворачивания сделал что-то типа такого: --- Код: ---Procedure.a Parse1Color(inp.a, pbtosmd.a=0) out.a If pbtosmd = 0 Select inp Case 0 out = 0 Case 2 out = 36 Case 4 out = 72 Case 6 out = 109 Case 8 out = 145 Case $A out = 181 Case $C out = 219 Case $E out = 255 EndSelect Else Select inp Case 0 out = 0 Case 36 out = 2 Case 72 out = 4 Case 109 out = 6 Case 145 out = 8 Case 181 out = $A Case 219 out = $C Case 255 out = $E EndSelect EndIf ProcedureReturn out EndProcedure Procedure.l Parse3Color(inp.u) out.l r = GetBits(inp, 0, 3) ;: Debug Hex(b) g = GetBits(inp, 4, 7) ;: Debug Hex(g) b = GetBits(inp, 8, 11) ;: Debug Hex(r) out = RGB(Parse1Color(r), Parse1Color(g), Parse1Color(b)) ProcedureReturn out EndProcedure --- Конец кода --- хотя это чтение. ну сохранение примерно так-же, то есть полученный RGB конвертируется в значение, как оно в файлах палитры идет двухбайтовое... эээ... BGR? хотя насчет таблицы значений я в последнее время не уверен. цвета то похожи, но где-то в соседней теме видел чуть чуть другие значения, то есть числа рядышком, но все-таки другие. ну мне колхознику пойдет :) Добавлено позже: и у меня вроде что-то получается :) насильно засунул фиолетовый в просчитываемые цвета и в результате он всегда есть в выходной палитре, независимо от того, есть ли он на изображении или нет. теперь надо сделать вилку, даже тройник. три варианта развития событий - как есть, учитывать фиолетовый есть или нету на изображении, учитывать черный есть или нету на изображении. и то, причем не фиолетовый, а любой какой укажешь. доволен как слон :) НО! спасти красный цвет так и не получилось. слишком мало места красным цветом на Трампе покрашено и в результате у красного маленький рейтинг. не смотря что он ярче, так сказать, в палитру в итоге вошел более блеклый какой-то цвет, просто у него был лучше рейтинг. |
| Sharpnull:
--- Цитата: Guyver(X.B.M.) от 05 Сентябрь 2018, 14:46:00 ---Имхо, Dither - это вообще шляпа. Никогда не использую в своих работах и стараюсь избавляться от этого шакального эффекта в изображениях... --- Конец цитаты --- Не знал, что такие люди бывают. Как же вы играете в игры для ретроконсолей, там же повсеместно используется Dither, невозможно ограничить цвета и чтобы выглядело хорошо без этого (для объёмных изображений, пихать везде очевидно нет смысла). SeregaZ, я бы на вашем месте не возился из-за одного цвета, а почему с маджентой проблемы не понял, в хорошем алгоритме можно задать что считать прозрачностью и он не должен считать его цветом, а просто отметить отдельным индексом. Если вы управляете "популярностью", то можно занижать мадженту (цвет прозрачности) до минимуму, чтобы никогда не попадал в палитру (так в конвертерах и происходит), и после обработки тупо в те пиксели вставить индекс прозрачного цвета. (UPD: Глупость сморозил, можно же просто игнорить пиксели с прозрачностью.) Хотя наверно я неправильно понял и вам именно маджента и нужна в итоге... Галстук никогда не будет таким, какой вы хотите. Выход из конвертера нельзя назвать пиксель артом, потому что пиксель арт - это когда художник ставит в определённое место определённый цвет. Я к тому, что красиво автоматом не получится. -------- И опять же пастеризуют молоко, а картинки постеризуют. |
| SeregaZ:
ну вот... неожиданно развязал холивар :) этот код не различает прозрачный или нет. ему подавай количество выходных цветов и все на этом. поэтому я и делал не в 16, а в 15 цветов постеризацию (гугель хрому не нравится через о), всегда резервируя 0 цвет как фиолетовый. однако если в изображении был фиолетовый - в итоговой палитре оказывалось два фиолетовых. то есть 1 цвет терялся. теперь же, добавив обязательное наличие в выходной палитре фиолетового, я могу делать в 16 цветов. просто в конце нужна будет сортировка палитры, чтоб сдвигать фиолетовый (либо какой другой цвет) на 0 номер. этот же трюк буду проворачивать и с регионами - добавляя обязательно черный, независимо от его наличия на изображении. он должен быть под 15 номером. 0 фиолетовый, 1-7 постеризация может изменять, 8-14 опять фиолетовый, а вобще пустые не используемые и 15 черный. |
| SeregaZ:
добавил в опциях галку для этого самого Dither и во всех четырех местах, где у меня импорт добавил эту переменную. --- Код: ---CheckBoxGadget(#OptionsDither, x, y, 915, 20, "Use Dither for import images | Использовать Dither для импорта изображений") --- Конец кода --- ну и... пофиксил глаза для Трампа :))))) |
| morskoyzmey:
Не знаю, актуален ли заголовок топика, но внесу свои 5 копеек. HxD Удобный хекс редактор. Есть кодировки, сравнение файлов, чек сумма, настраиваемая тема. Русский язык можно найти в гугле. https://mh-nexus.de/en/hxd/ famiROM Удобный сплиттер ROM файлов (NES-> PRG BIN, CHR BIN). Сам обрезает iNES, наращивает до нужных размеров. Один клик и можно прошивать флешку. Также есть и редактор заголовка, и еще куча всего, чего я пока не понимаю. Ветка автора: http://nintendoage.com/forum/messageview.cfm?catid=22&threadid=63070 DISASM6 Хороший дизассемблер. Работает с CDL файлами статистики Code/Data Logger эмулятора FCEUX. Красиво оформляет код для ASM6. https://forums.nesdev.com/viewtopic.php?t=7466 Извините, если это очевидные тулзы, но мало ли кому пригодится. |
| Omkommersind:
Эмулятор FCE220 имеет потрясающий набор встроенных инструментов для интерактивной отладки, есть ли какие-нибудь схожие аналоги для ромов SMD/Genesis? |
| MetalliC:
Omkommersind, вагон - Exodus, Gens Kmod, RegenD или Smd IDA Tools |
| Навигация |
| Главная страница сообщений |
| Следующая страница |
| Предыдущая страница |