PNG Tileset Splitter and more

Started by Hardcoal, January 08, 2021, 06:40:21

Previous topic - Next topic

Hardcoal

some app I made and decided to share..
It has various things.. I experiment with

one of the is a hidden image within image experiment Ive made..
I wondered if I could make it work.. and Ive managed to do so..

Feel Free to Take a look

[Download] https://hardcoal.itch.io/pngtilesetsplitter-and-more



The funny thing is that somehow it got into softpedia.. i guess from itch.io that i posted it there.. a year ago or so

https://www.softpedia.com/get/Multimedia/Graphic/Graphic-Editors/Png-Tile-Splitter.shtml




Code

Matty

You've actually shared that hidden image thing before...

Hardcoal

i was looking for this post. didnt find it. so i assumed i didnt.
anyway ive added some stuff..  ::)
Code


GrindalfGames

Thats really interesting, How does it work?

Hardcoal

thanks matty..

grindalf you mean how do i split the tiles?
If so... it looks for islands of pixles around usig the png empty parts..

Ive stopped messing with it because ive achieved my main goal back than.

but I have more ideas to add to this App.. when time comes



Code

GrindalfGames

I mean hiding an image in an image

Hardcoal

ahhh.. i took the last 4 bits of each pixel color .. and used it to store the hidden image values with 16 degrees of levels..

the visible picture is not effected too much.

it was a pretty complex thing but it worked..
its not as easy as it may appear
Code

GrindalfGames

Thats pretty genius, I would never have thought of that

RemiD

quite clever indeed, congrats  :)


this made me think of hidden messages / images in ancient books, where some letters were made with many tiny dots, and with normal eyes you only see the normal text, but if you use a magnifier with enough zoom, you can read the tiny message / image in a letter.

Hardcoal

#10
Thanks..

Im gonna Add a hidden message in image thing to this App..
on same principle.. thought its been done before

also here is the code.. if anyone interested

'Need to add code to indicate hidden image

Type ImageHider_Type

Field FirstImage  'Also Reduced Image
Field SecondImage
Field HiddenImage
Field CombinedImage
    Field Pixel[,]

Field LoadHiddenImage_bt = alCreateGButton(Roller_Area, "LoadSecondImage", 50, -3, 130, 30)
Field ExtractImage_bt = alCreateGButton(Roller_Area, "ExtractImage", 180, -3, 100, 30)

Field Colored_cb = alCreateGToggleButton(rightpanel_win, "Colored Output", 5, 5, 140, 25, 0, "CheckBox")

Method New()
alHide(LoadHiddenImage_bt)
End Method

Method Play()

   'Load First Image
If alTestClick(Load_bt) Or DraggedURL <> "" Then
    Local TmpHandle, WantedURL:String

If DraggedURL <> "" Then
WantedURL = DraggedURL
DraggedURL = ""
Else
WantedURL = RequestFile("Choose Image",,, AppURL + "ExampleMedia/")
End If

If WantedURL <> "" Then TmpHandle = xLoadImage(WantedURL)

If TmpHandle > 0 Then
If FirstImage > 0 Then xFreeImage(FirstImage)
xResizeImage(TmpHandle, CanvasWidth / 2, CanvasHeight / 2)  'For Display Only
FirstImage = TmpHandle
SlightlyReduceImageColors_General(FirstImage)  'Essential
alShow(LoadHiddenImage_bt)
ConsoleMessage("Image One Loaded")
End If

End If

   'Load Second Image
    If alTestClick(LoadHiddenImage_bt) Then
Local TmpHandle
Local WantedURL:String = RequestFile("Choose Image",,, AppURL + "ExampleMedia/")
If WantedURL <> "" Then TmpHandle = xLoadImage(WantedURL)
If TmpHandle > 0 Then

If SecondImage > 0 Then xFreeImage(SecondImage)
    SecondImage = RealResizeImage(TmpHandle, xImageWidth(FirstImage), xImageHeight(FirstImage))
xSaveImage(SecondImage, "TmpImage.png")
xFreeImage(SecondImage)
SecondImage = xLoadImage("TmpImage.png")
xDeleteFile("TmpImage.png")

xResizeImage(SecondImage, CanvasWidth / 2, CanvasHeight / 2) 'For Display Only

alShow(Execute_bt)
alSetText(Execute_bt, "Process")
End If
End If
   
   'Process
If alTestClick(Execute_bt) Then
If FirstImage > 0 Then

   'Gray
If alGetValueI(Colored_cb) = 0 Then
   HiddenImage = CreateSecondImage_Gray(SecondImage)  'For Display Use
   BuildImageIndex_Gray(SecondImage)
   'Colored
Else
HiddenImage = CreateSecondImage_Colored(SecondImage) 'For Display Use
BuildImageIndex_Colored(SecondImage)
End If

MergeImages()

If CombinedImage > 0 Then
ClearConsol()
alShow(ForceStop_bt)
xResizeImage(CombinedImage, CanvasWidth / 2, CanvasHeight / 2)   'For Display Only
xSaveImage(CombinedImage, AppURL + Output_URL + "HiddenImage.bmp")
OpenURL(Output_URL)
End If
    If HiddenImage > 0 Then xResizeImage(HiddenImage, CanvasWidth / 2, CanvasHeight / 2)    'For Display Only
alHide(ForceStop_bt)
ConsoleMessage("Process Done. Image Name HiddenImage.bmp")
End If
End If
 
   'Extract Hidden Image
If alTestClick(ExtractImage_bt) Or DraggedURL <> "" Then
Local TmpHandle, WantedURL:String

If DraggedURL <> "" Then
WantedURL = DraggedURL
DraggedURL = ""
Else
WantedURL = RequestFile("Choose Image",,, AppURL + "Output/")
End If

If WantedURL <> "" Then TmpHandle = xLoadImage(WantedURL)
If TmpHandle > 0 Then
Local NewImage

   'Gray
If alGetValueI(Colored_cb) = 0 Then
NewImage = ExtractHiddenImage_Gray(TmpHandle)
   'Colored
Else
NewImage = ExtractHiddenImage_Colored(TmpHandle)
End If

xSaveImage(NewImage, AppURL + Output_URL + "ExtractedImage.Jpg")
OpenURL(Output_URL)
ConsoleMessage("Process Done. Extracted ImageName: ExtractedImage.Jpg")

End If
End If

End Method

Method Prepare()
alSetValueI(Colored_cb, Left(EditorState_Text, 2).ToInt())
End Method

'----------------------------------------------------------------'

   'Merge the two images..  'should be good for both gray and color
Method MergeImages()
Local X, Y
    CombinedImage = xCreateImage(xImageWidth(FirstImage), xImageHeight(FirstImage))
xLockBuffer(xImageBuffer(CombinedImage))
For Y = 0 To xImageHeight(CombinedImage) - 1
For X = 0 To xImageWidth(CombinedImage) - 1
Local Pxl = xReadPixelfast(X, Y, xImageBuffer(FirstImage))
Local NewPix = Pxl | pixel[x, y]
xWritePixelFast(X, Y, NewPix, xImageBuffer(CombinedImage))
Next
Next
xUnlockBuffer(xImageBuffer(CombinedImage))
End Method

   'SlightlyReduceImageColors_General 
Method SlightlyReduceImageColors_General(ImageHandle)
Local X, Y
xLockBuffer(xImageBuffer(ImageHandle))
For Y = 0 To xImageHeight(ImageHandle) - 1
For X = 0 To xImageWidth(ImageHandle) - 1
Local Pixel = xReadPixel(X, Y, xImageBuffer(ImageHandle))

   'Gray
If alGetValueI(Colored_cb) = 0 Then
xWritePixelFast(X, Y, Remove4LastBitsFromPixel_Gray(Pixel), xImageBuffer(ImageHandle))
   'Colored
Else
xWritePixelFast(X, Y, Remove4LastBitsFromPixel_Colored(Pixel), xImageBuffer(ImageHandle))
End If

Next
Next
xUnlockBuffer(xImageBuffer(ImageHandle))
End Method

   'CreateSecondImage_Gray  'For Display Only
Method CreateSecondImage_Gray(ImageHandle)
Local X, Y
Local TargetImage = xCreateImage(xImageWidth(ImageHandle), xImageHeight(ImageHandle))
xLockBuffer(xImageBuffer(TargetImage))
For Y = 0 To xImageHeight(ImageHandle) - 1
For X = 0 To xImageWidth(ImageHandle) - 1
Local Pixel = xReadPixel(X, Y, xImageBuffer(ImageHandle))
xWritePixelFast(X, Y, GrayPixel(Pixel), xImageBuffer(TargetImage))  'GrayPixel
Next
Next
xUnlockBuffer(xImageBuffer(TargetImage))
Return TargetImage
End Method

Method CreateSecondImage_Colored(ImageHandle)
Local X, Y
Local TargetImage = xCreateImage(xImageWidth(ImageHandle), xImageHeight(ImageHandle))
xLockBuffer(xImageBuffer(TargetImage))
For Y = 0 To xImageHeight(ImageHandle) - 1
For X = 0 To xImageWidth(ImageHandle) - 1
Local Pixel = xReadPixel(X, Y, xImageBuffer(ImageHandle))
xWritePixelFast(X, Y, Remove4LastBitsFromPixel_Colored(Pixel), xImageBuffer(TargetImage))
Next
Next
xUnlockBuffer(xImageBuffer(TargetImage))
Return TargetImage
End Method

'----------------------------------------------------------------------'


'-----------------------ExtractHiddenImage_Gray----------------------------'

Method ExtractHiddenImage_Gray(Imagehandle)
Local NewImage = xCreateImage(xImageWidth(ImageHandle), xImageHeight(ImageHandle)), x, y, Pxl, Gray
xLockBuffer(xImageBuffer(NewImage))
For Y = 0 To xImageHeight(ImageHandle) - 1
For X = 0 To xImageWidth(ImageHandle) - 1
Pxl = xReadPixel(x, y, xImageBuffer(Imagehandle))
Gray = Pxl & %00000000000000000000000000001111
Pxl = GetGrayLevel_Int(Gray)
    Pxl = Pxl | %11111111000000000000000000000000
    xWritePixelFast(x, y, Pxl, xImageBuffer(NewImage))
TimedUpdateGraphics()
Next
Next
xUnlockBuffer(xImageBuffer(NewImage))
Return NewImage
End Method

'-----------------------ExtractHiddenImage_Colored----------------------------'

Method ExtractHiddenImage_Colored(Imagehandle)
Local NewImage = xCreateImage(xImageWidth(ImageHandle), xImageHeight(ImageHandle)), x, y, Pxl
xLockBuffer(xImageBuffer(NewImage))
For Y = 0 To xImageHeight(ImageHandle) - 1
For X = 0 To xImageWidth(ImageHandle) - 1
Pxl = xReadPixel(x, y, xImageBuffer(Imagehandle))
Pxl = GetColorLevel_Colored(Pxl)
    Pxl = Pxl | %11111111000000000000000000000000  'Make Alpha Full
    xWritePixelFast(x, y, Pxl, xImageBuffer(NewImage))
Next
Next
xUnlockBuffer(xImageBuffer(NewImage))
Return NewImage
End Method

  '----------------BuildImageGraysIndex_Gray---------------------------'

Method BuildImageIndex_Gray(ImageHandle)  'leave it in For now
Local X, Y
Pixel = Null
Pixel = New Int[xImageWidth(ImageHandle) + 1, xImageHeight(ImageHandle) + 1]
xLockBuffer(xImageBuffer(ImageHandle))
For Y = 0 To xImageHeight(ImageHandle) - 1
For X = 0 To xImageWidth(ImageHandle) - 1
Local Pxl = xReadPixelfast(X, Y, xImageBuffer(ImageHandle))
Pixel[X, Y] = DecideColorLevel_Gray(Pxl)
Next
Next
xUnlockBuffer(xImageBuffer(ImageHandle))
End Method

  '----------------BuildImageGraysIndex_Colored---------------------------'

Method BuildImageIndex_Colored(ImageHandle)
Local X, Y
Pixel = Null
Pixel = New Int[xImageWidth(ImageHandle) + 1, xImageHeight(ImageHandle) + 1]
xLockBuffer(xImageBuffer(ImageHandle))
For Y = 0 To xImageHeight(ImageHandle) - 1
For X = 0 To xImageWidth(ImageHandle) - 1
Local Pxl = xReadPixelfast(X, Y, xImageBuffer(ImageHandle))
Pixel[X, Y] = DecideColorLevel_Colored(Pxl)
Next
Next
xUnlockBuffer(xImageBuffer(ImageHandle))
End Method

End Type

'-------------Gray HiderMode-----------------------'

Function DecideColorLevel_Gray(Pixel)
Local PixelWithoutAlpha
PixelWithoutAlpha = Pixel & %00000000111111111111111111111111
Return GetColorValue_Gray(PixelWithoutAlpha)
End Function

Function Remove4LastBitsFromPixel_Gray(Pixel)  'Remove 4 Last Bits From Pixel before merge
Local KeepAlpha
KeepAlpha = Pixel & %11111111000000000000000000000000
Pixel = Pixel & %00000000111111111111111111110000
Return Pixel | KeepAlpha
End Function

Function GrayPixel(Pixel) ' i think it decrease image
Local PixelWithoutAlpha, KeepAlpha
KeepAlpha = Pixel & %11111111000000000000000000000000
PixelWithoutAlpha = Pixel & %00000000111111111111111111110000
Pixel = Get10GrayLevelFromSourceImage(PixelWithoutAlpha)
Return Pixel | KeepAlpha
End Function

Function GetColorValue_Gray(Value)  'For Creating Gray Levels Before Merge
Select True
Case Value = PNGEmptySpace_Value
Return 10
Case Value < %110010001100100011001
Return 0
Case Value < %1100100011001000110010
Return 1
Case Value < %10011000100110001001100
Return 2
Case Value < %11001100110011001100110
Return 3
Case Value < %100000001000000010000000
Return 4
Case Value < %100110011001100110011001
Return 5
Case Value < %101100111011001110110011
Return 6
Case Value < %110011001100110011001100
Return 7
Case Value < %111001101110011011100110
Return 8
Case Value <= %111111111111111111111111
Return 9
End Select
End Function

Function Get10GrayLevelFromSourceImage(Value)  'For Creating Gray Image for display
Select True
Case Value = PNGEmptySpace_Value
Return PNGEmptySpace_Value
Case Value < %110010001100100011001
Return %000000000000000000000000
Case Value < %1100100011001000110010
Return %110010001100100011001
Case Value < %10011000100110001001100
Return %1100100011001000110010
Case Value < %11001100110011001100110
Return %10011000100110001001100
Case Value < %100000001000000010000000
Return %11001100110011001100110
Case Value < %100110011001100110011001
Return %100000001000000010000000
Case Value < %101100111011001110110011
Return %100110011001100110011001
Case Value < %110011001100110011001100
Return %101100111011001110110011
Case Value < %111001101110011011100110
Return %110011001100110011001100
Case Value <= %111111111111111111111111
Return %111111111111111111111111
End Select
End Function

Function GetGrayLevel_Int(Value)  'For Creating Gray Image after extraction
Select Value
Case 0
Return %110010001100100011001
Case 1
Return %1100100011001000110010
Case 2
Return %10011000100110001001100
Case 3
Return %11001100110011001100110
Case 4
Return %100000001000000010000000
Case 5
Return %100110011001100110011001
Case 6
Return %101100111011001110110011
Case 7
Return %110011001100110011001100
Case 8
Return %111001101110011011100110
Case 9
Return %111111111111111111111111
Case 10
Return PNGEmptySpace_Value
End Select
End Function

'-------------------------------Color HiderMode -------------------------------------'

Function Remove4LastBitsFromPixel_Colored(Pixel)
Local KeepAlpha
KeepAlpha = Pixel & %11111111000000000000000000000000
Pixel = Pixel & %00000000111100001111000011110000
Return Pixel | KeepAlpha
End Function

Function DecideColorLevel_Colored(Pixel)
Local Red, Green, Blue

Red = (Pixel Shr 16) & %00000000000000000000000011111111
Green = (Pixel Shr 8) & %00000000000000000000000011111111
Blue = Pixel & %00000000000000000000000011111111

Red = GetColorValue_Colored(Red)
Green = GetColorValue_Colored(Green)
Blue = GetColorValue_Colored(Blue)

red = red Shl 16
Green = Green Shl 8

Return Red | Green | Blue
End Function

Function GetColorValue_Colored(Value)  'For Creating Gray Levels Before Merge
Select True
Case Value < 28
Return 0
Case Value < 56
Return 1
Case Value < 84
Return 2
Case Value < 112
Return 3
Case Value < 140
Return 4
Case Value < 168
Return 5
Case Value < 196
Return 6
Case Value < 224
Return 7
Case Value < 232
Return 8
Case Value < 255
Return 9
Case Value = 255
Return 10
End Select
End Function

Function GetColorLevel_Colored(Pixel)  'For Creating Gray Image after extraction 
Local Red, Green, Blue

Red = Pixel & %00000000000011110000000000000000
Green = Pixel & %00000000000000000000111100000000
Blue = Pixel & %00000000000000000000000000001111

red = red Shr 16  'Must be Seperate!
Green = Green Shr 8

Select Red
Case 0
Red = 0
Case 1
Red = 28
Case 2
Red = 56
Case 3
Red = 84
Case 4
Red = 112
Case 5
Red = 140
Case 6
Red = 168
Case 7
Red = 196
Case 8
Red = 224
Case 9
Red = 232
Case 10
Red = 255
End Select

Select Green
Case 0
Green = 0
Case 1
Green = 28
Case 2
Green = 56
Case 3
Green = 84
Case 4
Green = 112
Case 5
Green = 140
Case 6
Green = 168
Case 7
Green = 196
Case 8
Green = 224
Case 9
Green = 232
Case 10
Green = 255
End Select

Select Blue
Case 0
Blue = 0
Case 1
Blue = 28
Case 2
Blue = 56
Case 3
Blue = 84
Case 4
Blue = 112
Case 5
Blue = 140
Case 6
Blue = 168
Case 7
Blue = 196
Case 8
Blue = 224
Case 9
Blue = 232
Case 10
Blue = 255
End Select

Red = Red Shl 16
Green = Green Shl 8

Return (Red | Green | Blue)
End Function


'--------------------------------------------------'

'So The Alpha of a Png is the Left 8 bits
'Pixel | %11111111000000000000000000000000   'This keeps PNG as it Is
'Pixel | %00000000000000000000000000000000   'This makes png have white background
'Pixel & %11111111111111111111111111111111   'this also makes png appear as it is


' 00000000
' 11111111
' 11010011
'%11111111111111111111111111111111
Code

Matty

There's an out of print chemical engineering book I once had called Transport Phenomena which had a dedication hidden in the preface.  If you took the first capital letter in each sentence you found a message "This book is dedicated to O.H.Haugen" (I might have the name wrong a bit. .it's from memory)

Hardcoal

#12
Thats a good idea.. making an app that is dedicated to hiding stuff in various ways
Code

Matty

#13
Well here is a simple method.
Take your previous post,convert it to bytes.
Take the post before it, convert to bytes and keep only the same length as the first.
Xor each byte of the two messages to produce a long string of junk.
Now...if you xor the bytes in the junk message with either of the other two you will get back the alternate message


Now....there's  a saying that not all those who wander are lost.   Well not all junk data is junk....

Hardcoal

#14
whatever.. I dont know what you want Matty..

Code